xref: /petsc/src/mat/interface/matrix.c (revision f0b74427b291237450348b8514d67555ad08bce6)
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 $ -viewer_type {binary, hdf5}
1329 
1330   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1331   and src/mat/tutorials/ex10.c with the second approach.
1332 
1333   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1334   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1335   Multiple objects, both matrices and vectors, can be stored within the same file.
1336   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1337 
1338   Most users should not need to know the details of the binary storage
1339   format, since `MatLoad()` and `MatView()` completely hide these details.
1340   But for anyone who is interested, the standard binary matrix storage
1341   format is
1342 
1343 .vb
1344     PetscInt    MAT_FILE_CLASSID
1345     PetscInt    number of rows
1346     PetscInt    number of columns
1347     PetscInt    total number of nonzeros
1348     PetscInt    *number nonzeros in each row
1349     PetscInt    *column indices of all nonzeros (starting index is zero)
1350     PetscScalar *values of all nonzeros
1351 .ve
1352   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1353   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
1354   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1355 
1356   PETSc automatically does the byte swapping for
1357   machines that store the bytes reversed. Thus if you write your own binary
1358   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1359   and `PetscBinaryWrite()` to see how this may be done.
1360 
1361   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1362   Each processor's chunk is loaded independently by its owning MPI process.
1363   Multiple objects, both matrices and vectors, can be stored within the same file.
1364   They are looked up by their PetscObject name.
1365 
1366   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1367   by default the same structure and naming of the AIJ arrays and column count
1368   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1369 $    save example.mat A b -v7.3
1370   can be directly read by this routine (see Reference 1 for details).
1371 
1372   Depending on your MATLAB version, this format might be a default,
1373   otherwise you can set it as default in Preferences.
1374 
1375   Unless -nocompression flag is used to save the file in MATLAB,
1376   PETSc must be configured with ZLIB package.
1377 
1378   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1379 
1380   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1381 
1382   Corresponding `MatView()` is not yet implemented.
1383 
1384   The loaded matrix is actually a transpose of the original one in MATLAB,
1385   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1386   With this format, matrix is automatically transposed by PETSc,
1387   unless the matrix is marked as SPD or symmetric
1388   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1389 
1390   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1391 
1392 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1393  @*/
1394 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1395 {
1396   PetscBool flg;
1397 
1398   PetscFunctionBegin;
1399   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1400   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1401 
1402   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1403 
1404   flg = PETSC_FALSE;
1405   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1406   if (flg) {
1407     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1408     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1409   }
1410   flg = PETSC_FALSE;
1411   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1412   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1413 
1414   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1415   PetscUseTypeMethod(mat, load, viewer);
1416   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1417   PetscFunctionReturn(PETSC_SUCCESS);
1418 }
1419 
1420 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1421 {
1422   Mat_Redundant *redund = *redundant;
1423 
1424   PetscFunctionBegin;
1425   if (redund) {
1426     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1427       PetscCall(ISDestroy(&redund->isrow));
1428       PetscCall(ISDestroy(&redund->iscol));
1429       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1430     } else {
1431       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1432       PetscCall(PetscFree(redund->sbuf_j));
1433       PetscCall(PetscFree(redund->sbuf_a));
1434       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1435         PetscCall(PetscFree(redund->rbuf_j[i]));
1436         PetscCall(PetscFree(redund->rbuf_a[i]));
1437       }
1438       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1439     }
1440 
1441     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1442     PetscCall(PetscFree(redund));
1443   }
1444   PetscFunctionReturn(PETSC_SUCCESS);
1445 }
1446 
1447 /*@
1448   MatDestroy - Frees space taken by a matrix.
1449 
1450   Collective
1451 
1452   Input Parameter:
1453 . A - the matrix
1454 
1455   Level: beginner
1456 
1457   Developer Note:
1458   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1459   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1460   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1461   if changes are needed here.
1462 
1463 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1464 @*/
1465 PetscErrorCode MatDestroy(Mat *A)
1466 {
1467   PetscFunctionBegin;
1468   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1469   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1470   if (--((PetscObject)*A)->refct > 0) {
1471     *A = NULL;
1472     PetscFunctionReturn(PETSC_SUCCESS);
1473   }
1474 
1475   /* if memory was published with SAWs then destroy it */
1476   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1477   PetscTryTypeMethod(*A, destroy);
1478 
1479   PetscCall(PetscFree((*A)->factorprefix));
1480   PetscCall(PetscFree((*A)->defaultvectype));
1481   PetscCall(PetscFree((*A)->defaultrandtype));
1482   PetscCall(PetscFree((*A)->bsizes));
1483   PetscCall(PetscFree((*A)->solvertype));
1484   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1485   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1486   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1487   PetscCall(MatProductClear(*A));
1488   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1489   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1490   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1491   PetscCall(MatDestroy(&(*A)->schur));
1492   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1493   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1494   PetscCall(PetscHeaderDestroy(A));
1495   PetscFunctionReturn(PETSC_SUCCESS);
1496 }
1497 
1498 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1499 /*@
1500   MatSetValues - Inserts or adds a block of values into a matrix.
1501   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1502   MUST be called after all calls to `MatSetValues()` have been completed.
1503 
1504   Not Collective
1505 
1506   Input Parameters:
1507 + mat  - the matrix
1508 . v    - a logically two-dimensional array of values
1509 . m    - the number of rows
1510 . idxm - the global indices of the rows
1511 . n    - the number of columns
1512 . idxn - the global indices of the columns
1513 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1514 
1515   Level: beginner
1516 
1517   Notes:
1518   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1519 
1520   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1521   options cannot be mixed without intervening calls to the assembly
1522   routines.
1523 
1524   `MatSetValues()` uses 0-based row and column numbers in Fortran
1525   as well as in C.
1526 
1527   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1528   simply ignored. This allows easily inserting element stiffness matrices
1529   with homogeneous Dirichlet boundary conditions that you don't want represented
1530   in the matrix.
1531 
1532   Efficiency Alert:
1533   The routine `MatSetValuesBlocked()` may offer much better efficiency
1534   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1535 
1536   Fortran Notes:
1537   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1538 .vb
1539   call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
1540 .ve
1541 
1542   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1543 
1544   Developer Note:
1545   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1546   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1547 
1548 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1549           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1550 @*/
1551 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1552 {
1553   PetscFunctionBeginHot;
1554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1555   PetscValidType(mat, 1);
1556   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1557   PetscAssertPointer(idxm, 3);
1558   PetscAssertPointer(idxn, 5);
1559   MatCheckPreallocated(mat, 1);
1560 
1561   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1562   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1563 
1564   if (PetscDefined(USE_DEBUG)) {
1565     PetscInt i, j;
1566 
1567     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1568     if (v) {
1569       for (i = 0; i < m; i++) {
1570         for (j = 0; j < n; j++) {
1571           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1572 #if defined(PETSC_USE_COMPLEX)
1573             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]);
1574 #else
1575             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]);
1576 #endif
1577         }
1578       }
1579     }
1580     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);
1581     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);
1582   }
1583 
1584   if (mat->assembled) {
1585     mat->was_assembled = PETSC_TRUE;
1586     mat->assembled     = PETSC_FALSE;
1587   }
1588   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1589   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1590   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1591   PetscFunctionReturn(PETSC_SUCCESS);
1592 }
1593 
1594 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1595 /*@
1596   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1597   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1598   MUST be called after all calls to `MatSetValues()` have been completed.
1599 
1600   Not Collective
1601 
1602   Input Parameters:
1603 + mat  - the matrix
1604 . v    - a logically two-dimensional array of values
1605 . ism  - the rows to provide
1606 . isn  - the columns to provide
1607 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1608 
1609   Level: beginner
1610 
1611   Notes:
1612   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1613 
1614   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1615   options cannot be mixed without intervening calls to the assembly
1616   routines.
1617 
1618   `MatSetValues()` uses 0-based row and column numbers in Fortran
1619   as well as in C.
1620 
1621   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1622   simply ignored. This allows easily inserting element stiffness matrices
1623   with homogeneous Dirichlet boundary conditions that you don't want represented
1624   in the matrix.
1625 
1626   Efficiency Alert:
1627   The routine `MatSetValuesBlocked()` may offer much better efficiency
1628   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1629 
1630   This is currently not optimized for any particular `ISType`
1631 
1632   Developer Note:
1633   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1634   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1635 
1636 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1637           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1638 @*/
1639 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1640 {
1641   PetscInt        m, n;
1642   const PetscInt *rows, *cols;
1643 
1644   PetscFunctionBeginHot;
1645   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1646   PetscCall(ISGetIndices(ism, &rows));
1647   PetscCall(ISGetIndices(isn, &cols));
1648   PetscCall(ISGetLocalSize(ism, &m));
1649   PetscCall(ISGetLocalSize(isn, &n));
1650   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1651   PetscCall(ISRestoreIndices(ism, &rows));
1652   PetscCall(ISRestoreIndices(isn, &cols));
1653   PetscFunctionReturn(PETSC_SUCCESS);
1654 }
1655 
1656 /*@
1657   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1658   values into a matrix
1659 
1660   Not Collective
1661 
1662   Input Parameters:
1663 + mat - the matrix
1664 . row - the (block) row to set
1665 - v   - a logically two-dimensional array of values
1666 
1667   Level: intermediate
1668 
1669   Notes:
1670   The values, `v`, are column-oriented (for the block version) and sorted
1671 
1672   All the nonzero values in `row` must be provided
1673 
1674   The matrix must have previously had its column indices set, likely by having been assembled.
1675 
1676   `row` must belong to this MPI process
1677 
1678 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1679           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1680 @*/
1681 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1682 {
1683   PetscInt globalrow;
1684 
1685   PetscFunctionBegin;
1686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1687   PetscValidType(mat, 1);
1688   PetscAssertPointer(v, 3);
1689   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1690   PetscCall(MatSetValuesRow(mat, globalrow, v));
1691   PetscFunctionReturn(PETSC_SUCCESS);
1692 }
1693 
1694 /*@
1695   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1696   values into a matrix
1697 
1698   Not Collective
1699 
1700   Input Parameters:
1701 + mat - the matrix
1702 . row - the (block) row to set
1703 - v   - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1704 
1705   Level: advanced
1706 
1707   Notes:
1708   The values, `v`, are column-oriented for the block version.
1709 
1710   All the nonzeros in `row` must be provided
1711 
1712   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1713 
1714   `row` must belong to this process
1715 
1716 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1717           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1718 @*/
1719 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1720 {
1721   PetscFunctionBeginHot;
1722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1723   PetscValidType(mat, 1);
1724   MatCheckPreallocated(mat, 1);
1725   PetscAssertPointer(v, 3);
1726   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1727   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1728   mat->insertmode = INSERT_VALUES;
1729 
1730   if (mat->assembled) {
1731     mat->was_assembled = PETSC_TRUE;
1732     mat->assembled     = PETSC_FALSE;
1733   }
1734   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1735   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1736   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1737   PetscFunctionReturn(PETSC_SUCCESS);
1738 }
1739 
1740 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1741 /*@
1742   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1743   Using structured grid indexing
1744 
1745   Not Collective
1746 
1747   Input Parameters:
1748 + mat  - the matrix
1749 . m    - number of rows being entered
1750 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1751 . n    - number of columns being entered
1752 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1753 . v    - a logically two-dimensional array of values
1754 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1755 
1756   Level: beginner
1757 
1758   Notes:
1759   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1760 
1761   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1762   options cannot be mixed without intervening calls to the assembly
1763   routines.
1764 
1765   The grid coordinates are across the entire grid, not just the local portion
1766 
1767   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1768   as well as in C.
1769 
1770   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1771 
1772   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1773   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1774 
1775   The columns and rows in the stencil passed in MUST be contained within the
1776   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1777   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1778   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1779   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1780 
1781   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1782   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1783   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1784   `DM_BOUNDARY_PERIODIC` boundary type.
1785 
1786   For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1787   a single value per point) you can skip filling those indices.
1788 
1789   Inspired by the structured grid interface to the HYPRE package
1790   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1791 
1792   Efficiency Alert:
1793   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1794   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1795 
1796 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1797           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1798 @*/
1799 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1800 {
1801   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1802   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1803   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1804 
1805   PetscFunctionBegin;
1806   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1808   PetscValidType(mat, 1);
1809   PetscAssertPointer(idxm, 3);
1810   PetscAssertPointer(idxn, 5);
1811 
1812   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1813     jdxm = buf;
1814     jdxn = buf + m;
1815   } else {
1816     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1817     jdxm = bufm;
1818     jdxn = bufn;
1819   }
1820   for (i = 0; i < m; i++) {
1821     for (j = 0; j < 3 - sdim; j++) dxm++;
1822     tmp = *dxm++ - starts[0];
1823     for (j = 0; j < dim - 1; j++) {
1824       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1825       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1826     }
1827     if (mat->stencil.noc) dxm++;
1828     jdxm[i] = tmp;
1829   }
1830   for (i = 0; i < n; i++) {
1831     for (j = 0; j < 3 - sdim; j++) dxn++;
1832     tmp = *dxn++ - starts[0];
1833     for (j = 0; j < dim - 1; j++) {
1834       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1835       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1836     }
1837     if (mat->stencil.noc) dxn++;
1838     jdxn[i] = tmp;
1839   }
1840   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1841   PetscCall(PetscFree2(bufm, bufn));
1842   PetscFunctionReturn(PETSC_SUCCESS);
1843 }
1844 
1845 /*@
1846   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1847   Using structured grid indexing
1848 
1849   Not Collective
1850 
1851   Input Parameters:
1852 + mat  - the matrix
1853 . m    - number of rows being entered
1854 . idxm - grid coordinates for matrix rows being entered
1855 . n    - number of columns being entered
1856 . idxn - grid coordinates for matrix columns being entered
1857 . v    - a logically two-dimensional array of values
1858 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1859 
1860   Level: beginner
1861 
1862   Notes:
1863   By default the values, `v`, are row-oriented and unsorted.
1864   See `MatSetOption()` for other options.
1865 
1866   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1867   options cannot be mixed without intervening calls to the assembly
1868   routines.
1869 
1870   The grid coordinates are across the entire grid, not just the local portion
1871 
1872   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1873   as well as in C.
1874 
1875   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1876 
1877   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1878   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1879 
1880   The columns and rows in the stencil passed in MUST be contained within the
1881   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1882   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1883   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1884   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1885 
1886   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1887   simply ignored. This allows easily inserting element stiffness matrices
1888   with homogeneous Dirichlet boundary conditions that you don't want represented
1889   in the matrix.
1890 
1891   Inspired by the structured grid interface to the HYPRE package
1892   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1893 
1894   Fortran Note:
1895   `idxm` and `idxn` should be declared as
1896 .vb
1897     MatStencil idxm(4,m),idxn(4,n)
1898 .ve
1899   and the values inserted using
1900 .vb
1901     idxm(MatStencil_i,1) = i
1902     idxm(MatStencil_j,1) = j
1903     idxm(MatStencil_k,1) = k
1904    etc
1905 .ve
1906 
1907 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1908           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1909           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1910 @*/
1911 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1912 {
1913   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1914   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1915   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1916 
1917   PetscFunctionBegin;
1918   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1919   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1920   PetscValidType(mat, 1);
1921   PetscAssertPointer(idxm, 3);
1922   PetscAssertPointer(idxn, 5);
1923   PetscAssertPointer(v, 6);
1924 
1925   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1926     jdxm = buf;
1927     jdxn = buf + m;
1928   } else {
1929     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1930     jdxm = bufm;
1931     jdxn = bufn;
1932   }
1933   for (i = 0; i < m; i++) {
1934     for (j = 0; j < 3 - sdim; j++) dxm++;
1935     tmp = *dxm++ - starts[0];
1936     for (j = 0; j < sdim - 1; j++) {
1937       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1938       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1939     }
1940     dxm++;
1941     jdxm[i] = tmp;
1942   }
1943   for (i = 0; i < n; i++) {
1944     for (j = 0; j < 3 - sdim; j++) dxn++;
1945     tmp = *dxn++ - starts[0];
1946     for (j = 0; j < sdim - 1; j++) {
1947       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1948       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1949     }
1950     dxn++;
1951     jdxn[i] = tmp;
1952   }
1953   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1954   PetscCall(PetscFree2(bufm, bufn));
1955   PetscFunctionReturn(PETSC_SUCCESS);
1956 }
1957 
1958 /*@
1959   MatSetStencil - Sets the grid information for setting values into a matrix via
1960   `MatSetValuesStencil()`
1961 
1962   Not Collective
1963 
1964   Input Parameters:
1965 + mat    - the matrix
1966 . dim    - dimension of the grid 1, 2, or 3
1967 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1968 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1969 - dof    - number of degrees of freedom per node
1970 
1971   Level: beginner
1972 
1973   Notes:
1974   Inspired by the structured grid interface to the HYPRE package
1975   (www.llnl.gov/CASC/hyper)
1976 
1977   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1978   user.
1979 
1980 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1981           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1982 @*/
1983 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1984 {
1985   PetscFunctionBegin;
1986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1987   PetscAssertPointer(dims, 3);
1988   PetscAssertPointer(starts, 4);
1989 
1990   mat->stencil.dim = dim + (dof > 1);
1991   for (PetscInt i = 0; i < dim; i++) {
1992     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1993     mat->stencil.starts[i] = starts[dim - i - 1];
1994   }
1995   mat->stencil.dims[dim]   = dof;
1996   mat->stencil.starts[dim] = 0;
1997   mat->stencil.noc         = (PetscBool)(dof == 1);
1998   PetscFunctionReturn(PETSC_SUCCESS);
1999 }
2000 
2001 /*@
2002   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
2003 
2004   Not Collective
2005 
2006   Input Parameters:
2007 + mat  - the matrix
2008 . v    - a logically two-dimensional array of values
2009 . m    - the number of block rows
2010 . idxm - the global block indices
2011 . n    - the number of block columns
2012 . idxn - the global block indices
2013 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
2014 
2015   Level: intermediate
2016 
2017   Notes:
2018   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
2019   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
2020 
2021   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
2022   NOT the total number of rows/columns; for example, if the block size is 2 and
2023   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
2024   The values in `idxm` would be 1 2; that is the first index for each block divided by
2025   the block size.
2026 
2027   You must call `MatSetBlockSize()` when constructing this matrix (before
2028   preallocating it).
2029 
2030   By default the values, `v`, are row-oriented, so the layout of
2031   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
2032 
2033   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
2034   options cannot be mixed without intervening calls to the assembly
2035   routines.
2036 
2037   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
2038   as well as in C.
2039 
2040   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2041   simply ignored. This allows easily inserting element stiffness matrices
2042   with homogeneous Dirichlet boundary conditions that you don't want represented
2043   in the matrix.
2044 
2045   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2046   internal searching must be done to determine where to place the
2047   data in the matrix storage space.  By instead inserting blocks of
2048   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2049   reduced.
2050 
2051   Example:
2052 .vb
2053    Suppose m=n=2 and block size(bs) = 2 The array is
2054 
2055    1  2  | 3  4
2056    5  6  | 7  8
2057    - - - | - - -
2058    9  10 | 11 12
2059    13 14 | 15 16
2060 
2061    v[] should be passed in like
2062    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2063 
2064   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2065    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2066 .ve
2067 
2068   Fortran Notes:
2069   If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2070 .vb
2071   call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
2072 .ve
2073 
2074   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2075 
2076 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2077 @*/
2078 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2079 {
2080   PetscFunctionBeginHot;
2081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2082   PetscValidType(mat, 1);
2083   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2084   PetscAssertPointer(idxm, 3);
2085   PetscAssertPointer(idxn, 5);
2086   MatCheckPreallocated(mat, 1);
2087   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2088   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2089   if (PetscDefined(USE_DEBUG)) {
2090     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2091     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2092   }
2093   if (PetscDefined(USE_DEBUG)) {
2094     PetscInt rbs, cbs, M, N, i;
2095     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2096     PetscCall(MatGetSize(mat, &M, &N));
2097     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);
2098     for (i = 0; i < n; i++)
2099       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);
2100   }
2101   if (mat->assembled) {
2102     mat->was_assembled = PETSC_TRUE;
2103     mat->assembled     = PETSC_FALSE;
2104   }
2105   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2106   if (mat->ops->setvaluesblocked) {
2107     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2108   } else {
2109     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2110     PetscInt i, j, bs, cbs;
2111 
2112     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2113     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2114       iidxm = buf;
2115       iidxn = buf + m * bs;
2116     } else {
2117       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2118       iidxm = bufr;
2119       iidxn = bufc;
2120     }
2121     for (i = 0; i < m; i++) {
2122       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2123     }
2124     if (m != n || bs != cbs || idxm != idxn) {
2125       for (i = 0; i < n; i++) {
2126         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2127       }
2128     } else iidxn = iidxm;
2129     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2130     PetscCall(PetscFree2(bufr, bufc));
2131   }
2132   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2133   PetscFunctionReturn(PETSC_SUCCESS);
2134 }
2135 
2136 /*@
2137   MatGetValues - Gets a block of local values from a matrix.
2138 
2139   Not Collective; can only return values that are owned by the give process
2140 
2141   Input Parameters:
2142 + mat  - the matrix
2143 . v    - a logically two-dimensional array for storing the values
2144 . m    - the number of rows
2145 . idxm - the  global indices of the rows
2146 . n    - the number of columns
2147 - idxn - the global indices of the columns
2148 
2149   Level: advanced
2150 
2151   Notes:
2152   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2153   The values, `v`, are then returned in a row-oriented format,
2154   analogous to that used by default in `MatSetValues()`.
2155 
2156   `MatGetValues()` uses 0-based row and column numbers in
2157   Fortran as well as in C.
2158 
2159   `MatGetValues()` requires that the matrix has been assembled
2160   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2161   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2162   without intermediate matrix assembly.
2163 
2164   Negative row or column indices will be ignored and those locations in `v` will be
2165   left unchanged.
2166 
2167   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2168   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2169   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2170 
2171 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2172 @*/
2173 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2174 {
2175   PetscFunctionBegin;
2176   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2177   PetscValidType(mat, 1);
2178   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2179   PetscAssertPointer(idxm, 3);
2180   PetscAssertPointer(idxn, 5);
2181   PetscAssertPointer(v, 6);
2182   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2183   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2184   MatCheckPreallocated(mat, 1);
2185 
2186   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2187   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2188   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2189   PetscFunctionReturn(PETSC_SUCCESS);
2190 }
2191 
2192 /*@
2193   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2194   defined previously by `MatSetLocalToGlobalMapping()`
2195 
2196   Not Collective
2197 
2198   Input Parameters:
2199 + mat  - the matrix
2200 . nrow - number of rows
2201 . irow - the row local indices
2202 . ncol - number of columns
2203 - icol - the column local indices
2204 
2205   Output Parameter:
2206 . y - a logically two-dimensional array of values
2207 
2208   Level: advanced
2209 
2210   Notes:
2211   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2212 
2213   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,
2214   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2215   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2216   with `MatSetLocalToGlobalMapping()`.
2217 
2218   Developer Note:
2219   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2220   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2221 
2222 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2223           `MatSetValuesLocal()`, `MatGetValues()`
2224 @*/
2225 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2226 {
2227   PetscFunctionBeginHot;
2228   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2229   PetscValidType(mat, 1);
2230   MatCheckPreallocated(mat, 1);
2231   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2232   PetscAssertPointer(irow, 3);
2233   PetscAssertPointer(icol, 5);
2234   if (PetscDefined(USE_DEBUG)) {
2235     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2236     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2237   }
2238   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2239   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2240   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2241   else {
2242     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2243     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2244       irowm = buf;
2245       icolm = buf + nrow;
2246     } else {
2247       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2248       irowm = bufr;
2249       icolm = bufc;
2250     }
2251     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2252     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2253     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2254     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2255     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2256     PetscCall(PetscFree2(bufr, bufc));
2257   }
2258   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2259   PetscFunctionReturn(PETSC_SUCCESS);
2260 }
2261 
2262 /*@
2263   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2264   the same size. Currently, this can only be called once and creates the given matrix.
2265 
2266   Not Collective
2267 
2268   Input Parameters:
2269 + mat  - the matrix
2270 . nb   - the number of blocks
2271 . bs   - the number of rows (and columns) in each block
2272 . rows - a concatenation of the rows for each block
2273 - v    - a concatenation of logically two-dimensional arrays of values
2274 
2275   Level: advanced
2276 
2277   Notes:
2278   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2279 
2280   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2281 
2282 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2283           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2284 @*/
2285 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2286 {
2287   PetscFunctionBegin;
2288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2289   PetscValidType(mat, 1);
2290   PetscAssertPointer(rows, 4);
2291   PetscAssertPointer(v, 5);
2292   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2293 
2294   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2295   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2296   else {
2297     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2298   }
2299   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2300   PetscFunctionReturn(PETSC_SUCCESS);
2301 }
2302 
2303 /*@
2304   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2305   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2306   using a local (per-processor) numbering.
2307 
2308   Not Collective
2309 
2310   Input Parameters:
2311 + x        - the matrix
2312 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2313 - cmapping - column mapping
2314 
2315   Level: intermediate
2316 
2317   Note:
2318   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2319 
2320 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2321 @*/
2322 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2323 {
2324   PetscFunctionBegin;
2325   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2326   PetscValidType(x, 1);
2327   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2328   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2329   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2330   else {
2331     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2332     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2333   }
2334   PetscFunctionReturn(PETSC_SUCCESS);
2335 }
2336 
2337 /*@
2338   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2339 
2340   Not Collective
2341 
2342   Input Parameter:
2343 . A - the matrix
2344 
2345   Output Parameters:
2346 + rmapping - row mapping
2347 - cmapping - column mapping
2348 
2349   Level: advanced
2350 
2351 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2352 @*/
2353 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2354 {
2355   PetscFunctionBegin;
2356   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2357   PetscValidType(A, 1);
2358   if (rmapping) {
2359     PetscAssertPointer(rmapping, 2);
2360     *rmapping = A->rmap->mapping;
2361   }
2362   if (cmapping) {
2363     PetscAssertPointer(cmapping, 3);
2364     *cmapping = A->cmap->mapping;
2365   }
2366   PetscFunctionReturn(PETSC_SUCCESS);
2367 }
2368 
2369 /*@
2370   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2371 
2372   Logically Collective
2373 
2374   Input Parameters:
2375 + A    - the matrix
2376 . rmap - row layout
2377 - cmap - column layout
2378 
2379   Level: advanced
2380 
2381   Note:
2382   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2383 
2384 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2385 @*/
2386 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2387 {
2388   PetscFunctionBegin;
2389   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2390   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2391   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2392   PetscFunctionReturn(PETSC_SUCCESS);
2393 }
2394 
2395 /*@
2396   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2397 
2398   Not Collective
2399 
2400   Input Parameter:
2401 . A - the matrix
2402 
2403   Output Parameters:
2404 + rmap - row layout
2405 - cmap - column layout
2406 
2407   Level: advanced
2408 
2409 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2410 @*/
2411 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2412 {
2413   PetscFunctionBegin;
2414   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2415   PetscValidType(A, 1);
2416   if (rmap) {
2417     PetscAssertPointer(rmap, 2);
2418     *rmap = A->rmap;
2419   }
2420   if (cmap) {
2421     PetscAssertPointer(cmap, 3);
2422     *cmap = A->cmap;
2423   }
2424   PetscFunctionReturn(PETSC_SUCCESS);
2425 }
2426 
2427 /*@
2428   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2429   using a local numbering of the rows and columns.
2430 
2431   Not Collective
2432 
2433   Input Parameters:
2434 + mat  - the matrix
2435 . nrow - number of rows
2436 . irow - the row local indices
2437 . ncol - number of columns
2438 . icol - the column local indices
2439 . y    - a logically two-dimensional array of values
2440 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2441 
2442   Level: intermediate
2443 
2444   Notes:
2445   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2446 
2447   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2448   options cannot be mixed without intervening calls to the assembly
2449   routines.
2450 
2451   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2452   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2453 
2454   Fortran Notes:
2455   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2456 .vb
2457   call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2458 .ve
2459 
2460   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2461 
2462 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2463           `MatGetValuesLocal()`
2464 @*/
2465 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2466 {
2467   PetscFunctionBeginHot;
2468   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2469   PetscValidType(mat, 1);
2470   MatCheckPreallocated(mat, 1);
2471   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2472   PetscAssertPointer(irow, 3);
2473   PetscAssertPointer(icol, 5);
2474   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2475   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2476   if (PetscDefined(USE_DEBUG)) {
2477     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2478     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2479   }
2480 
2481   if (mat->assembled) {
2482     mat->was_assembled = PETSC_TRUE;
2483     mat->assembled     = PETSC_FALSE;
2484   }
2485   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2486   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2487   else {
2488     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2489     const PetscInt *irowm, *icolm;
2490 
2491     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2492       bufr  = buf;
2493       bufc  = buf + nrow;
2494       irowm = bufr;
2495       icolm = bufc;
2496     } else {
2497       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2498       irowm = bufr;
2499       icolm = bufc;
2500     }
2501     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2502     else irowm = irow;
2503     if (mat->cmap->mapping) {
2504       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2505         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2506       } else icolm = irowm;
2507     } else icolm = icol;
2508     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2509     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2510   }
2511   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2512   PetscFunctionReturn(PETSC_SUCCESS);
2513 }
2514 
2515 /*@
2516   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2517   using a local ordering of the nodes a block at a time.
2518 
2519   Not Collective
2520 
2521   Input Parameters:
2522 + mat  - the matrix
2523 . nrow - number of rows
2524 . irow - the row local indices
2525 . ncol - number of columns
2526 . icol - the column local indices
2527 . y    - a logically two-dimensional array of values
2528 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2529 
2530   Level: intermediate
2531 
2532   Notes:
2533   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2534   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2535 
2536   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2537   options cannot be mixed without intervening calls to the assembly
2538   routines.
2539 
2540   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2541   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2542 
2543   Fortran Notes:
2544   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2545 .vb
2546   call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2547 .ve
2548 
2549   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2550 
2551 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2552           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2553 @*/
2554 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2555 {
2556   PetscFunctionBeginHot;
2557   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2558   PetscValidType(mat, 1);
2559   MatCheckPreallocated(mat, 1);
2560   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2561   PetscAssertPointer(irow, 3);
2562   PetscAssertPointer(icol, 5);
2563   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2564   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2565   if (PetscDefined(USE_DEBUG)) {
2566     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2567     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);
2568   }
2569 
2570   if (mat->assembled) {
2571     mat->was_assembled = PETSC_TRUE;
2572     mat->assembled     = PETSC_FALSE;
2573   }
2574   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2575     PetscInt irbs, rbs;
2576     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2577     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2578     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2579   }
2580   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2581     PetscInt icbs, cbs;
2582     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2583     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2584     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2585   }
2586   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2587   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2588   else {
2589     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2590     const PetscInt *irowm, *icolm;
2591 
2592     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2593       bufr  = buf;
2594       bufc  = buf + nrow;
2595       irowm = bufr;
2596       icolm = bufc;
2597     } else {
2598       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2599       irowm = bufr;
2600       icolm = bufc;
2601     }
2602     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2603     else irowm = irow;
2604     if (mat->cmap->mapping) {
2605       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2606         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2607       } else icolm = irowm;
2608     } else icolm = icol;
2609     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2610     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2611   }
2612   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2613   PetscFunctionReturn(PETSC_SUCCESS);
2614 }
2615 
2616 /*@
2617   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2618 
2619   Collective
2620 
2621   Input Parameters:
2622 + mat - the matrix
2623 - x   - the vector to be multiplied
2624 
2625   Output Parameter:
2626 . y - the result
2627 
2628   Level: developer
2629 
2630   Note:
2631   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2632   call `MatMultDiagonalBlock`(A,y,y).
2633 
2634 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2635 @*/
2636 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2637 {
2638   PetscFunctionBegin;
2639   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2640   PetscValidType(mat, 1);
2641   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2642   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2643 
2644   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2645   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2646   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2647   MatCheckPreallocated(mat, 1);
2648 
2649   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2650   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2651   PetscFunctionReturn(PETSC_SUCCESS);
2652 }
2653 
2654 /*@
2655   MatMult - Computes the matrix-vector product, $y = Ax$.
2656 
2657   Neighbor-wise Collective
2658 
2659   Input Parameters:
2660 + mat - the matrix
2661 - x   - the vector to be multiplied
2662 
2663   Output Parameter:
2664 . y - the result
2665 
2666   Level: beginner
2667 
2668   Note:
2669   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2670   call `MatMult`(A,y,y).
2671 
2672 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2673 @*/
2674 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2675 {
2676   PetscFunctionBegin;
2677   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2678   PetscValidType(mat, 1);
2679   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2680   VecCheckAssembled(x);
2681   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2682   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2683   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2684   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2685   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);
2686   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);
2687   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);
2688   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);
2689   PetscCall(VecSetErrorIfLocked(y, 3));
2690   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2691   MatCheckPreallocated(mat, 1);
2692 
2693   PetscCall(VecLockReadPush(x));
2694   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2695   PetscUseTypeMethod(mat, mult, x, y);
2696   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2697   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2698   PetscCall(VecLockReadPop(x));
2699   PetscFunctionReturn(PETSC_SUCCESS);
2700 }
2701 
2702 /*@
2703   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2704 
2705   Neighbor-wise Collective
2706 
2707   Input Parameters:
2708 + mat - the matrix
2709 - x   - the vector to be multiplied
2710 
2711   Output Parameter:
2712 . y - the result
2713 
2714   Level: beginner
2715 
2716   Notes:
2717   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2718   call `MatMultTranspose`(A,y,y).
2719 
2720   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2721   use `MatMultHermitianTranspose()`
2722 
2723 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2724 @*/
2725 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2726 {
2727   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2728 
2729   PetscFunctionBegin;
2730   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2731   PetscValidType(mat, 1);
2732   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2733   VecCheckAssembled(x);
2734   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2735 
2736   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2737   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2738   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2739   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);
2740   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);
2741   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);
2742   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);
2743   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2744   MatCheckPreallocated(mat, 1);
2745 
2746   if (!mat->ops->multtranspose) {
2747     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2748     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);
2749   } else op = mat->ops->multtranspose;
2750   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2751   PetscCall(VecLockReadPush(x));
2752   PetscCall((*op)(mat, x, y));
2753   PetscCall(VecLockReadPop(x));
2754   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2755   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2756   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2757   PetscFunctionReturn(PETSC_SUCCESS);
2758 }
2759 
2760 /*@
2761   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2762 
2763   Neighbor-wise Collective
2764 
2765   Input Parameters:
2766 + mat - the matrix
2767 - x   - the vector to be multiplied
2768 
2769   Output Parameter:
2770 . y - the result
2771 
2772   Level: beginner
2773 
2774   Notes:
2775   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2776   call `MatMultHermitianTranspose`(A,y,y).
2777 
2778   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2779 
2780   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2781 
2782 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2783 @*/
2784 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2785 {
2786   PetscFunctionBegin;
2787   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2788   PetscValidType(mat, 1);
2789   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2790   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2791 
2792   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2793   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2794   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2795   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);
2796   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);
2797   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);
2798   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);
2799   MatCheckPreallocated(mat, 1);
2800 
2801   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2802 #if defined(PETSC_USE_COMPLEX)
2803   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2804     PetscCall(VecLockReadPush(x));
2805     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2806     else PetscUseTypeMethod(mat, mult, x, y);
2807     PetscCall(VecLockReadPop(x));
2808   } else {
2809     Vec w;
2810     PetscCall(VecDuplicate(x, &w));
2811     PetscCall(VecCopy(x, w));
2812     PetscCall(VecConjugate(w));
2813     PetscCall(MatMultTranspose(mat, w, y));
2814     PetscCall(VecDestroy(&w));
2815     PetscCall(VecConjugate(y));
2816   }
2817   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2818 #else
2819   PetscCall(MatMultTranspose(mat, x, y));
2820 #endif
2821   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2822   PetscFunctionReturn(PETSC_SUCCESS);
2823 }
2824 
2825 /*@
2826   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2827 
2828   Neighbor-wise Collective
2829 
2830   Input Parameters:
2831 + mat - the matrix
2832 . v1  - the vector to be multiplied by `mat`
2833 - v2  - the vector to be added to the result
2834 
2835   Output Parameter:
2836 . v3 - the result
2837 
2838   Level: beginner
2839 
2840   Note:
2841   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2842   call `MatMultAdd`(A,v1,v2,v1).
2843 
2844 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2845 @*/
2846 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2847 {
2848   PetscFunctionBegin;
2849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2850   PetscValidType(mat, 1);
2851   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2852   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2853   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2854 
2855   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2856   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2857   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);
2858   /* 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);
2859      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); */
2860   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);
2861   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);
2862   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2863   MatCheckPreallocated(mat, 1);
2864 
2865   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2866   PetscCall(VecLockReadPush(v1));
2867   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2868   PetscCall(VecLockReadPop(v1));
2869   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2870   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2871   PetscFunctionReturn(PETSC_SUCCESS);
2872 }
2873 
2874 /*@
2875   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2876 
2877   Neighbor-wise Collective
2878 
2879   Input Parameters:
2880 + mat - the matrix
2881 . v1  - the vector to be multiplied by the transpose of the matrix
2882 - v2  - the vector to be added to the result
2883 
2884   Output Parameter:
2885 . v3 - the result
2886 
2887   Level: beginner
2888 
2889   Note:
2890   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2891   call `MatMultTransposeAdd`(A,v1,v2,v1).
2892 
2893 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2894 @*/
2895 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2896 {
2897   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2898 
2899   PetscFunctionBegin;
2900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2901   PetscValidType(mat, 1);
2902   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2903   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2904   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2905 
2906   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2907   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2908   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);
2909   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);
2910   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);
2911   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2912   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2913   MatCheckPreallocated(mat, 1);
2914 
2915   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2916   PetscCall(VecLockReadPush(v1));
2917   PetscCall((*op)(mat, v1, v2, v3));
2918   PetscCall(VecLockReadPop(v1));
2919   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2920   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2921   PetscFunctionReturn(PETSC_SUCCESS);
2922 }
2923 
2924 /*@
2925   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2926 
2927   Neighbor-wise Collective
2928 
2929   Input Parameters:
2930 + mat - the matrix
2931 . v1  - the vector to be multiplied by the Hermitian transpose
2932 - v2  - the vector to be added to the result
2933 
2934   Output Parameter:
2935 . v3 - the result
2936 
2937   Level: beginner
2938 
2939   Note:
2940   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2941   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2942 
2943 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2944 @*/
2945 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2946 {
2947   PetscFunctionBegin;
2948   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2949   PetscValidType(mat, 1);
2950   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2951   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2952   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2953 
2954   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2955   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2956   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2957   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);
2958   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);
2959   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);
2960   MatCheckPreallocated(mat, 1);
2961 
2962   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2963   PetscCall(VecLockReadPush(v1));
2964   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2965   else {
2966     Vec w, z;
2967     PetscCall(VecDuplicate(v1, &w));
2968     PetscCall(VecCopy(v1, w));
2969     PetscCall(VecConjugate(w));
2970     PetscCall(VecDuplicate(v3, &z));
2971     PetscCall(MatMultTranspose(mat, w, z));
2972     PetscCall(VecDestroy(&w));
2973     PetscCall(VecConjugate(z));
2974     if (v2 != v3) {
2975       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2976     } else {
2977       PetscCall(VecAXPY(v3, 1.0, z));
2978     }
2979     PetscCall(VecDestroy(&z));
2980   }
2981   PetscCall(VecLockReadPop(v1));
2982   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2983   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2984   PetscFunctionReturn(PETSC_SUCCESS);
2985 }
2986 
2987 /*@
2988   MatGetFactorType - gets the type of factorization a matrix is
2989 
2990   Not Collective
2991 
2992   Input Parameter:
2993 . mat - the matrix
2994 
2995   Output Parameter:
2996 . 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`
2997 
2998   Level: intermediate
2999 
3000 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3001           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3002 @*/
3003 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
3004 {
3005   PetscFunctionBegin;
3006   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3007   PetscValidType(mat, 1);
3008   PetscAssertPointer(t, 2);
3009   *t = mat->factortype;
3010   PetscFunctionReturn(PETSC_SUCCESS);
3011 }
3012 
3013 /*@
3014   MatSetFactorType - sets the type of factorization a matrix is
3015 
3016   Logically Collective
3017 
3018   Input Parameters:
3019 + mat - the matrix
3020 - 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`
3021 
3022   Level: intermediate
3023 
3024 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3025           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3026 @*/
3027 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
3028 {
3029   PetscFunctionBegin;
3030   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3031   PetscValidType(mat, 1);
3032   mat->factortype = t;
3033   PetscFunctionReturn(PETSC_SUCCESS);
3034 }
3035 
3036 /*@
3037   MatGetInfo - Returns information about matrix storage (number of
3038   nonzeros, memory, etc.).
3039 
3040   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3041 
3042   Input Parameters:
3043 + mat  - the matrix
3044 - 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)
3045 
3046   Output Parameter:
3047 . info - matrix information context
3048 
3049   Options Database Key:
3050 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3051 
3052   Level: intermediate
3053 
3054   Notes:
3055   The `MatInfo` context contains a variety of matrix data, including
3056   number of nonzeros allocated and used, number of mallocs during
3057   matrix assembly, etc.  Additional information for factored matrices
3058   is provided (such as the fill ratio, number of mallocs during
3059   factorization, etc.).
3060 
3061   Example:
3062   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3063   data within the `MatInfo` context.  For example,
3064 .vb
3065       MatInfo info;
3066       Mat     A;
3067       double  mal, nz_a, nz_u;
3068 
3069       MatGetInfo(A, MAT_LOCAL, &info);
3070       mal  = info.mallocs;
3071       nz_a = info.nz_allocated;
3072 .ve
3073 
3074 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3075 @*/
3076 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3077 {
3078   PetscFunctionBegin;
3079   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3080   PetscValidType(mat, 1);
3081   PetscAssertPointer(info, 3);
3082   MatCheckPreallocated(mat, 1);
3083   PetscUseTypeMethod(mat, getinfo, flag, info);
3084   PetscFunctionReturn(PETSC_SUCCESS);
3085 }
3086 
3087 /*
3088    This is used by external packages where it is not easy to get the info from the actual
3089    matrix factorization.
3090 */
3091 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3092 {
3093   PetscFunctionBegin;
3094   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3095   PetscFunctionReturn(PETSC_SUCCESS);
3096 }
3097 
3098 /*@
3099   MatLUFactor - Performs in-place LU factorization of matrix.
3100 
3101   Collective
3102 
3103   Input Parameters:
3104 + mat  - the matrix
3105 . row  - row permutation
3106 . col  - column permutation
3107 - info - options for factorization, includes
3108 .vb
3109           fill - expected fill as ratio of original fill.
3110           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3111                    Run with the option -info to determine an optimal value to use
3112 .ve
3113 
3114   Level: developer
3115 
3116   Notes:
3117   Most users should employ the `KSP` interface for linear solvers
3118   instead of working directly with matrix algebra routines such as this.
3119   See, e.g., `KSPCreate()`.
3120 
3121   This changes the state of the matrix to a factored matrix; it cannot be used
3122   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3123 
3124   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3125   when not using `KSP`.
3126 
3127   Developer Note:
3128   The Fortran interface is not autogenerated as the
3129   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3130 
3131 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3132           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3133 @*/
3134 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3135 {
3136   MatFactorInfo tinfo;
3137 
3138   PetscFunctionBegin;
3139   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3140   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3141   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3142   if (info) PetscAssertPointer(info, 4);
3143   PetscValidType(mat, 1);
3144   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3145   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3146   MatCheckPreallocated(mat, 1);
3147   if (!info) {
3148     PetscCall(MatFactorInfoInitialize(&tinfo));
3149     info = &tinfo;
3150   }
3151 
3152   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3153   PetscUseTypeMethod(mat, lufactor, row, col, info);
3154   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3155   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3156   PetscFunctionReturn(PETSC_SUCCESS);
3157 }
3158 
3159 /*@
3160   MatILUFactor - Performs in-place ILU factorization of matrix.
3161 
3162   Collective
3163 
3164   Input Parameters:
3165 + mat  - the matrix
3166 . row  - row permutation
3167 . col  - column permutation
3168 - info - structure containing
3169 .vb
3170       levels - number of levels of fill.
3171       expected fill - as ratio of original fill.
3172       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3173                 missing diagonal entries)
3174 .ve
3175 
3176   Level: developer
3177 
3178   Notes:
3179   Most users should employ the `KSP` interface for linear solvers
3180   instead of working directly with matrix algebra routines such as this.
3181   See, e.g., `KSPCreate()`.
3182 
3183   Probably really in-place only when level of fill is zero, otherwise allocates
3184   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3185   when not using `KSP`.
3186 
3187   Developer Note:
3188   The Fortran interface is not autogenerated as the
3189   interface definition cannot be generated correctly [due to MatFactorInfo]
3190 
3191 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3192 @*/
3193 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3194 {
3195   PetscFunctionBegin;
3196   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3197   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3198   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3199   PetscAssertPointer(info, 4);
3200   PetscValidType(mat, 1);
3201   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3202   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3203   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3204   MatCheckPreallocated(mat, 1);
3205 
3206   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3207   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3208   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3209   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3210   PetscFunctionReturn(PETSC_SUCCESS);
3211 }
3212 
3213 /*@
3214   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3215   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3216 
3217   Collective
3218 
3219   Input Parameters:
3220 + fact - the factor matrix obtained with `MatGetFactor()`
3221 . mat  - the matrix
3222 . row  - the row permutation
3223 . col  - the column permutation
3224 - info - options for factorization, includes
3225 .vb
3226           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3227           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3228 .ve
3229 
3230   Level: developer
3231 
3232   Notes:
3233   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3234 
3235   Most users should employ the simplified `KSP` interface for linear solvers
3236   instead of working directly with matrix algebra routines such as this.
3237   See, e.g., `KSPCreate()`.
3238 
3239   Developer Note:
3240   The Fortran interface is not autogenerated as the
3241   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3242 
3243 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3244 @*/
3245 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3246 {
3247   MatFactorInfo tinfo;
3248 
3249   PetscFunctionBegin;
3250   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3251   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3252   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3253   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3254   if (info) PetscAssertPointer(info, 5);
3255   PetscValidType(fact, 1);
3256   PetscValidType(mat, 2);
3257   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3258   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3259   MatCheckPreallocated(mat, 2);
3260   if (!info) {
3261     PetscCall(MatFactorInfoInitialize(&tinfo));
3262     info = &tinfo;
3263   }
3264 
3265   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3266   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3267   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3268   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3269   PetscFunctionReturn(PETSC_SUCCESS);
3270 }
3271 
3272 /*@
3273   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3274   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3275 
3276   Collective
3277 
3278   Input Parameters:
3279 + fact - the factor matrix obtained with `MatGetFactor()`
3280 . mat  - the matrix
3281 - info - options for factorization
3282 
3283   Level: developer
3284 
3285   Notes:
3286   See `MatLUFactor()` for in-place factorization.  See
3287   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3288 
3289   Most users should employ the `KSP` interface for linear solvers
3290   instead of working directly with matrix algebra routines such as this.
3291   See, e.g., `KSPCreate()`.
3292 
3293   Developer Note:
3294   The Fortran interface is not autogenerated as the
3295   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3296 
3297 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3298 @*/
3299 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3300 {
3301   MatFactorInfo tinfo;
3302 
3303   PetscFunctionBegin;
3304   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3306   PetscValidType(fact, 1);
3307   PetscValidType(mat, 2);
3308   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3309   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,
3310              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3311 
3312   MatCheckPreallocated(mat, 2);
3313   if (!info) {
3314     PetscCall(MatFactorInfoInitialize(&tinfo));
3315     info = &tinfo;
3316   }
3317 
3318   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3319   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3320   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3321   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3322   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3323   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3324   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3325   PetscFunctionReturn(PETSC_SUCCESS);
3326 }
3327 
3328 /*@
3329   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3330   symmetric matrix.
3331 
3332   Collective
3333 
3334   Input Parameters:
3335 + mat  - the matrix
3336 . perm - row and column permutations
3337 - info - expected fill as ratio of original fill
3338 
3339   Level: developer
3340 
3341   Notes:
3342   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3343   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3344 
3345   Most users should employ the `KSP` interface for linear solvers
3346   instead of working directly with matrix algebra routines such as this.
3347   See, e.g., `KSPCreate()`.
3348 
3349   Developer Note:
3350   The Fortran interface is not autogenerated as the
3351   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3352 
3353 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3354           `MatGetOrdering()`
3355 @*/
3356 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3357 {
3358   MatFactorInfo tinfo;
3359 
3360   PetscFunctionBegin;
3361   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3362   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3363   if (info) PetscAssertPointer(info, 3);
3364   PetscValidType(mat, 1);
3365   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3366   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3367   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3368   MatCheckPreallocated(mat, 1);
3369   if (!info) {
3370     PetscCall(MatFactorInfoInitialize(&tinfo));
3371     info = &tinfo;
3372   }
3373 
3374   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3375   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3376   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3377   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3378   PetscFunctionReturn(PETSC_SUCCESS);
3379 }
3380 
3381 /*@
3382   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3383   of a symmetric matrix.
3384 
3385   Collective
3386 
3387   Input Parameters:
3388 + fact - the factor matrix obtained with `MatGetFactor()`
3389 . mat  - the matrix
3390 . perm - row and column permutations
3391 - info - options for factorization, includes
3392 .vb
3393           fill - expected fill as ratio of original fill.
3394           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3395                    Run with the option -info to determine an optimal value to use
3396 .ve
3397 
3398   Level: developer
3399 
3400   Notes:
3401   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3402   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3403 
3404   Most users should employ the `KSP` interface for linear solvers
3405   instead of working directly with matrix algebra routines such as this.
3406   See, e.g., `KSPCreate()`.
3407 
3408   Developer Note:
3409   The Fortran interface is not autogenerated as the
3410   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3411 
3412 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3413           `MatGetOrdering()`
3414 @*/
3415 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3416 {
3417   MatFactorInfo tinfo;
3418 
3419   PetscFunctionBegin;
3420   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3421   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3422   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3423   if (info) PetscAssertPointer(info, 4);
3424   PetscValidType(fact, 1);
3425   PetscValidType(mat, 2);
3426   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3427   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3428   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3429   MatCheckPreallocated(mat, 2);
3430   if (!info) {
3431     PetscCall(MatFactorInfoInitialize(&tinfo));
3432     info = &tinfo;
3433   }
3434 
3435   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3436   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3437   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3438   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3439   PetscFunctionReturn(PETSC_SUCCESS);
3440 }
3441 
3442 /*@
3443   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3444   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3445   `MatCholeskyFactorSymbolic()`.
3446 
3447   Collective
3448 
3449   Input Parameters:
3450 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3451 . mat  - the initial matrix that is to be factored
3452 - info - options for factorization
3453 
3454   Level: developer
3455 
3456   Note:
3457   Most users should employ the `KSP` interface for linear solvers
3458   instead of working directly with matrix algebra routines such as this.
3459   See, e.g., `KSPCreate()`.
3460 
3461   Developer Note:
3462   The Fortran interface is not autogenerated as the
3463   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3464 
3465 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3466 @*/
3467 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3468 {
3469   MatFactorInfo tinfo;
3470 
3471   PetscFunctionBegin;
3472   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3473   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3474   PetscValidType(fact, 1);
3475   PetscValidType(mat, 2);
3476   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3477   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,
3478              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3479   MatCheckPreallocated(mat, 2);
3480   if (!info) {
3481     PetscCall(MatFactorInfoInitialize(&tinfo));
3482     info = &tinfo;
3483   }
3484 
3485   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3486   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3487   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3488   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3489   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3490   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3491   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3492   PetscFunctionReturn(PETSC_SUCCESS);
3493 }
3494 
3495 /*@
3496   MatQRFactor - Performs in-place QR factorization of matrix.
3497 
3498   Collective
3499 
3500   Input Parameters:
3501 + mat  - the matrix
3502 . col  - column permutation
3503 - info - options for factorization, includes
3504 .vb
3505           fill - expected fill as ratio of original fill.
3506           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3507                    Run with the option -info to determine an optimal value to use
3508 .ve
3509 
3510   Level: developer
3511 
3512   Notes:
3513   Most users should employ the `KSP` interface for linear solvers
3514   instead of working directly with matrix algebra routines such as this.
3515   See, e.g., `KSPCreate()`.
3516 
3517   This changes the state of the matrix to a factored matrix; it cannot be used
3518   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3519 
3520   Developer Note:
3521   The Fortran interface is not autogenerated as the
3522   interface definition cannot be generated correctly [due to MatFactorInfo]
3523 
3524 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3525           `MatSetUnfactored()`
3526 @*/
3527 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3528 {
3529   PetscFunctionBegin;
3530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3531   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3532   if (info) PetscAssertPointer(info, 3);
3533   PetscValidType(mat, 1);
3534   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3535   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3536   MatCheckPreallocated(mat, 1);
3537   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3538   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3539   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3540   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3541   PetscFunctionReturn(PETSC_SUCCESS);
3542 }
3543 
3544 /*@
3545   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3546   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3547 
3548   Collective
3549 
3550   Input Parameters:
3551 + fact - the factor matrix obtained with `MatGetFactor()`
3552 . mat  - the matrix
3553 . col  - column permutation
3554 - info - options for factorization, includes
3555 .vb
3556           fill - expected fill as ratio of original fill.
3557           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3558                    Run with the option -info to determine an optimal value to use
3559 .ve
3560 
3561   Level: developer
3562 
3563   Note:
3564   Most users should employ the `KSP` interface for linear solvers
3565   instead of working directly with matrix algebra routines such as this.
3566   See, e.g., `KSPCreate()`.
3567 
3568   Developer Note:
3569   The Fortran interface is not autogenerated as the
3570   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3571 
3572 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3573 @*/
3574 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3575 {
3576   MatFactorInfo tinfo;
3577 
3578   PetscFunctionBegin;
3579   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3580   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3581   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3582   if (info) PetscAssertPointer(info, 4);
3583   PetscValidType(fact, 1);
3584   PetscValidType(mat, 2);
3585   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3586   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3587   MatCheckPreallocated(mat, 2);
3588   if (!info) {
3589     PetscCall(MatFactorInfoInitialize(&tinfo));
3590     info = &tinfo;
3591   }
3592 
3593   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3594   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3595   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3596   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3597   PetscFunctionReturn(PETSC_SUCCESS);
3598 }
3599 
3600 /*@
3601   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3602   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3603 
3604   Collective
3605 
3606   Input Parameters:
3607 + fact - the factor matrix obtained with `MatGetFactor()`
3608 . mat  - the matrix
3609 - info - options for factorization
3610 
3611   Level: developer
3612 
3613   Notes:
3614   See `MatQRFactor()` for in-place factorization.
3615 
3616   Most users should employ the `KSP` interface for linear solvers
3617   instead of working directly with matrix algebra routines such as this.
3618   See, e.g., `KSPCreate()`.
3619 
3620   Developer Note:
3621   The Fortran interface is not autogenerated as the
3622   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3623 
3624 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3625 @*/
3626 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3627 {
3628   MatFactorInfo tinfo;
3629 
3630   PetscFunctionBegin;
3631   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3633   PetscValidType(fact, 1);
3634   PetscValidType(mat, 2);
3635   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3636   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,
3637              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3638 
3639   MatCheckPreallocated(mat, 2);
3640   if (!info) {
3641     PetscCall(MatFactorInfoInitialize(&tinfo));
3642     info = &tinfo;
3643   }
3644 
3645   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3646   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3647   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3648   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3649   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3650   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3651   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3652   PetscFunctionReturn(PETSC_SUCCESS);
3653 }
3654 
3655 /*@
3656   MatSolve - Solves $A x = b$, given a factored matrix.
3657 
3658   Neighbor-wise Collective
3659 
3660   Input Parameters:
3661 + mat - the factored matrix
3662 - b   - the right-hand-side vector
3663 
3664   Output Parameter:
3665 . x - the result vector
3666 
3667   Level: developer
3668 
3669   Notes:
3670   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3671   call `MatSolve`(A,x,x).
3672 
3673   Most users should employ the `KSP` interface for linear solvers
3674   instead of working directly with matrix algebra routines such as this.
3675   See, e.g., `KSPCreate()`.
3676 
3677 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3678 @*/
3679 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3680 {
3681   PetscFunctionBegin;
3682   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3683   PetscValidType(mat, 1);
3684   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3685   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3686   PetscCheckSameComm(mat, 1, b, 2);
3687   PetscCheckSameComm(mat, 1, x, 3);
3688   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3689   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);
3690   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);
3691   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);
3692   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3693   MatCheckPreallocated(mat, 1);
3694 
3695   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3696   PetscCall(VecFlag(x, mat->factorerrortype));
3697   if (mat->factorerrortype) {
3698     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3699   } else PetscUseTypeMethod(mat, solve, b, x);
3700   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3701   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3702   PetscFunctionReturn(PETSC_SUCCESS);
3703 }
3704 
3705 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3706 {
3707   Vec      b, x;
3708   PetscInt N, i;
3709   PetscErrorCode (*f)(Mat, Vec, Vec);
3710   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3711 
3712   PetscFunctionBegin;
3713   if (A->factorerrortype) {
3714     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3715     PetscCall(MatSetInf(X));
3716     PetscFunctionReturn(PETSC_SUCCESS);
3717   }
3718   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3719   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3720   PetscCall(MatBoundToCPU(A, &Abound));
3721   if (!Abound) {
3722     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3723     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3724   }
3725 #if PetscDefined(HAVE_CUDA)
3726   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3727   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3728 #elif PetscDefined(HAVE_HIP)
3729   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3730   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3731 #endif
3732   PetscCall(MatGetSize(B, NULL, &N));
3733   for (i = 0; i < N; i++) {
3734     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3735     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3736     PetscCall((*f)(A, b, x));
3737     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3738     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3739   }
3740   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3741   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3742   PetscFunctionReturn(PETSC_SUCCESS);
3743 }
3744 
3745 /*@
3746   MatMatSolve - Solves $A X = B$, given a factored matrix.
3747 
3748   Neighbor-wise Collective
3749 
3750   Input Parameters:
3751 + A - the factored matrix
3752 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3753 
3754   Output Parameter:
3755 . X - the result matrix (dense matrix)
3756 
3757   Level: developer
3758 
3759   Note:
3760   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3761   otherwise, `B` and `X` cannot be the same.
3762 
3763 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3764 @*/
3765 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3766 {
3767   PetscFunctionBegin;
3768   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3769   PetscValidType(A, 1);
3770   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3771   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3772   PetscCheckSameComm(A, 1, B, 2);
3773   PetscCheckSameComm(A, 1, X, 3);
3774   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);
3775   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);
3776   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");
3777   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3778   MatCheckPreallocated(A, 1);
3779 
3780   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3781   if (!A->ops->matsolve) {
3782     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3783     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3784   } else PetscUseTypeMethod(A, matsolve, B, X);
3785   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3786   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3787   PetscFunctionReturn(PETSC_SUCCESS);
3788 }
3789 
3790 /*@
3791   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3792 
3793   Neighbor-wise Collective
3794 
3795   Input Parameters:
3796 + A - the factored matrix
3797 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3798 
3799   Output Parameter:
3800 . X - the result matrix (dense matrix)
3801 
3802   Level: developer
3803 
3804   Note:
3805   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3806   call `MatMatSolveTranspose`(A,X,X).
3807 
3808 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3809 @*/
3810 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3811 {
3812   PetscFunctionBegin;
3813   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3814   PetscValidType(A, 1);
3815   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3816   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3817   PetscCheckSameComm(A, 1, B, 2);
3818   PetscCheckSameComm(A, 1, X, 3);
3819   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3820   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);
3821   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);
3822   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);
3823   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");
3824   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3825   MatCheckPreallocated(A, 1);
3826 
3827   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3828   if (!A->ops->matsolvetranspose) {
3829     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3830     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3831   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3832   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3833   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3834   PetscFunctionReturn(PETSC_SUCCESS);
3835 }
3836 
3837 /*@
3838   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3839 
3840   Neighbor-wise Collective
3841 
3842   Input Parameters:
3843 + A  - the factored matrix
3844 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3845 
3846   Output Parameter:
3847 . X - the result matrix (dense matrix)
3848 
3849   Level: developer
3850 
3851   Note:
3852   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
3853   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3854 
3855 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3856 @*/
3857 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3858 {
3859   PetscFunctionBegin;
3860   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3861   PetscValidType(A, 1);
3862   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3863   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3864   PetscCheckSameComm(A, 1, Bt, 2);
3865   PetscCheckSameComm(A, 1, X, 3);
3866 
3867   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3868   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);
3869   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);
3870   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");
3871   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3872   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3873   MatCheckPreallocated(A, 1);
3874 
3875   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3876   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3877   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3878   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3879   PetscFunctionReturn(PETSC_SUCCESS);
3880 }
3881 
3882 /*@
3883   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3884   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3885 
3886   Neighbor-wise Collective
3887 
3888   Input Parameters:
3889 + mat - the factored matrix
3890 - b   - the right-hand-side vector
3891 
3892   Output Parameter:
3893 . x - the result vector
3894 
3895   Level: developer
3896 
3897   Notes:
3898   `MatSolve()` should be used for most applications, as it performs
3899   a forward solve followed by a backward solve.
3900 
3901   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3902   call `MatForwardSolve`(A,x,x).
3903 
3904   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3905   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3906   `MatForwardSolve()` solves $U^T*D y = b$, and
3907   `MatBackwardSolve()` solves $U x = y$.
3908   Thus they do not provide a symmetric preconditioner.
3909 
3910 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3911 @*/
3912 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3913 {
3914   PetscFunctionBegin;
3915   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3916   PetscValidType(mat, 1);
3917   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3918   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3919   PetscCheckSameComm(mat, 1, b, 2);
3920   PetscCheckSameComm(mat, 1, x, 3);
3921   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3922   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);
3923   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);
3924   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);
3925   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3926   MatCheckPreallocated(mat, 1);
3927 
3928   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3929   PetscUseTypeMethod(mat, forwardsolve, b, x);
3930   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3931   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3932   PetscFunctionReturn(PETSC_SUCCESS);
3933 }
3934 
3935 /*@
3936   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3937   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3938 
3939   Neighbor-wise Collective
3940 
3941   Input Parameters:
3942 + mat - the factored matrix
3943 - b   - the right-hand-side vector
3944 
3945   Output Parameter:
3946 . x - the result vector
3947 
3948   Level: developer
3949 
3950   Notes:
3951   `MatSolve()` should be used for most applications, as it performs
3952   a forward solve followed by a backward solve.
3953 
3954   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3955   call `MatBackwardSolve`(A,x,x).
3956 
3957   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3958   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3959   `MatForwardSolve()` solves $U^T*D y = b$, and
3960   `MatBackwardSolve()` solves $U x = y$.
3961   Thus they do not provide a symmetric preconditioner.
3962 
3963 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3964 @*/
3965 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3966 {
3967   PetscFunctionBegin;
3968   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3969   PetscValidType(mat, 1);
3970   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3971   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3972   PetscCheckSameComm(mat, 1, b, 2);
3973   PetscCheckSameComm(mat, 1, x, 3);
3974   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3975   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);
3976   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);
3977   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);
3978   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3979   MatCheckPreallocated(mat, 1);
3980 
3981   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3982   PetscUseTypeMethod(mat, backwardsolve, b, x);
3983   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3984   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3985   PetscFunctionReturn(PETSC_SUCCESS);
3986 }
3987 
3988 /*@
3989   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3990 
3991   Neighbor-wise Collective
3992 
3993   Input Parameters:
3994 + mat - the factored matrix
3995 . b   - the right-hand-side vector
3996 - y   - the vector to be added to
3997 
3998   Output Parameter:
3999 . x - the result vector
4000 
4001   Level: developer
4002 
4003   Note:
4004   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4005   call `MatSolveAdd`(A,x,y,x).
4006 
4007 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
4008 @*/
4009 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
4010 {
4011   PetscScalar one = 1.0;
4012   Vec         tmp;
4013 
4014   PetscFunctionBegin;
4015   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4016   PetscValidType(mat, 1);
4017   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4018   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4019   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4020   PetscCheckSameComm(mat, 1, b, 2);
4021   PetscCheckSameComm(mat, 1, y, 3);
4022   PetscCheckSameComm(mat, 1, x, 4);
4023   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4024   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);
4025   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);
4026   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);
4027   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);
4028   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);
4029   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4030   MatCheckPreallocated(mat, 1);
4031 
4032   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4033   PetscCall(VecFlag(x, mat->factorerrortype));
4034   if (mat->factorerrortype) {
4035     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4036   } else if (mat->ops->solveadd) {
4037     PetscUseTypeMethod(mat, solveadd, b, y, x);
4038   } else {
4039     /* do the solve then the add manually */
4040     if (x != y) {
4041       PetscCall(MatSolve(mat, b, x));
4042       PetscCall(VecAXPY(x, one, y));
4043     } else {
4044       PetscCall(VecDuplicate(x, &tmp));
4045       PetscCall(VecCopy(x, tmp));
4046       PetscCall(MatSolve(mat, b, x));
4047       PetscCall(VecAXPY(x, one, tmp));
4048       PetscCall(VecDestroy(&tmp));
4049     }
4050   }
4051   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4052   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4053   PetscFunctionReturn(PETSC_SUCCESS);
4054 }
4055 
4056 /*@
4057   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4058 
4059   Neighbor-wise Collective
4060 
4061   Input Parameters:
4062 + mat - the factored matrix
4063 - b   - the right-hand-side vector
4064 
4065   Output Parameter:
4066 . x - the result vector
4067 
4068   Level: developer
4069 
4070   Notes:
4071   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4072   call `MatSolveTranspose`(A,x,x).
4073 
4074   Most users should employ the `KSP` interface for linear solvers
4075   instead of working directly with matrix algebra routines such as this.
4076   See, e.g., `KSPCreate()`.
4077 
4078 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4079 @*/
4080 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4081 {
4082   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4083 
4084   PetscFunctionBegin;
4085   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4086   PetscValidType(mat, 1);
4087   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4088   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4089   PetscCheckSameComm(mat, 1, b, 2);
4090   PetscCheckSameComm(mat, 1, x, 3);
4091   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4092   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);
4093   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);
4094   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4095   MatCheckPreallocated(mat, 1);
4096   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4097   PetscCall(VecFlag(x, mat->factorerrortype));
4098   if (mat->factorerrortype) {
4099     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4100   } else {
4101     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4102     PetscCall((*f)(mat, b, x));
4103   }
4104   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4105   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4106   PetscFunctionReturn(PETSC_SUCCESS);
4107 }
4108 
4109 /*@
4110   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4111   factored matrix.
4112 
4113   Neighbor-wise Collective
4114 
4115   Input Parameters:
4116 + mat - the factored matrix
4117 . b   - the right-hand-side vector
4118 - y   - the vector to be added to
4119 
4120   Output Parameter:
4121 . x - the result vector
4122 
4123   Level: developer
4124 
4125   Note:
4126   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4127   call `MatSolveTransposeAdd`(A,x,y,x).
4128 
4129 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4130 @*/
4131 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4132 {
4133   PetscScalar one = 1.0;
4134   Vec         tmp;
4135   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4136 
4137   PetscFunctionBegin;
4138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4139   PetscValidType(mat, 1);
4140   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4141   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4142   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4143   PetscCheckSameComm(mat, 1, b, 2);
4144   PetscCheckSameComm(mat, 1, y, 3);
4145   PetscCheckSameComm(mat, 1, x, 4);
4146   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4147   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);
4148   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);
4149   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);
4150   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);
4151   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4152   MatCheckPreallocated(mat, 1);
4153 
4154   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4155   PetscCall(VecFlag(x, mat->factorerrortype));
4156   if (mat->factorerrortype) {
4157     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4158   } else if (f) {
4159     PetscCall((*f)(mat, b, y, x));
4160   } else {
4161     /* do the solve then the add manually */
4162     if (x != y) {
4163       PetscCall(MatSolveTranspose(mat, b, x));
4164       PetscCall(VecAXPY(x, one, y));
4165     } else {
4166       PetscCall(VecDuplicate(x, &tmp));
4167       PetscCall(VecCopy(x, tmp));
4168       PetscCall(MatSolveTranspose(mat, b, x));
4169       PetscCall(VecAXPY(x, one, tmp));
4170       PetscCall(VecDestroy(&tmp));
4171     }
4172   }
4173   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4174   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4175   PetscFunctionReturn(PETSC_SUCCESS);
4176 }
4177 
4178 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4179 /*@
4180   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4181 
4182   Neighbor-wise Collective
4183 
4184   Input Parameters:
4185 + mat   - the matrix
4186 . b     - the right-hand side
4187 . omega - the relaxation factor
4188 . flag  - flag indicating the type of SOR (see below)
4189 . shift - diagonal shift
4190 . its   - the number of iterations
4191 - lits  - the number of local iterations
4192 
4193   Output Parameter:
4194 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4195 
4196   SOR Flags:
4197 +     `SOR_FORWARD_SWEEP` - forward SOR
4198 .     `SOR_BACKWARD_SWEEP` - backward SOR
4199 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4200 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4201 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4202 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4203 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4204 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4205   upper/lower triangular part of matrix to
4206   vector (with omega)
4207 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4208 
4209   Level: developer
4210 
4211   Notes:
4212   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4213   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4214   on each processor.
4215 
4216   Application programmers will not generally use `MatSOR()` directly,
4217   but instead will employ the `KSP`/`PC` interface.
4218 
4219   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4220 
4221   Most users should employ the `KSP` interface for linear solvers
4222   instead of working directly with matrix algebra routines such as this.
4223   See, e.g., `KSPCreate()`.
4224 
4225   Vectors `x` and `b` CANNOT be the same
4226 
4227   The flags are implemented as bitwise inclusive or operations.
4228   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4229   to specify a zero initial guess for SSOR.
4230 
4231   Developer Note:
4232   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4233 
4234 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4235 @*/
4236 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4237 {
4238   PetscFunctionBegin;
4239   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4240   PetscValidType(mat, 1);
4241   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4242   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4243   PetscCheckSameComm(mat, 1, b, 2);
4244   PetscCheckSameComm(mat, 1, x, 8);
4245   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4246   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4247   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);
4248   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);
4249   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);
4250   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4251   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4252   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4253 
4254   MatCheckPreallocated(mat, 1);
4255   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4256   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4257   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4258   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4259   PetscFunctionReturn(PETSC_SUCCESS);
4260 }
4261 
4262 /*
4263       Default matrix copy routine.
4264 */
4265 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4266 {
4267   PetscInt           i, rstart = 0, rend = 0, nz;
4268   const PetscInt    *cwork;
4269   const PetscScalar *vwork;
4270 
4271   PetscFunctionBegin;
4272   if (B->assembled) PetscCall(MatZeroEntries(B));
4273   if (str == SAME_NONZERO_PATTERN) {
4274     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4275     for (i = rstart; i < rend; i++) {
4276       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4277       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4278       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4279     }
4280   } else {
4281     PetscCall(MatAYPX(B, 0.0, A, str));
4282   }
4283   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4284   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4285   PetscFunctionReturn(PETSC_SUCCESS);
4286 }
4287 
4288 /*@
4289   MatCopy - Copies a matrix to another matrix.
4290 
4291   Collective
4292 
4293   Input Parameters:
4294 + A   - the matrix
4295 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4296 
4297   Output Parameter:
4298 . B - where the copy is put
4299 
4300   Level: intermediate
4301 
4302   Notes:
4303   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4304 
4305   `MatCopy()` copies the matrix entries of a matrix to another existing
4306   matrix (after first zeroing the second matrix).  A related routine is
4307   `MatConvert()`, which first creates a new matrix and then copies the data.
4308 
4309 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4310 @*/
4311 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4312 {
4313   PetscInt i;
4314 
4315   PetscFunctionBegin;
4316   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4317   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4318   PetscValidType(A, 1);
4319   PetscValidType(B, 2);
4320   PetscCheckSameComm(A, 1, B, 2);
4321   MatCheckPreallocated(B, 2);
4322   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4323   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4324   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,
4325              A->cmap->N, B->cmap->N);
4326   MatCheckPreallocated(A, 1);
4327   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4328 
4329   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4330   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4331   else PetscCall(MatCopy_Basic(A, B, str));
4332 
4333   B->stencil.dim = A->stencil.dim;
4334   B->stencil.noc = A->stencil.noc;
4335   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4336     B->stencil.dims[i]   = A->stencil.dims[i];
4337     B->stencil.starts[i] = A->stencil.starts[i];
4338   }
4339 
4340   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4341   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4342   PetscFunctionReturn(PETSC_SUCCESS);
4343 }
4344 
4345 /*@
4346   MatConvert - Converts a matrix to another matrix, either of the same
4347   or different type.
4348 
4349   Collective
4350 
4351   Input Parameters:
4352 + mat     - the matrix
4353 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4354             same type as the original matrix.
4355 - reuse   - denotes if the destination matrix is to be created or reused.
4356             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
4357             `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).
4358 
4359   Output Parameter:
4360 . M - pointer to place new matrix
4361 
4362   Level: intermediate
4363 
4364   Notes:
4365   `MatConvert()` first creates a new matrix and then copies the data from
4366   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4367   entries of one matrix to another already existing matrix context.
4368 
4369   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4370   the MPI communicator of the generated matrix is always the same as the communicator
4371   of the input matrix.
4372 
4373 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4374 @*/
4375 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4376 {
4377   PetscBool  sametype, issame, flg;
4378   PetscBool3 issymmetric, ishermitian;
4379   char       convname[256], mtype[256];
4380   Mat        B;
4381 
4382   PetscFunctionBegin;
4383   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4384   PetscValidType(mat, 1);
4385   PetscAssertPointer(M, 4);
4386   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4387   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4388   MatCheckPreallocated(mat, 1);
4389 
4390   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4391   if (flg) newtype = mtype;
4392 
4393   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4394   PetscCall(PetscStrcmp(newtype, "same", &issame));
4395   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4396   if (reuse == MAT_REUSE_MATRIX) {
4397     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4398     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4399   }
4400 
4401   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4402     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4403     PetscFunctionReturn(PETSC_SUCCESS);
4404   }
4405 
4406   /* Cache Mat options because some converters use MatHeaderReplace  */
4407   issymmetric = mat->symmetric;
4408   ishermitian = mat->hermitian;
4409 
4410   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4411     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4412     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4413   } else {
4414     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4415     const char *prefix[3]                                 = {"seq", "mpi", ""};
4416     PetscInt    i;
4417     /*
4418        Order of precedence:
4419        0) See if newtype is a superclass of the current matrix.
4420        1) See if a specialized converter is known to the current matrix.
4421        2) See if a specialized converter is known to the desired matrix class.
4422        3) See if a good general converter is registered for the desired class
4423           (as of 6/27/03 only MATMPIADJ falls into this category).
4424        4) See if a good general converter is known for the current matrix.
4425        5) Use a really basic converter.
4426     */
4427 
4428     /* 0) See if newtype is a superclass of the current matrix.
4429           i.e mat is mpiaij and newtype is aij */
4430     for (i = 0; i < 2; i++) {
4431       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4432       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4433       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4434       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4435       if (flg) {
4436         if (reuse == MAT_INPLACE_MATRIX) {
4437           PetscCall(PetscInfo(mat, "Early return\n"));
4438           PetscFunctionReturn(PETSC_SUCCESS);
4439         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4440           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4441           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4442           PetscFunctionReturn(PETSC_SUCCESS);
4443         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4444           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4445           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4446           PetscFunctionReturn(PETSC_SUCCESS);
4447         }
4448       }
4449     }
4450     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4451     for (i = 0; i < 3; i++) {
4452       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4453       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4454       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4455       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4456       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4457       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4458       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4459       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4460       if (conv) goto foundconv;
4461     }
4462 
4463     /* 2)  See if a specialized converter is known to the desired matrix class. */
4464     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4465     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4466     PetscCall(MatSetType(B, newtype));
4467     for (i = 0; i < 3; i++) {
4468       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4469       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4470       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4471       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4472       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4473       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4474       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4475       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4476       if (conv) {
4477         PetscCall(MatDestroy(&B));
4478         goto foundconv;
4479       }
4480     }
4481 
4482     /* 3) See if a good general converter is registered for the desired class */
4483     conv = B->ops->convertfrom;
4484     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4485     PetscCall(MatDestroy(&B));
4486     if (conv) goto foundconv;
4487 
4488     /* 4) See if a good general converter is known for the current matrix */
4489     if (mat->ops->convert) conv = mat->ops->convert;
4490     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4491     if (conv) goto foundconv;
4492 
4493     /* 5) Use a really basic converter. */
4494     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4495     conv = MatConvert_Basic;
4496 
4497   foundconv:
4498     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4499     PetscCall((*conv)(mat, newtype, reuse, M));
4500     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4501       /* the block sizes must be same if the mappings are copied over */
4502       (*M)->rmap->bs = mat->rmap->bs;
4503       (*M)->cmap->bs = mat->cmap->bs;
4504       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4505       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4506       (*M)->rmap->mapping = mat->rmap->mapping;
4507       (*M)->cmap->mapping = mat->cmap->mapping;
4508     }
4509     (*M)->stencil.dim = mat->stencil.dim;
4510     (*M)->stencil.noc = mat->stencil.noc;
4511     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4512       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4513       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4514     }
4515     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4516   }
4517   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4518 
4519   /* Copy Mat options */
4520   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4521   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4522   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4523   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4524   PetscFunctionReturn(PETSC_SUCCESS);
4525 }
4526 
4527 /*@
4528   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4529 
4530   Not Collective
4531 
4532   Input Parameter:
4533 . mat - the matrix, must be a factored matrix
4534 
4535   Output Parameter:
4536 . type - the string name of the package (do not free this string)
4537 
4538   Level: intermediate
4539 
4540 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4541 @*/
4542 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4543 {
4544   PetscErrorCode (*conv)(Mat, MatSolverType *);
4545 
4546   PetscFunctionBegin;
4547   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4548   PetscValidType(mat, 1);
4549   PetscAssertPointer(type, 2);
4550   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4551   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4552   if (conv) PetscCall((*conv)(mat, type));
4553   else *type = MATSOLVERPETSC;
4554   PetscFunctionReturn(PETSC_SUCCESS);
4555 }
4556 
4557 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4558 struct _MatSolverTypeForSpecifcType {
4559   MatType mtype;
4560   /* no entry for MAT_FACTOR_NONE */
4561   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4562   MatSolverTypeForSpecifcType next;
4563 };
4564 
4565 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4566 struct _MatSolverTypeHolder {
4567   char                       *name;
4568   MatSolverTypeForSpecifcType handlers;
4569   MatSolverTypeHolder         next;
4570 };
4571 
4572 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4573 
4574 /*@C
4575   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4576 
4577   Logically Collective, No Fortran Support
4578 
4579   Input Parameters:
4580 + package      - name of the package, for example `petsc` or `superlu`
4581 . mtype        - the matrix type that works with this package
4582 . ftype        - the type of factorization supported by the package
4583 - createfactor - routine that will create the factored matrix ready to be used
4584 
4585   Level: developer
4586 
4587 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4588   `MatGetFactor()`
4589 @*/
4590 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4591 {
4592   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4593   PetscBool                   flg;
4594   MatSolverTypeForSpecifcType inext, iprev = NULL;
4595 
4596   PetscFunctionBegin;
4597   PetscCall(MatInitializePackage());
4598   if (!next) {
4599     PetscCall(PetscNew(&MatSolverTypeHolders));
4600     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4601     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4602     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4603     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4604     PetscFunctionReturn(PETSC_SUCCESS);
4605   }
4606   while (next) {
4607     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4608     if (flg) {
4609       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4610       inext = next->handlers;
4611       while (inext) {
4612         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4613         if (flg) {
4614           inext->createfactor[(int)ftype - 1] = createfactor;
4615           PetscFunctionReturn(PETSC_SUCCESS);
4616         }
4617         iprev = inext;
4618         inext = inext->next;
4619       }
4620       PetscCall(PetscNew(&iprev->next));
4621       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4622       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4623       PetscFunctionReturn(PETSC_SUCCESS);
4624     }
4625     prev = next;
4626     next = next->next;
4627   }
4628   PetscCall(PetscNew(&prev->next));
4629   PetscCall(PetscStrallocpy(package, &prev->next->name));
4630   PetscCall(PetscNew(&prev->next->handlers));
4631   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4632   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4633   PetscFunctionReturn(PETSC_SUCCESS);
4634 }
4635 
4636 /*@C
4637   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4638 
4639   Input Parameters:
4640 + 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
4641 . ftype - the type of factorization supported by the type
4642 - mtype - the matrix type that works with this type
4643 
4644   Output Parameters:
4645 + foundtype    - `PETSC_TRUE` if the type was registered
4646 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4647 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4648 
4649   Calling sequence of `createfactor`:
4650 + A     - the matrix providing the factor matrix
4651 . ftype - the `MatFactorType` of the factor requested
4652 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4653 
4654   Level: developer
4655 
4656   Note:
4657   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4658   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4659   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4660 
4661 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4662           `MatInitializePackage()`
4663 @*/
4664 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4665 {
4666   MatSolverTypeHolder         next = MatSolverTypeHolders;
4667   PetscBool                   flg;
4668   MatSolverTypeForSpecifcType inext;
4669 
4670   PetscFunctionBegin;
4671   if (foundtype) *foundtype = PETSC_FALSE;
4672   if (foundmtype) *foundmtype = PETSC_FALSE;
4673   if (createfactor) *createfactor = NULL;
4674 
4675   if (type) {
4676     while (next) {
4677       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4678       if (flg) {
4679         if (foundtype) *foundtype = PETSC_TRUE;
4680         inext = next->handlers;
4681         while (inext) {
4682           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4683           if (flg) {
4684             if (foundmtype) *foundmtype = PETSC_TRUE;
4685             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4686             PetscFunctionReturn(PETSC_SUCCESS);
4687           }
4688           inext = inext->next;
4689         }
4690       }
4691       next = next->next;
4692     }
4693   } else {
4694     while (next) {
4695       inext = next->handlers;
4696       while (inext) {
4697         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4698         if (flg && inext->createfactor[(int)ftype - 1]) {
4699           if (foundtype) *foundtype = PETSC_TRUE;
4700           if (foundmtype) *foundmtype = PETSC_TRUE;
4701           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4702           PetscFunctionReturn(PETSC_SUCCESS);
4703         }
4704         inext = inext->next;
4705       }
4706       next = next->next;
4707     }
4708     /* try with base classes inext->mtype */
4709     next = MatSolverTypeHolders;
4710     while (next) {
4711       inext = next->handlers;
4712       while (inext) {
4713         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4714         if (flg && inext->createfactor[(int)ftype - 1]) {
4715           if (foundtype) *foundtype = PETSC_TRUE;
4716           if (foundmtype) *foundmtype = PETSC_TRUE;
4717           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4718           PetscFunctionReturn(PETSC_SUCCESS);
4719         }
4720         inext = inext->next;
4721       }
4722       next = next->next;
4723     }
4724   }
4725   PetscFunctionReturn(PETSC_SUCCESS);
4726 }
4727 
4728 PetscErrorCode MatSolverTypeDestroy(void)
4729 {
4730   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4731   MatSolverTypeForSpecifcType inext, iprev;
4732 
4733   PetscFunctionBegin;
4734   while (next) {
4735     PetscCall(PetscFree(next->name));
4736     inext = next->handlers;
4737     while (inext) {
4738       PetscCall(PetscFree(inext->mtype));
4739       iprev = inext;
4740       inext = inext->next;
4741       PetscCall(PetscFree(iprev));
4742     }
4743     prev = next;
4744     next = next->next;
4745     PetscCall(PetscFree(prev));
4746   }
4747   MatSolverTypeHolders = NULL;
4748   PetscFunctionReturn(PETSC_SUCCESS);
4749 }
4750 
4751 /*@
4752   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4753 
4754   Logically Collective
4755 
4756   Input Parameter:
4757 . mat - the matrix
4758 
4759   Output Parameter:
4760 . flg - `PETSC_TRUE` if uses the ordering
4761 
4762   Level: developer
4763 
4764   Note:
4765   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4766   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4767 
4768 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4769 @*/
4770 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4771 {
4772   PetscFunctionBegin;
4773   *flg = mat->canuseordering;
4774   PetscFunctionReturn(PETSC_SUCCESS);
4775 }
4776 
4777 /*@
4778   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4779 
4780   Logically Collective
4781 
4782   Input Parameters:
4783 + mat   - the matrix obtained with `MatGetFactor()`
4784 - ftype - the factorization type to be used
4785 
4786   Output Parameter:
4787 . otype - the preferred ordering type
4788 
4789   Level: developer
4790 
4791 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4792 @*/
4793 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4794 {
4795   PetscFunctionBegin;
4796   *otype = mat->preferredordering[ftype];
4797   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4798   PetscFunctionReturn(PETSC_SUCCESS);
4799 }
4800 
4801 /*@
4802   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4803 
4804   Collective
4805 
4806   Input Parameters:
4807 + mat   - the matrix
4808 . 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
4809           the other criteria is returned
4810 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4811 
4812   Output Parameter:
4813 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4814 
4815   Options Database Keys:
4816 + -pc_factor_mat_solver_type <type>    - choose the type at run time. When using `KSP` solvers
4817 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device
4818 - -pc_factor_mat_solve_on_host <bool>  - do mat solve on host (with device matrices). Default is doing it on device
4819 
4820   Level: intermediate
4821 
4822   Notes:
4823   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4824   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4825 
4826   Users usually access the factorization solvers via `KSP`
4827 
4828   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4829   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
4830 
4831   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4832   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4833   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4834 
4835   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4836   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4837   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4838 
4839   Developer Note:
4840   This should actually be called `MatCreateFactor()` since it creates a new factor object
4841 
4842 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4843           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4844           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4845 @*/
4846 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4847 {
4848   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4849   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4850 
4851   PetscFunctionBegin;
4852   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4853   PetscValidType(mat, 1);
4854 
4855   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4856   MatCheckPreallocated(mat, 1);
4857 
4858   PetscCall(MatIsShell(mat, &shell));
4859   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4860   if (hasop) {
4861     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4862     PetscFunctionReturn(PETSC_SUCCESS);
4863   }
4864 
4865   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4866   if (!foundtype) {
4867     if (type) {
4868       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],
4869               ((PetscObject)mat)->type_name, type);
4870     } else {
4871       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);
4872     }
4873   }
4874   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4875   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);
4876 
4877   PetscCall((*conv)(mat, ftype, f));
4878   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4879   PetscFunctionReturn(PETSC_SUCCESS);
4880 }
4881 
4882 /*@
4883   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4884 
4885   Not Collective
4886 
4887   Input Parameters:
4888 + mat   - the matrix
4889 . type  - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default)
4890 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4891 
4892   Output Parameter:
4893 . flg - PETSC_TRUE if the factorization is available
4894 
4895   Level: intermediate
4896 
4897   Notes:
4898   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4899   such as pastix, superlu, mumps etc.
4900 
4901   PETSc must have been ./configure to use the external solver, using the option --download-package
4902 
4903   Developer Note:
4904   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4905 
4906 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4907           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4908 @*/
4909 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4910 {
4911   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4912 
4913   PetscFunctionBegin;
4914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4915   PetscAssertPointer(flg, 4);
4916 
4917   *flg = PETSC_FALSE;
4918   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4919 
4920   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4921   MatCheckPreallocated(mat, 1);
4922 
4923   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4924   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4925   PetscFunctionReturn(PETSC_SUCCESS);
4926 }
4927 
4928 /*@
4929   MatDuplicate - Duplicates a matrix including the non-zero structure.
4930 
4931   Collective
4932 
4933   Input Parameters:
4934 + mat - the matrix
4935 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4936         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4937 
4938   Output Parameter:
4939 . M - pointer to place new matrix
4940 
4941   Level: intermediate
4942 
4943   Notes:
4944   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4945 
4946   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4947 
4948   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.
4949 
4950   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4951   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4952   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4953 
4954 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4955 @*/
4956 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4957 {
4958   Mat         B;
4959   VecType     vtype;
4960   PetscInt    i;
4961   PetscObject dm, container_h, container_d;
4962   void (*viewf)(void);
4963 
4964   PetscFunctionBegin;
4965   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4966   PetscValidType(mat, 1);
4967   PetscAssertPointer(M, 3);
4968   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4969   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4970   MatCheckPreallocated(mat, 1);
4971 
4972   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4973   PetscUseTypeMethod(mat, duplicate, op, M);
4974   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4975   B = *M;
4976 
4977   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4978   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4979   PetscCall(MatGetVecType(mat, &vtype));
4980   PetscCall(MatSetVecType(B, vtype));
4981 
4982   B->stencil.dim = mat->stencil.dim;
4983   B->stencil.noc = mat->stencil.noc;
4984   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4985     B->stencil.dims[i]   = mat->stencil.dims[i];
4986     B->stencil.starts[i] = mat->stencil.starts[i];
4987   }
4988 
4989   B->nooffproczerorows = mat->nooffproczerorows;
4990   B->nooffprocentries  = mat->nooffprocentries;
4991 
4992   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4993   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4994   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4995   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4996   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4997   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4998   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
4999   PetscCall(PetscObjectStateIncrease((PetscObject)B));
5000   PetscFunctionReturn(PETSC_SUCCESS);
5001 }
5002 
5003 /*@
5004   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
5005 
5006   Logically Collective
5007 
5008   Input Parameter:
5009 . mat - the matrix
5010 
5011   Output Parameter:
5012 . v - the diagonal of the matrix
5013 
5014   Level: intermediate
5015 
5016   Note:
5017   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5018   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5019   is larger than `ndiag`, the values of the remaining entries are unspecified.
5020 
5021   Currently only correct in parallel for square matrices.
5022 
5023 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5024 @*/
5025 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5026 {
5027   PetscFunctionBegin;
5028   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5029   PetscValidType(mat, 1);
5030   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5031   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5032   MatCheckPreallocated(mat, 1);
5033   if (PetscDefined(USE_DEBUG)) {
5034     PetscInt nv, row, col, ndiag;
5035 
5036     PetscCall(VecGetLocalSize(v, &nv));
5037     PetscCall(MatGetLocalSize(mat, &row, &col));
5038     ndiag = PetscMin(row, col);
5039     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);
5040   }
5041 
5042   PetscUseTypeMethod(mat, getdiagonal, v);
5043   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5044   PetscFunctionReturn(PETSC_SUCCESS);
5045 }
5046 
5047 /*@
5048   MatGetRowMin - Gets the minimum value (of the real part) of each
5049   row of the matrix
5050 
5051   Logically Collective
5052 
5053   Input Parameter:
5054 . mat - the matrix
5055 
5056   Output Parameters:
5057 + v   - the vector for storing the maximums
5058 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5059 
5060   Level: intermediate
5061 
5062   Note:
5063   The result of this call are the same as if one converted the matrix to dense format
5064   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5065 
5066   This code is only implemented for a couple of matrix formats.
5067 
5068 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5069           `MatGetRowMax()`
5070 @*/
5071 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5072 {
5073   PetscFunctionBegin;
5074   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5075   PetscValidType(mat, 1);
5076   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5077   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5078 
5079   if (!mat->cmap->N) {
5080     PetscCall(VecSet(v, PETSC_MAX_REAL));
5081     if (idx) {
5082       PetscInt i, m = mat->rmap->n;
5083       for (i = 0; i < m; i++) idx[i] = -1;
5084     }
5085   } else {
5086     MatCheckPreallocated(mat, 1);
5087   }
5088   PetscUseTypeMethod(mat, getrowmin, v, idx);
5089   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5090   PetscFunctionReturn(PETSC_SUCCESS);
5091 }
5092 
5093 /*@
5094   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5095   row of the matrix
5096 
5097   Logically Collective
5098 
5099   Input Parameter:
5100 . mat - the matrix
5101 
5102   Output Parameters:
5103 + v   - the vector for storing the minimums
5104 - idx - the indices of the column found for each row (or `NULL` if not needed)
5105 
5106   Level: intermediate
5107 
5108   Notes:
5109   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5110   row is 0 (the first column).
5111 
5112   This code is only implemented for a couple of matrix formats.
5113 
5114 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5115 @*/
5116 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5117 {
5118   PetscFunctionBegin;
5119   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5120   PetscValidType(mat, 1);
5121   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5122   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5123   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5124 
5125   if (!mat->cmap->N) {
5126     PetscCall(VecSet(v, 0.0));
5127     if (idx) {
5128       PetscInt i, m = mat->rmap->n;
5129       for (i = 0; i < m; i++) idx[i] = -1;
5130     }
5131   } else {
5132     MatCheckPreallocated(mat, 1);
5133     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5134     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5135   }
5136   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5137   PetscFunctionReturn(PETSC_SUCCESS);
5138 }
5139 
5140 /*@
5141   MatGetRowMax - Gets the maximum value (of the real part) of each
5142   row of the matrix
5143 
5144   Logically Collective
5145 
5146   Input Parameter:
5147 . mat - the matrix
5148 
5149   Output Parameters:
5150 + v   - the vector for storing the maximums
5151 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5152 
5153   Level: intermediate
5154 
5155   Notes:
5156   The result of this call are the same as if one converted the matrix to dense format
5157   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5158 
5159   This code is only implemented for a couple of matrix formats.
5160 
5161 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5162 @*/
5163 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5164 {
5165   PetscFunctionBegin;
5166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5167   PetscValidType(mat, 1);
5168   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5169   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5170 
5171   if (!mat->cmap->N) {
5172     PetscCall(VecSet(v, PETSC_MIN_REAL));
5173     if (idx) {
5174       PetscInt i, m = mat->rmap->n;
5175       for (i = 0; i < m; i++) idx[i] = -1;
5176     }
5177   } else {
5178     MatCheckPreallocated(mat, 1);
5179     PetscUseTypeMethod(mat, getrowmax, v, idx);
5180   }
5181   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5182   PetscFunctionReturn(PETSC_SUCCESS);
5183 }
5184 
5185 /*@
5186   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5187   row of the matrix
5188 
5189   Logically Collective
5190 
5191   Input Parameter:
5192 . mat - the matrix
5193 
5194   Output Parameters:
5195 + v   - the vector for storing the maximums
5196 - idx - the indices of the column found for each row (or `NULL` if not needed)
5197 
5198   Level: intermediate
5199 
5200   Notes:
5201   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5202   row is 0 (the first column).
5203 
5204   This code is only implemented for a couple of matrix formats.
5205 
5206 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5207 @*/
5208 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5209 {
5210   PetscFunctionBegin;
5211   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5212   PetscValidType(mat, 1);
5213   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5214   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5215 
5216   if (!mat->cmap->N) {
5217     PetscCall(VecSet(v, 0.0));
5218     if (idx) {
5219       PetscInt i, m = mat->rmap->n;
5220       for (i = 0; i < m; i++) idx[i] = -1;
5221     }
5222   } else {
5223     MatCheckPreallocated(mat, 1);
5224     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5225     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5226   }
5227   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5228   PetscFunctionReturn(PETSC_SUCCESS);
5229 }
5230 
5231 /*@
5232   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5233 
5234   Logically Collective
5235 
5236   Input Parameter:
5237 . mat - the matrix
5238 
5239   Output Parameter:
5240 . v - the vector for storing the sum
5241 
5242   Level: intermediate
5243 
5244   This code is only implemented for a couple of matrix formats.
5245 
5246 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5247 @*/
5248 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5249 {
5250   PetscFunctionBegin;
5251   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5252   PetscValidType(mat, 1);
5253   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5254   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5255 
5256   if (!mat->cmap->N) {
5257     PetscCall(VecSet(v, 0.0));
5258   } else {
5259     MatCheckPreallocated(mat, 1);
5260     PetscUseTypeMethod(mat, getrowsumabs, v);
5261   }
5262   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5263   PetscFunctionReturn(PETSC_SUCCESS);
5264 }
5265 
5266 /*@
5267   MatGetRowSum - Gets the sum of each row of the matrix
5268 
5269   Logically or Neighborhood Collective
5270 
5271   Input Parameter:
5272 . mat - the matrix
5273 
5274   Output Parameter:
5275 . v - the vector for storing the sum of rows
5276 
5277   Level: intermediate
5278 
5279   Note:
5280   This code is slow since it is not currently specialized for different formats
5281 
5282 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5283 @*/
5284 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5285 {
5286   Vec ones;
5287 
5288   PetscFunctionBegin;
5289   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5290   PetscValidType(mat, 1);
5291   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5292   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5293   MatCheckPreallocated(mat, 1);
5294   PetscCall(MatCreateVecs(mat, &ones, NULL));
5295   PetscCall(VecSet(ones, 1.));
5296   PetscCall(MatMult(mat, ones, v));
5297   PetscCall(VecDestroy(&ones));
5298   PetscFunctionReturn(PETSC_SUCCESS);
5299 }
5300 
5301 /*@
5302   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5303   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5304 
5305   Collective
5306 
5307   Input Parameter:
5308 . mat - the matrix to provide the transpose
5309 
5310   Output Parameter:
5311 . 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
5312 
5313   Level: advanced
5314 
5315   Note:
5316   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
5317   routine allows bypassing that call.
5318 
5319 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5320 @*/
5321 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5322 {
5323   MatParentState *rb = NULL;
5324 
5325   PetscFunctionBegin;
5326   PetscCall(PetscNew(&rb));
5327   rb->id    = ((PetscObject)mat)->id;
5328   rb->state = 0;
5329   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5330   PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault));
5331   PetscFunctionReturn(PETSC_SUCCESS);
5332 }
5333 
5334 /*@
5335   MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5336 
5337   Collective
5338 
5339   Input Parameters:
5340 + mat   - the matrix to transpose
5341 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5342 
5343   Output Parameter:
5344 . B - the transpose of the matrix
5345 
5346   Level: intermediate
5347 
5348   Notes:
5349   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5350 
5351   `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
5352   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5353 
5354   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.
5355 
5356   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5357   For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5358 
5359   If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5360 
5361   If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5362 
5363 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5364           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5365 @*/
5366 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5367 {
5368   PetscContainer  rB = NULL;
5369   MatParentState *rb = NULL;
5370 
5371   PetscFunctionBegin;
5372   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5373   PetscValidType(mat, 1);
5374   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5375   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5376   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5377   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5378   MatCheckPreallocated(mat, 1);
5379   if (reuse == MAT_REUSE_MATRIX) {
5380     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5381     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5382     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5383     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5384     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5385   }
5386 
5387   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5388   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5389     PetscUseTypeMethod(mat, transpose, reuse, B);
5390     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5391   }
5392   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5393 
5394   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5395   if (reuse != MAT_INPLACE_MATRIX) {
5396     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5397     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5398     rb->state        = ((PetscObject)mat)->state;
5399     rb->nonzerostate = mat->nonzerostate;
5400   }
5401   PetscFunctionReturn(PETSC_SUCCESS);
5402 }
5403 
5404 /*@
5405   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5406 
5407   Collective
5408 
5409   Input Parameter:
5410 . A - the matrix to transpose
5411 
5412   Output Parameter:
5413 . 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
5414       numerical portion.
5415 
5416   Level: intermediate
5417 
5418   Note:
5419   This is not supported for many matrix types, use `MatTranspose()` in those cases
5420 
5421 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5422 @*/
5423 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5424 {
5425   PetscFunctionBegin;
5426   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5427   PetscValidType(A, 1);
5428   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5429   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5430   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5431   PetscUseTypeMethod(A, transposesymbolic, B);
5432   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5433 
5434   PetscCall(MatTransposeSetPrecursor(A, *B));
5435   PetscFunctionReturn(PETSC_SUCCESS);
5436 }
5437 
5438 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5439 {
5440   PetscContainer  rB;
5441   MatParentState *rb;
5442 
5443   PetscFunctionBegin;
5444   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5445   PetscValidType(A, 1);
5446   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5447   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5448   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5449   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5450   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5451   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5452   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5453   PetscFunctionReturn(PETSC_SUCCESS);
5454 }
5455 
5456 /*@
5457   MatIsTranspose - Test whether a matrix is another one's transpose,
5458   or its own, in which case it tests symmetry.
5459 
5460   Collective
5461 
5462   Input Parameters:
5463 + A   - the matrix to test
5464 . B   - the matrix to test against, this can equal the first parameter
5465 - tol - tolerance, differences between entries smaller than this are counted as zero
5466 
5467   Output Parameter:
5468 . flg - the result
5469 
5470   Level: intermediate
5471 
5472   Notes:
5473   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5474   test involves parallel copies of the block off-diagonal parts of the matrix.
5475 
5476 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5477 @*/
5478 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5479 {
5480   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5481 
5482   PetscFunctionBegin;
5483   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5484   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5485   PetscAssertPointer(flg, 4);
5486   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5487   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5488   *flg = PETSC_FALSE;
5489   if (f && g) {
5490     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5491     PetscCall((*f)(A, B, tol, flg));
5492   } else {
5493     MatType mattype;
5494 
5495     PetscCall(MatGetType(f ? B : A, &mattype));
5496     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5497   }
5498   PetscFunctionReturn(PETSC_SUCCESS);
5499 }
5500 
5501 /*@
5502   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5503 
5504   Collective
5505 
5506   Input Parameters:
5507 + mat   - the matrix to transpose and complex conjugate
5508 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5509 
5510   Output Parameter:
5511 . B - the Hermitian transpose
5512 
5513   Level: intermediate
5514 
5515 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5516 @*/
5517 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5518 {
5519   PetscFunctionBegin;
5520   PetscCall(MatTranspose(mat, reuse, B));
5521 #if defined(PETSC_USE_COMPLEX)
5522   PetscCall(MatConjugate(*B));
5523 #endif
5524   PetscFunctionReturn(PETSC_SUCCESS);
5525 }
5526 
5527 /*@
5528   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5529 
5530   Collective
5531 
5532   Input Parameters:
5533 + A   - the matrix to test
5534 . B   - the matrix to test against, this can equal the first parameter
5535 - tol - tolerance, differences between entries smaller than this are counted as zero
5536 
5537   Output Parameter:
5538 . flg - the result
5539 
5540   Level: intermediate
5541 
5542   Notes:
5543   Only available for `MATAIJ` matrices.
5544 
5545   The sequential algorithm
5546   has a running time of the order of the number of nonzeros; the parallel
5547   test involves parallel copies of the block off-diagonal parts of the matrix.
5548 
5549 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5550 @*/
5551 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5552 {
5553   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5554 
5555   PetscFunctionBegin;
5556   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5557   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5558   PetscAssertPointer(flg, 4);
5559   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5560   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5561   if (f && g) {
5562     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5563     PetscCall((*f)(A, B, tol, flg));
5564   }
5565   PetscFunctionReturn(PETSC_SUCCESS);
5566 }
5567 
5568 /*@
5569   MatPermute - Creates a new matrix with rows and columns permuted from the
5570   original.
5571 
5572   Collective
5573 
5574   Input Parameters:
5575 + mat - the matrix to permute
5576 . row - row permutation, each processor supplies only the permutation for its rows
5577 - col - column permutation, each processor supplies only the permutation for its columns
5578 
5579   Output Parameter:
5580 . B - the permuted matrix
5581 
5582   Level: advanced
5583 
5584   Note:
5585   The index sets map from row/col of permuted matrix to row/col of original matrix.
5586   The index sets should be on the same communicator as mat and have the same local sizes.
5587 
5588   Developer Note:
5589   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5590   exploit the fact that row and col are permutations, consider implementing the
5591   more general `MatCreateSubMatrix()` instead.
5592 
5593 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5594 @*/
5595 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5596 {
5597   PetscFunctionBegin;
5598   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5599   PetscValidType(mat, 1);
5600   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5601   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5602   PetscAssertPointer(B, 4);
5603   PetscCheckSameComm(mat, 1, row, 2);
5604   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5605   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5606   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5607   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5608   MatCheckPreallocated(mat, 1);
5609 
5610   if (mat->ops->permute) {
5611     PetscUseTypeMethod(mat, permute, row, col, B);
5612     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5613   } else {
5614     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5615   }
5616   PetscFunctionReturn(PETSC_SUCCESS);
5617 }
5618 
5619 /*@
5620   MatEqual - Compares two matrices.
5621 
5622   Collective
5623 
5624   Input Parameters:
5625 + A - the first matrix
5626 - B - the second matrix
5627 
5628   Output Parameter:
5629 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5630 
5631   Level: intermediate
5632 
5633   Note:
5634   If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product
5635   using several randomly created vectors, see `MatMultEqual()`.
5636 
5637 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()`
5638 @*/
5639 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5640 {
5641   PetscFunctionBegin;
5642   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5643   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5644   PetscValidType(A, 1);
5645   PetscValidType(B, 2);
5646   PetscAssertPointer(flg, 3);
5647   PetscCheckSameComm(A, 1, B, 2);
5648   MatCheckPreallocated(A, 1);
5649   MatCheckPreallocated(B, 2);
5650   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5651   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5652   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,
5653              B->cmap->N);
5654   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5655     PetscUseTypeMethod(A, equal, B, flg);
5656   } else {
5657     PetscCall(MatMultEqual(A, B, 10, flg));
5658   }
5659   PetscFunctionReturn(PETSC_SUCCESS);
5660 }
5661 
5662 /*@
5663   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5664   matrices that are stored as vectors.  Either of the two scaling
5665   matrices can be `NULL`.
5666 
5667   Collective
5668 
5669   Input Parameters:
5670 + mat - the matrix to be scaled
5671 . l   - the left scaling vector (or `NULL`)
5672 - r   - the right scaling vector (or `NULL`)
5673 
5674   Level: intermediate
5675 
5676   Note:
5677   `MatDiagonalScale()` computes $A = LAR$, where
5678   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5679   The L scales the rows of the matrix, the R scales the columns of the matrix.
5680 
5681 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5682 @*/
5683 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5684 {
5685   PetscFunctionBegin;
5686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5687   PetscValidType(mat, 1);
5688   if (l) {
5689     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5690     PetscCheckSameComm(mat, 1, l, 2);
5691   }
5692   if (r) {
5693     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5694     PetscCheckSameComm(mat, 1, r, 3);
5695   }
5696   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5697   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5698   MatCheckPreallocated(mat, 1);
5699   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5700 
5701   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5702   PetscUseTypeMethod(mat, diagonalscale, l, r);
5703   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5704   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5705   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5706   PetscFunctionReturn(PETSC_SUCCESS);
5707 }
5708 
5709 /*@
5710   MatScale - Scales all elements of a matrix by a given number.
5711 
5712   Logically Collective
5713 
5714   Input Parameters:
5715 + mat - the matrix to be scaled
5716 - a   - the scaling value
5717 
5718   Level: intermediate
5719 
5720 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5721 @*/
5722 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5723 {
5724   PetscFunctionBegin;
5725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5726   PetscValidType(mat, 1);
5727   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5728   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5729   PetscValidLogicalCollectiveScalar(mat, a, 2);
5730   MatCheckPreallocated(mat, 1);
5731 
5732   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5733   if (a != (PetscScalar)1.0) {
5734     PetscUseTypeMethod(mat, scale, a);
5735     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5736   }
5737   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5738   PetscFunctionReturn(PETSC_SUCCESS);
5739 }
5740 
5741 /*@
5742   MatNorm - Calculates various norms of a matrix.
5743 
5744   Collective
5745 
5746   Input Parameters:
5747 + mat  - the matrix
5748 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5749 
5750   Output Parameter:
5751 . nrm - the resulting norm
5752 
5753   Level: intermediate
5754 
5755 .seealso: [](ch_matrices), `Mat`
5756 @*/
5757 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5758 {
5759   PetscFunctionBegin;
5760   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5761   PetscValidType(mat, 1);
5762   PetscAssertPointer(nrm, 3);
5763 
5764   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5765   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5766   MatCheckPreallocated(mat, 1);
5767 
5768   PetscUseTypeMethod(mat, norm, type, nrm);
5769   PetscFunctionReturn(PETSC_SUCCESS);
5770 }
5771 
5772 /*
5773      This variable is used to prevent counting of MatAssemblyBegin() that
5774    are called from within a MatAssemblyEnd().
5775 */
5776 static PetscInt MatAssemblyEnd_InUse = 0;
5777 /*@
5778   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5779   be called after completing all calls to `MatSetValues()`.
5780 
5781   Collective
5782 
5783   Input Parameters:
5784 + mat  - the matrix
5785 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5786 
5787   Level: beginner
5788 
5789   Notes:
5790   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5791   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5792 
5793   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5794   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5795   using the matrix.
5796 
5797   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5798   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
5799   a global collective operation requiring all processes that share the matrix.
5800 
5801   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5802   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5803   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5804 
5805 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5806 @*/
5807 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5808 {
5809   PetscFunctionBegin;
5810   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5811   PetscValidType(mat, 1);
5812   MatCheckPreallocated(mat, 1);
5813   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5814   if (mat->assembled) {
5815     mat->was_assembled = PETSC_TRUE;
5816     mat->assembled     = PETSC_FALSE;
5817   }
5818 
5819   if (!MatAssemblyEnd_InUse) {
5820     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5821     PetscTryTypeMethod(mat, assemblybegin, type);
5822     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5823   } else PetscTryTypeMethod(mat, assemblybegin, type);
5824   PetscFunctionReturn(PETSC_SUCCESS);
5825 }
5826 
5827 /*@
5828   MatAssembled - Indicates if a matrix has been assembled and is ready for
5829   use; for example, in matrix-vector product.
5830 
5831   Not Collective
5832 
5833   Input Parameter:
5834 . mat - the matrix
5835 
5836   Output Parameter:
5837 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5838 
5839   Level: advanced
5840 
5841 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5842 @*/
5843 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5844 {
5845   PetscFunctionBegin;
5846   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5847   PetscAssertPointer(assembled, 2);
5848   *assembled = mat->assembled;
5849   PetscFunctionReturn(PETSC_SUCCESS);
5850 }
5851 
5852 /*@
5853   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5854   be called after `MatAssemblyBegin()`.
5855 
5856   Collective
5857 
5858   Input Parameters:
5859 + mat  - the matrix
5860 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5861 
5862   Options Database Keys:
5863 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5864 . -mat_view ::ascii_info_detail      - Prints more detailed info
5865 . -mat_view                          - Prints matrix in ASCII format
5866 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5867 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5868 . -display <name>                    - Sets display name (default is host)
5869 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5870 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5871 . -viewer_socket_machine <machine>   - Machine to use for socket
5872 . -viewer_socket_port <port>         - Port number to use for socket
5873 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5874 
5875   Level: beginner
5876 
5877 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5878 @*/
5879 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5880 {
5881   static PetscInt inassm = 0;
5882   PetscBool       flg    = PETSC_FALSE;
5883 
5884   PetscFunctionBegin;
5885   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5886   PetscValidType(mat, 1);
5887 
5888   inassm++;
5889   MatAssemblyEnd_InUse++;
5890   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5891     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5892     PetscTryTypeMethod(mat, assemblyend, type);
5893     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5894   } else PetscTryTypeMethod(mat, assemblyend, type);
5895 
5896   /* Flush assembly is not a true assembly */
5897   if (type != MAT_FLUSH_ASSEMBLY) {
5898     if (mat->num_ass) {
5899       if (!mat->symmetry_eternal) {
5900         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5901         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5902       }
5903       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5904       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5905     }
5906     mat->num_ass++;
5907     mat->assembled        = PETSC_TRUE;
5908     mat->ass_nonzerostate = mat->nonzerostate;
5909   }
5910 
5911   mat->insertmode = NOT_SET_VALUES;
5912   MatAssemblyEnd_InUse--;
5913   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5914   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5915     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5916 
5917     if (mat->checksymmetryonassembly) {
5918       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5919       if (flg) {
5920         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5921       } else {
5922         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5923       }
5924     }
5925     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5926   }
5927   inassm--;
5928   PetscFunctionReturn(PETSC_SUCCESS);
5929 }
5930 
5931 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5932 /*@
5933   MatSetOption - Sets a parameter option for a matrix. Some options
5934   may be specific to certain storage formats.  Some options
5935   determine how values will be inserted (or added). Sorted,
5936   row-oriented input will generally assemble the fastest. The default
5937   is row-oriented.
5938 
5939   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5940 
5941   Input Parameters:
5942 + mat - the matrix
5943 . op  - the option, one of those listed below (and possibly others),
5944 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5945 
5946   Options Describing Matrix Structure:
5947 + `MAT_SPD`                         - symmetric positive definite
5948 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5949 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5950 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5951 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5952 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5953 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5954 
5955    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5956    do not need to be computed (usually at a high cost)
5957 
5958    Options For Use with `MatSetValues()`:
5959    Insert a logically dense subblock, which can be
5960 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5961 
5962    These options reflect the data you pass in with `MatSetValues()`; it has
5963    nothing to do with how the data is stored internally in the matrix
5964    data structure.
5965 
5966    When (re)assembling a matrix, we can restrict the input for
5967    efficiency/debugging purposes.  These options include
5968 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5969 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5970 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5971 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5972 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5973 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5974         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5975         performance for very large process counts.
5976 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5977         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5978         functions, instead sending only neighbor messages.
5979 
5980   Level: intermediate
5981 
5982   Notes:
5983   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5984 
5985   Some options are relevant only for particular matrix types and
5986   are thus ignored by others.  Other options are not supported by
5987   certain matrix types and will generate an error message if set.
5988 
5989   If using Fortran to compute a matrix, one may need to
5990   use the column-oriented option (or convert to the row-oriented
5991   format).
5992 
5993   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5994   that would generate a new entry in the nonzero structure is instead
5995   ignored.  Thus, if memory has not already been allocated for this particular
5996   data, then the insertion is ignored. For dense matrices, in which
5997   the entire array is allocated, no entries are ever ignored.
5998   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5999 
6000   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
6001   that would generate a new entry in the nonzero structure instead produces
6002   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
6003 
6004   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
6005   that would generate a new entry that has not been preallocated will
6006   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
6007   only.) This is a useful flag when debugging matrix memory preallocation.
6008   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6009 
6010   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
6011   other processors should be dropped, rather than stashed.
6012   This is useful if you know that the "owning" processor is also
6013   always generating the correct matrix entries, so that PETSc need
6014   not transfer duplicate entries generated on another processor.
6015 
6016   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6017   searches during matrix assembly. When this flag is set, the hash table
6018   is created during the first matrix assembly. This hash table is
6019   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6020   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6021   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6022   supported by `MATMPIBAIJ` format only.
6023 
6024   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6025   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6026 
6027   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6028   a zero location in the matrix
6029 
6030   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6031 
6032   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6033   zero row routines and thus improves performance for very large process counts.
6034 
6035   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6036   part of the matrix (since they should match the upper triangular part).
6037 
6038   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6039   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6040   with finite difference schemes with non-periodic boundary conditions.
6041 
6042   Developer Note:
6043   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6044   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6045   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6046   not changed.
6047 
6048 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6049 @*/
6050 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6051 {
6052   PetscFunctionBegin;
6053   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6054   if (op > 0) {
6055     PetscValidLogicalCollectiveEnum(mat, op, 2);
6056     PetscValidLogicalCollectiveBool(mat, flg, 3);
6057   }
6058 
6059   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);
6060 
6061   switch (op) {
6062   case MAT_FORCE_DIAGONAL_ENTRIES:
6063     mat->force_diagonals = flg;
6064     PetscFunctionReturn(PETSC_SUCCESS);
6065   case MAT_NO_OFF_PROC_ENTRIES:
6066     mat->nooffprocentries = flg;
6067     PetscFunctionReturn(PETSC_SUCCESS);
6068   case MAT_SUBSET_OFF_PROC_ENTRIES:
6069     mat->assembly_subset = flg;
6070     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6071 #if !defined(PETSC_HAVE_MPIUNI)
6072       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6073 #endif
6074       mat->stash.first_assembly_done = PETSC_FALSE;
6075     }
6076     PetscFunctionReturn(PETSC_SUCCESS);
6077   case MAT_NO_OFF_PROC_ZERO_ROWS:
6078     mat->nooffproczerorows = flg;
6079     PetscFunctionReturn(PETSC_SUCCESS);
6080   case MAT_SPD:
6081     if (flg) {
6082       mat->spd                    = PETSC_BOOL3_TRUE;
6083       mat->symmetric              = PETSC_BOOL3_TRUE;
6084       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6085     } else {
6086       mat->spd = PETSC_BOOL3_FALSE;
6087     }
6088     break;
6089   case MAT_SYMMETRIC:
6090     mat->symmetric = PetscBoolToBool3(flg);
6091     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6092 #if !defined(PETSC_USE_COMPLEX)
6093     mat->hermitian = PetscBoolToBool3(flg);
6094 #endif
6095     break;
6096   case MAT_HERMITIAN:
6097     mat->hermitian = PetscBoolToBool3(flg);
6098     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6099 #if !defined(PETSC_USE_COMPLEX)
6100     mat->symmetric = PetscBoolToBool3(flg);
6101 #endif
6102     break;
6103   case MAT_STRUCTURALLY_SYMMETRIC:
6104     mat->structurally_symmetric = PetscBoolToBool3(flg);
6105     break;
6106   case MAT_SYMMETRY_ETERNAL:
6107     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");
6108     mat->symmetry_eternal = flg;
6109     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6110     break;
6111   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6112     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");
6113     mat->structural_symmetry_eternal = flg;
6114     break;
6115   case MAT_SPD_ETERNAL:
6116     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");
6117     mat->spd_eternal = flg;
6118     if (flg) {
6119       mat->structural_symmetry_eternal = PETSC_TRUE;
6120       mat->symmetry_eternal            = PETSC_TRUE;
6121     }
6122     break;
6123   case MAT_STRUCTURE_ONLY:
6124     mat->structure_only = flg;
6125     break;
6126   case MAT_SORTED_FULL:
6127     mat->sortedfull = flg;
6128     break;
6129   default:
6130     break;
6131   }
6132   PetscTryTypeMethod(mat, setoption, op, flg);
6133   PetscFunctionReturn(PETSC_SUCCESS);
6134 }
6135 
6136 /*@
6137   MatGetOption - Gets a parameter option that has been set for a matrix.
6138 
6139   Logically Collective
6140 
6141   Input Parameters:
6142 + mat - the matrix
6143 - op  - the option, this only responds to certain options, check the code for which ones
6144 
6145   Output Parameter:
6146 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6147 
6148   Level: intermediate
6149 
6150   Notes:
6151   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6152 
6153   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6154   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6155 
6156 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6157     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6158 @*/
6159 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6160 {
6161   PetscFunctionBegin;
6162   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6163   PetscValidType(mat, 1);
6164 
6165   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);
6166   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()");
6167 
6168   switch (op) {
6169   case MAT_NO_OFF_PROC_ENTRIES:
6170     *flg = mat->nooffprocentries;
6171     break;
6172   case MAT_NO_OFF_PROC_ZERO_ROWS:
6173     *flg = mat->nooffproczerorows;
6174     break;
6175   case MAT_SYMMETRIC:
6176     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6177     break;
6178   case MAT_HERMITIAN:
6179     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6180     break;
6181   case MAT_STRUCTURALLY_SYMMETRIC:
6182     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6183     break;
6184   case MAT_SPD:
6185     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6186     break;
6187   case MAT_SYMMETRY_ETERNAL:
6188     *flg = mat->symmetry_eternal;
6189     break;
6190   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6191     *flg = mat->symmetry_eternal;
6192     break;
6193   default:
6194     break;
6195   }
6196   PetscFunctionReturn(PETSC_SUCCESS);
6197 }
6198 
6199 /*@
6200   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6201   this routine retains the old nonzero structure.
6202 
6203   Logically Collective
6204 
6205   Input Parameter:
6206 . mat - the matrix
6207 
6208   Level: intermediate
6209 
6210   Note:
6211   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.
6212   See the Performance chapter of the users manual for information on preallocating matrices.
6213 
6214 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6215 @*/
6216 PetscErrorCode MatZeroEntries(Mat mat)
6217 {
6218   PetscFunctionBegin;
6219   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6220   PetscValidType(mat, 1);
6221   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6222   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");
6223   MatCheckPreallocated(mat, 1);
6224 
6225   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6226   PetscUseTypeMethod(mat, zeroentries);
6227   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6228   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6229   PetscFunctionReturn(PETSC_SUCCESS);
6230 }
6231 
6232 /*@
6233   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6234   of a set of rows and columns of a matrix.
6235 
6236   Collective
6237 
6238   Input Parameters:
6239 + mat     - the matrix
6240 . numRows - the number of rows/columns to zero
6241 . rows    - the global row indices
6242 . diag    - value put in the diagonal of the eliminated rows
6243 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6244 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6245 
6246   Level: intermediate
6247 
6248   Notes:
6249   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6250 
6251   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6252   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
6253 
6254   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6255   Krylov method to take advantage of the known solution on the zeroed rows.
6256 
6257   For the parallel case, all processes that share the matrix (i.e.,
6258   those in the communicator used for matrix creation) MUST call this
6259   routine, regardless of whether any rows being zeroed are owned by
6260   them.
6261 
6262   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6263   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
6264   missing.
6265 
6266   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6267   list only rows local to itself).
6268 
6269   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6270 
6271 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6272           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6273 @*/
6274 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6275 {
6276   PetscFunctionBegin;
6277   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6278   PetscValidType(mat, 1);
6279   if (numRows) PetscAssertPointer(rows, 3);
6280   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6281   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6282   MatCheckPreallocated(mat, 1);
6283 
6284   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6285   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6286   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6287   PetscFunctionReturn(PETSC_SUCCESS);
6288 }
6289 
6290 /*@
6291   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6292   of a set of rows and columns of a matrix.
6293 
6294   Collective
6295 
6296   Input Parameters:
6297 + mat  - the matrix
6298 . is   - the rows to zero
6299 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6300 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6301 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6302 
6303   Level: intermediate
6304 
6305   Note:
6306   See `MatZeroRowsColumns()` for details on how this routine operates.
6307 
6308 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6309           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6310 @*/
6311 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6312 {
6313   PetscInt        numRows;
6314   const PetscInt *rows;
6315 
6316   PetscFunctionBegin;
6317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6318   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6319   PetscValidType(mat, 1);
6320   PetscValidType(is, 2);
6321   PetscCall(ISGetLocalSize(is, &numRows));
6322   PetscCall(ISGetIndices(is, &rows));
6323   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6324   PetscCall(ISRestoreIndices(is, &rows));
6325   PetscFunctionReturn(PETSC_SUCCESS);
6326 }
6327 
6328 /*@
6329   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6330   of a set of rows of a matrix.
6331 
6332   Collective
6333 
6334   Input Parameters:
6335 + mat     - the matrix
6336 . numRows - the number of rows to zero
6337 . rows    - the global row indices
6338 . diag    - value put in the diagonal of the zeroed rows
6339 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6340 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6341 
6342   Level: intermediate
6343 
6344   Notes:
6345   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6346 
6347   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6348 
6349   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6350   Krylov method to take advantage of the known solution on the zeroed rows.
6351 
6352   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)
6353   from the matrix.
6354 
6355   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6356   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6357   formats this does not alter the nonzero structure.
6358 
6359   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6360   of the matrix is not changed the values are
6361   merely zeroed.
6362 
6363   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6364   formats can optionally remove the main diagonal entry from the
6365   nonzero structure as well, by passing 0.0 as the final argument).
6366 
6367   For the parallel case, all processes that share the matrix (i.e.,
6368   those in the communicator used for matrix creation) MUST call this
6369   routine, regardless of whether any rows being zeroed are owned by
6370   them.
6371 
6372   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6373   list only rows local to itself).
6374 
6375   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6376   owns that are to be zeroed. This saves a global synchronization in the implementation.
6377 
6378 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6379           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6380 @*/
6381 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6382 {
6383   PetscFunctionBegin;
6384   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6385   PetscValidType(mat, 1);
6386   if (numRows) PetscAssertPointer(rows, 3);
6387   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6388   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6389   MatCheckPreallocated(mat, 1);
6390 
6391   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6392   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6393   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6394   PetscFunctionReturn(PETSC_SUCCESS);
6395 }
6396 
6397 /*@
6398   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6399   of a set of rows of a matrix indicated by an `IS`
6400 
6401   Collective
6402 
6403   Input Parameters:
6404 + mat  - the matrix
6405 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6406 . diag - value put in all diagonals of eliminated rows
6407 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6408 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6409 
6410   Level: intermediate
6411 
6412   Note:
6413   See `MatZeroRows()` for details on how this routine operates.
6414 
6415 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6416           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6417 @*/
6418 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6419 {
6420   PetscInt        numRows = 0;
6421   const PetscInt *rows    = NULL;
6422 
6423   PetscFunctionBegin;
6424   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6425   PetscValidType(mat, 1);
6426   if (is) {
6427     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6428     PetscCall(ISGetLocalSize(is, &numRows));
6429     PetscCall(ISGetIndices(is, &rows));
6430   }
6431   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6432   if (is) PetscCall(ISRestoreIndices(is, &rows));
6433   PetscFunctionReturn(PETSC_SUCCESS);
6434 }
6435 
6436 /*@
6437   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6438   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6439 
6440   Collective
6441 
6442   Input Parameters:
6443 + mat     - the matrix
6444 . numRows - the number of rows to remove
6445 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6446 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6447 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6448 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6449 
6450   Level: intermediate
6451 
6452   Notes:
6453   See `MatZeroRows()` for details on how this routine operates.
6454 
6455   The grid coordinates are across the entire grid, not just the local portion
6456 
6457   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6458   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6459   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6460   `DM_BOUNDARY_PERIODIC` boundary type.
6461 
6462   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
6463   a single value per point) you can skip filling those indices.
6464 
6465   Fortran Note:
6466   `idxm` and `idxn` should be declared as
6467 .vb
6468     MatStencil idxm(4, m)
6469 .ve
6470   and the values inserted using
6471 .vb
6472     idxm(MatStencil_i, 1) = i
6473     idxm(MatStencil_j, 1) = j
6474     idxm(MatStencil_k, 1) = k
6475     idxm(MatStencil_c, 1) = c
6476    etc
6477 .ve
6478 
6479 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6480           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6481 @*/
6482 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6483 {
6484   PetscInt  dim    = mat->stencil.dim;
6485   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6486   PetscInt *dims   = mat->stencil.dims + 1;
6487   PetscInt *starts = mat->stencil.starts;
6488   PetscInt *dxm    = (PetscInt *)rows;
6489   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6490 
6491   PetscFunctionBegin;
6492   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6493   PetscValidType(mat, 1);
6494   if (numRows) PetscAssertPointer(rows, 3);
6495 
6496   PetscCall(PetscMalloc1(numRows, &jdxm));
6497   for (i = 0; i < numRows; ++i) {
6498     /* Skip unused dimensions (they are ordered k, j, i, c) */
6499     for (j = 0; j < 3 - sdim; ++j) dxm++;
6500     /* Local index in X dir */
6501     tmp = *dxm++ - starts[0];
6502     /* Loop over remaining dimensions */
6503     for (j = 0; j < dim - 1; ++j) {
6504       /* If nonlocal, set index to be negative */
6505       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6506       /* Update local index */
6507       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6508     }
6509     /* Skip component slot if necessary */
6510     if (mat->stencil.noc) dxm++;
6511     /* Local row number */
6512     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6513   }
6514   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6515   PetscCall(PetscFree(jdxm));
6516   PetscFunctionReturn(PETSC_SUCCESS);
6517 }
6518 
6519 /*@
6520   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6521   of a set of rows and columns of a matrix.
6522 
6523   Collective
6524 
6525   Input Parameters:
6526 + mat     - the matrix
6527 . numRows - the number of rows/columns to remove
6528 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6529 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6530 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6531 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6532 
6533   Level: intermediate
6534 
6535   Notes:
6536   See `MatZeroRowsColumns()` for details on how this routine operates.
6537 
6538   The grid coordinates are across the entire grid, not just the local portion
6539 
6540   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6541   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6542   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6543   `DM_BOUNDARY_PERIODIC` boundary type.
6544 
6545   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
6546   a single value per point) you can skip filling those indices.
6547 
6548   Fortran Note:
6549   `idxm` and `idxn` should be declared as
6550 .vb
6551     MatStencil idxm(4, m)
6552 .ve
6553   and the values inserted using
6554 .vb
6555     idxm(MatStencil_i, 1) = i
6556     idxm(MatStencil_j, 1) = j
6557     idxm(MatStencil_k, 1) = k
6558     idxm(MatStencil_c, 1) = c
6559     etc
6560 .ve
6561 
6562 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6563           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6564 @*/
6565 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6566 {
6567   PetscInt  dim    = mat->stencil.dim;
6568   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6569   PetscInt *dims   = mat->stencil.dims + 1;
6570   PetscInt *starts = mat->stencil.starts;
6571   PetscInt *dxm    = (PetscInt *)rows;
6572   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6573 
6574   PetscFunctionBegin;
6575   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6576   PetscValidType(mat, 1);
6577   if (numRows) PetscAssertPointer(rows, 3);
6578 
6579   PetscCall(PetscMalloc1(numRows, &jdxm));
6580   for (i = 0; i < numRows; ++i) {
6581     /* Skip unused dimensions (they are ordered k, j, i, c) */
6582     for (j = 0; j < 3 - sdim; ++j) dxm++;
6583     /* Local index in X dir */
6584     tmp = *dxm++ - starts[0];
6585     /* Loop over remaining dimensions */
6586     for (j = 0; j < dim - 1; ++j) {
6587       /* If nonlocal, set index to be negative */
6588       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6589       /* Update local index */
6590       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6591     }
6592     /* Skip component slot if necessary */
6593     if (mat->stencil.noc) dxm++;
6594     /* Local row number */
6595     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6596   }
6597   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6598   PetscCall(PetscFree(jdxm));
6599   PetscFunctionReturn(PETSC_SUCCESS);
6600 }
6601 
6602 /*@
6603   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6604   of a set of rows of a matrix; using local numbering of rows.
6605 
6606   Collective
6607 
6608   Input Parameters:
6609 + mat     - the matrix
6610 . numRows - the number of rows to remove
6611 . rows    - the local row indices
6612 . diag    - value put in all diagonals of eliminated rows
6613 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6614 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6615 
6616   Level: intermediate
6617 
6618   Notes:
6619   Before calling `MatZeroRowsLocal()`, the user must first set the
6620   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6621 
6622   See `MatZeroRows()` for details on how this routine operates.
6623 
6624 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6625           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6626 @*/
6627 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6628 {
6629   PetscFunctionBegin;
6630   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6631   PetscValidType(mat, 1);
6632   if (numRows) PetscAssertPointer(rows, 3);
6633   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6634   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6635   MatCheckPreallocated(mat, 1);
6636 
6637   if (mat->ops->zerorowslocal) {
6638     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6639   } else {
6640     IS              is, newis;
6641     const PetscInt *newRows;
6642 
6643     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6644     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6645     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6646     PetscCall(ISGetIndices(newis, &newRows));
6647     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6648     PetscCall(ISRestoreIndices(newis, &newRows));
6649     PetscCall(ISDestroy(&newis));
6650     PetscCall(ISDestroy(&is));
6651   }
6652   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6653   PetscFunctionReturn(PETSC_SUCCESS);
6654 }
6655 
6656 /*@
6657   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6658   of a set of rows of a matrix; using local numbering of rows.
6659 
6660   Collective
6661 
6662   Input Parameters:
6663 + mat  - the matrix
6664 . is   - index set of rows to remove
6665 . diag - value put in all diagonals of eliminated rows
6666 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6667 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6668 
6669   Level: intermediate
6670 
6671   Notes:
6672   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6673   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6674 
6675   See `MatZeroRows()` for details on how this routine operates.
6676 
6677 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6678           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6679 @*/
6680 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6681 {
6682   PetscInt        numRows;
6683   const PetscInt *rows;
6684 
6685   PetscFunctionBegin;
6686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6687   PetscValidType(mat, 1);
6688   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6689   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6690   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6691   MatCheckPreallocated(mat, 1);
6692 
6693   PetscCall(ISGetLocalSize(is, &numRows));
6694   PetscCall(ISGetIndices(is, &rows));
6695   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6696   PetscCall(ISRestoreIndices(is, &rows));
6697   PetscFunctionReturn(PETSC_SUCCESS);
6698 }
6699 
6700 /*@
6701   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6702   of a set of rows and columns of a matrix; using local numbering of rows.
6703 
6704   Collective
6705 
6706   Input Parameters:
6707 + mat     - the matrix
6708 . numRows - the number of rows to remove
6709 . rows    - the global row indices
6710 . diag    - value put in all diagonals of eliminated rows
6711 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6712 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6713 
6714   Level: intermediate
6715 
6716   Notes:
6717   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6718   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6719 
6720   See `MatZeroRowsColumns()` for details on how this routine operates.
6721 
6722 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6723           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6724 @*/
6725 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6726 {
6727   IS              is, newis;
6728   const PetscInt *newRows;
6729 
6730   PetscFunctionBegin;
6731   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6732   PetscValidType(mat, 1);
6733   if (numRows) PetscAssertPointer(rows, 3);
6734   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6735   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6736   MatCheckPreallocated(mat, 1);
6737 
6738   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6739   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6740   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6741   PetscCall(ISGetIndices(newis, &newRows));
6742   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6743   PetscCall(ISRestoreIndices(newis, &newRows));
6744   PetscCall(ISDestroy(&newis));
6745   PetscCall(ISDestroy(&is));
6746   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6747   PetscFunctionReturn(PETSC_SUCCESS);
6748 }
6749 
6750 /*@
6751   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6752   of a set of rows and columns of a matrix; using local numbering of rows.
6753 
6754   Collective
6755 
6756   Input Parameters:
6757 + mat  - the matrix
6758 . is   - index set of rows to remove
6759 . diag - value put in all diagonals of eliminated rows
6760 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6761 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6762 
6763   Level: intermediate
6764 
6765   Notes:
6766   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6767   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6768 
6769   See `MatZeroRowsColumns()` for details on how this routine operates.
6770 
6771 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6772           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6773 @*/
6774 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6775 {
6776   PetscInt        numRows;
6777   const PetscInt *rows;
6778 
6779   PetscFunctionBegin;
6780   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6781   PetscValidType(mat, 1);
6782   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6783   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6784   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6785   MatCheckPreallocated(mat, 1);
6786 
6787   PetscCall(ISGetLocalSize(is, &numRows));
6788   PetscCall(ISGetIndices(is, &rows));
6789   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6790   PetscCall(ISRestoreIndices(is, &rows));
6791   PetscFunctionReturn(PETSC_SUCCESS);
6792 }
6793 
6794 /*@
6795   MatGetSize - Returns the numbers of rows and columns in a matrix.
6796 
6797   Not Collective
6798 
6799   Input Parameter:
6800 . mat - the matrix
6801 
6802   Output Parameters:
6803 + m - the number of global rows
6804 - n - the number of global columns
6805 
6806   Level: beginner
6807 
6808   Note:
6809   Both output parameters can be `NULL` on input.
6810 
6811 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6812 @*/
6813 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6814 {
6815   PetscFunctionBegin;
6816   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6817   if (m) *m = mat->rmap->N;
6818   if (n) *n = mat->cmap->N;
6819   PetscFunctionReturn(PETSC_SUCCESS);
6820 }
6821 
6822 /*@
6823   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6824   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6825 
6826   Not Collective
6827 
6828   Input Parameter:
6829 . mat - the matrix
6830 
6831   Output Parameters:
6832 + m - the number of local rows, use `NULL` to not obtain this value
6833 - n - the number of local columns, use `NULL` to not obtain this value
6834 
6835   Level: beginner
6836 
6837 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6838 @*/
6839 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6840 {
6841   PetscFunctionBegin;
6842   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6843   if (m) PetscAssertPointer(m, 2);
6844   if (n) PetscAssertPointer(n, 3);
6845   if (m) *m = mat->rmap->n;
6846   if (n) *n = mat->cmap->n;
6847   PetscFunctionReturn(PETSC_SUCCESS);
6848 }
6849 
6850 /*@
6851   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6852   vector one multiplies this matrix by that are owned by this processor.
6853 
6854   Not Collective, unless matrix has not been allocated, then collective
6855 
6856   Input Parameter:
6857 . mat - the matrix
6858 
6859   Output Parameters:
6860 + m - the global index of the first local column, use `NULL` to not obtain this value
6861 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6862 
6863   Level: developer
6864 
6865   Notes:
6866   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6867 
6868   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6869   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6870 
6871   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6872   the local values in the matrix.
6873 
6874   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6875   Layouts](sec_matlayout) for details on matrix layouts.
6876 
6877 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6878           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6879 @*/
6880 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6881 {
6882   PetscFunctionBegin;
6883   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6884   PetscValidType(mat, 1);
6885   if (m) PetscAssertPointer(m, 2);
6886   if (n) PetscAssertPointer(n, 3);
6887   MatCheckPreallocated(mat, 1);
6888   if (m) *m = mat->cmap->rstart;
6889   if (n) *n = mat->cmap->rend;
6890   PetscFunctionReturn(PETSC_SUCCESS);
6891 }
6892 
6893 /*@
6894   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6895   this MPI process.
6896 
6897   Not Collective
6898 
6899   Input Parameter:
6900 . mat - the matrix
6901 
6902   Output Parameters:
6903 + m - the global index of the first local row, use `NULL` to not obtain this value
6904 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6905 
6906   Level: beginner
6907 
6908   Notes:
6909   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6910 
6911   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6912   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6913 
6914   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6915   the local values in the matrix.
6916 
6917   The high argument is one more than the last element stored locally.
6918 
6919   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6920   would contain the result of a matrix vector product with this matrix. See [Matrix
6921   Layouts](sec_matlayout) for details on matrix layouts.
6922 
6923 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6924           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6925 @*/
6926 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6927 {
6928   PetscFunctionBegin;
6929   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6930   PetscValidType(mat, 1);
6931   if (m) PetscAssertPointer(m, 2);
6932   if (n) PetscAssertPointer(n, 3);
6933   MatCheckPreallocated(mat, 1);
6934   if (m) *m = mat->rmap->rstart;
6935   if (n) *n = mat->rmap->rend;
6936   PetscFunctionReturn(PETSC_SUCCESS);
6937 }
6938 
6939 /*@C
6940   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6941   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6942 
6943   Not Collective, unless matrix has not been allocated
6944 
6945   Input Parameter:
6946 . mat - the matrix
6947 
6948   Output Parameter:
6949 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6950            where `size` is the number of MPI processes used by `mat`
6951 
6952   Level: beginner
6953 
6954   Notes:
6955   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6956 
6957   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6958   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6959 
6960   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6961   the local values in the matrix.
6962 
6963   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6964   would contain the result of a matrix vector product with this matrix. See [Matrix
6965   Layouts](sec_matlayout) for details on matrix layouts.
6966 
6967 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6968           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6969           `DMDAGetGhostCorners()`, `DM`
6970 @*/
6971 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6972 {
6973   PetscFunctionBegin;
6974   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6975   PetscValidType(mat, 1);
6976   MatCheckPreallocated(mat, 1);
6977   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6978   PetscFunctionReturn(PETSC_SUCCESS);
6979 }
6980 
6981 /*@C
6982   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6983   vector one multiplies this vector by that are owned by each processor.
6984 
6985   Not Collective, unless matrix has not been allocated
6986 
6987   Input Parameter:
6988 . mat - the matrix
6989 
6990   Output Parameter:
6991 . ranges - start of each processors portion plus one more than the total length at the end
6992 
6993   Level: beginner
6994 
6995   Notes:
6996   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6997 
6998   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6999   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
7000 
7001   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7002   the local values in the matrix.
7003 
7004   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
7005   Layouts](sec_matlayout) for details on matrix layouts.
7006 
7007 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
7008           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
7009           `DMDAGetGhostCorners()`, `DM`
7010 @*/
7011 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
7012 {
7013   PetscFunctionBegin;
7014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7015   PetscValidType(mat, 1);
7016   MatCheckPreallocated(mat, 1);
7017   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7018   PetscFunctionReturn(PETSC_SUCCESS);
7019 }
7020 
7021 /*@
7022   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7023 
7024   Not Collective
7025 
7026   Input Parameter:
7027 . A - matrix
7028 
7029   Output Parameters:
7030 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7031 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7032 
7033   Level: intermediate
7034 
7035   Note:
7036   You should call `ISDestroy()` on the returned `IS`
7037 
7038   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7039   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7040   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7041   details on matrix layouts.
7042 
7043 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7044 @*/
7045 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7046 {
7047   PetscErrorCode (*f)(Mat, IS *, IS *);
7048 
7049   PetscFunctionBegin;
7050   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7051   PetscValidType(A, 1);
7052   MatCheckPreallocated(A, 1);
7053   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7054   if (f) {
7055     PetscCall((*f)(A, rows, cols));
7056   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7057     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7058     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7059   }
7060   PetscFunctionReturn(PETSC_SUCCESS);
7061 }
7062 
7063 /*@
7064   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7065   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7066   to complete the factorization.
7067 
7068   Collective
7069 
7070   Input Parameters:
7071 + fact - the factorized matrix obtained with `MatGetFactor()`
7072 . mat  - the matrix
7073 . row  - row permutation
7074 . col  - column permutation
7075 - info - structure containing
7076 .vb
7077       levels - number of levels of fill.
7078       expected fill - as ratio of original fill.
7079       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7080                 missing diagonal entries)
7081 .ve
7082 
7083   Level: developer
7084 
7085   Notes:
7086   See [Matrix Factorization](sec_matfactor) for additional information.
7087 
7088   Most users should employ the `KSP` interface for linear solvers
7089   instead of working directly with matrix algebra routines such as this.
7090   See, e.g., `KSPCreate()`.
7091 
7092   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7093 
7094   Developer Note:
7095   The Fortran interface is not autogenerated as the
7096   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7097 
7098 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7099           `MatGetOrdering()`, `MatFactorInfo`
7100 @*/
7101 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7102 {
7103   PetscFunctionBegin;
7104   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7105   PetscValidType(mat, 2);
7106   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7107   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7108   PetscAssertPointer(info, 5);
7109   PetscAssertPointer(fact, 1);
7110   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7111   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7112   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7113   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7114   MatCheckPreallocated(mat, 2);
7115 
7116   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7117   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7118   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7119   PetscFunctionReturn(PETSC_SUCCESS);
7120 }
7121 
7122 /*@
7123   MatICCFactorSymbolic - Performs symbolic incomplete
7124   Cholesky factorization for a symmetric matrix.  Use
7125   `MatCholeskyFactorNumeric()` to complete the factorization.
7126 
7127   Collective
7128 
7129   Input Parameters:
7130 + fact - the factorized matrix obtained with `MatGetFactor()`
7131 . mat  - the matrix to be factored
7132 . perm - row and column permutation
7133 - info - structure containing
7134 .vb
7135       levels - number of levels of fill.
7136       expected fill - as ratio of original fill.
7137 .ve
7138 
7139   Level: developer
7140 
7141   Notes:
7142   Most users should employ the `KSP` interface for linear solvers
7143   instead of working directly with matrix algebra routines such as this.
7144   See, e.g., `KSPCreate()`.
7145 
7146   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7147 
7148   Developer Note:
7149   The Fortran interface is not autogenerated as the
7150   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7151 
7152 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7153 @*/
7154 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7155 {
7156   PetscFunctionBegin;
7157   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7158   PetscValidType(mat, 2);
7159   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7160   PetscAssertPointer(info, 4);
7161   PetscAssertPointer(fact, 1);
7162   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7163   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7164   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7165   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7166   MatCheckPreallocated(mat, 2);
7167 
7168   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7169   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7170   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7171   PetscFunctionReturn(PETSC_SUCCESS);
7172 }
7173 
7174 /*@C
7175   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7176   points to an array of valid matrices, they may be reused to store the new
7177   submatrices.
7178 
7179   Collective
7180 
7181   Input Parameters:
7182 + mat   - the matrix
7183 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7184 . irow  - index set of rows to extract
7185 . icol  - index set of columns to extract
7186 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7187 
7188   Output Parameter:
7189 . submat - the array of submatrices
7190 
7191   Level: advanced
7192 
7193   Notes:
7194   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7195   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7196   to extract a parallel submatrix.
7197 
7198   Some matrix types place restrictions on the row and column
7199   indices, such as that they be sorted or that they be equal to each other.
7200 
7201   The index sets may not have duplicate entries.
7202 
7203   When extracting submatrices from a parallel matrix, each processor can
7204   form a different submatrix by setting the rows and columns of its
7205   individual index sets according to the local submatrix desired.
7206 
7207   When finished using the submatrices, the user should destroy
7208   them with `MatDestroySubMatrices()`.
7209 
7210   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7211   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7212 
7213   This routine creates the matrices in submat; you should NOT create them before
7214   calling it. It also allocates the array of matrix pointers submat.
7215 
7216   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7217   request one row/column in a block, they must request all rows/columns that are in
7218   that block. For example, if the block size is 2 you cannot request just row 0 and
7219   column 0.
7220 
7221   Fortran Note:
7222 .vb
7223   Mat, pointer :: submat(:)
7224 .ve
7225 
7226 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7227 @*/
7228 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7229 {
7230   PetscInt  i;
7231   PetscBool eq;
7232 
7233   PetscFunctionBegin;
7234   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7235   PetscValidType(mat, 1);
7236   if (n) {
7237     PetscAssertPointer(irow, 3);
7238     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7239     PetscAssertPointer(icol, 4);
7240     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7241   }
7242   PetscAssertPointer(submat, 6);
7243   if (n && scall == MAT_REUSE_MATRIX) {
7244     PetscAssertPointer(*submat, 6);
7245     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7246   }
7247   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7248   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7249   MatCheckPreallocated(mat, 1);
7250   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7251   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7252   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7253   for (i = 0; i < n; i++) {
7254     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7255     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7256     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7257 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7258     if (mat->boundtocpu && mat->bindingpropagates) {
7259       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7260       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7261     }
7262 #endif
7263   }
7264   PetscFunctionReturn(PETSC_SUCCESS);
7265 }
7266 
7267 /*@C
7268   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms).
7269 
7270   Collective
7271 
7272   Input Parameters:
7273 + mat   - the matrix
7274 . n     - the number of submatrixes to be extracted
7275 . irow  - index set of rows to extract
7276 . icol  - index set of columns to extract
7277 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7278 
7279   Output Parameter:
7280 . submat - the array of submatrices
7281 
7282   Level: advanced
7283 
7284   Note:
7285   This is used by `PCGASM`
7286 
7287 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7288 @*/
7289 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7290 {
7291   PetscInt  i;
7292   PetscBool eq;
7293 
7294   PetscFunctionBegin;
7295   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7296   PetscValidType(mat, 1);
7297   if (n) {
7298     PetscAssertPointer(irow, 3);
7299     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7300     PetscAssertPointer(icol, 4);
7301     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7302   }
7303   PetscAssertPointer(submat, 6);
7304   if (n && scall == MAT_REUSE_MATRIX) {
7305     PetscAssertPointer(*submat, 6);
7306     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7307   }
7308   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7309   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7310   MatCheckPreallocated(mat, 1);
7311 
7312   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7313   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7314   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7315   for (i = 0; i < n; i++) {
7316     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7317     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7318   }
7319   PetscFunctionReturn(PETSC_SUCCESS);
7320 }
7321 
7322 /*@C
7323   MatDestroyMatrices - Destroys an array of matrices
7324 
7325   Collective
7326 
7327   Input Parameters:
7328 + n   - the number of local matrices
7329 - mat - the matrices (this is a pointer to the array of matrices)
7330 
7331   Level: advanced
7332 
7333   Notes:
7334   Frees not only the matrices, but also the array that contains the matrices
7335 
7336   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7337 
7338 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7339 @*/
7340 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7341 {
7342   PetscInt i;
7343 
7344   PetscFunctionBegin;
7345   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7346   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7347   PetscAssertPointer(mat, 2);
7348 
7349   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7350 
7351   /* memory is allocated even if n = 0 */
7352   PetscCall(PetscFree(*mat));
7353   PetscFunctionReturn(PETSC_SUCCESS);
7354 }
7355 
7356 /*@C
7357   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7358 
7359   Collective
7360 
7361   Input Parameters:
7362 + n   - the number of local matrices
7363 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`)
7364 
7365   Level: advanced
7366 
7367   Note:
7368   Frees not only the matrices, but also the array that contains the matrices
7369 
7370 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7371 @*/
7372 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7373 {
7374   Mat mat0;
7375 
7376   PetscFunctionBegin;
7377   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7378   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7379   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7380   PetscAssertPointer(mat, 2);
7381 
7382   mat0 = (*mat)[0];
7383   if (mat0 && mat0->ops->destroysubmatrices) {
7384     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7385   } else {
7386     PetscCall(MatDestroyMatrices(n, mat));
7387   }
7388   PetscFunctionReturn(PETSC_SUCCESS);
7389 }
7390 
7391 /*@
7392   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7393 
7394   Collective
7395 
7396   Input Parameter:
7397 . mat - the matrix
7398 
7399   Output Parameter:
7400 . matstruct - the sequential matrix with the nonzero structure of `mat`
7401 
7402   Level: developer
7403 
7404 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7405 @*/
7406 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7407 {
7408   PetscFunctionBegin;
7409   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7410   PetscAssertPointer(matstruct, 2);
7411 
7412   PetscValidType(mat, 1);
7413   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7414   MatCheckPreallocated(mat, 1);
7415 
7416   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7417   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7418   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7419   PetscFunctionReturn(PETSC_SUCCESS);
7420 }
7421 
7422 /*@C
7423   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7424 
7425   Collective
7426 
7427   Input Parameter:
7428 . mat - the matrix
7429 
7430   Level: advanced
7431 
7432   Note:
7433   This is not needed, one can just call `MatDestroy()`
7434 
7435 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7436 @*/
7437 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7438 {
7439   PetscFunctionBegin;
7440   PetscAssertPointer(mat, 1);
7441   PetscCall(MatDestroy(mat));
7442   PetscFunctionReturn(PETSC_SUCCESS);
7443 }
7444 
7445 /*@
7446   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7447   replaces the index sets by larger ones that represent submatrices with
7448   additional overlap.
7449 
7450   Collective
7451 
7452   Input Parameters:
7453 + mat - the matrix
7454 . n   - the number of index sets
7455 . is  - the array of index sets (these index sets will changed during the call)
7456 - ov  - the additional overlap requested
7457 
7458   Options Database Key:
7459 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7460 
7461   Level: developer
7462 
7463   Note:
7464   The computed overlap preserves the matrix block sizes when the blocks are square.
7465   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7466   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7467 
7468 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7469 @*/
7470 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7471 {
7472   PetscInt i, bs, cbs;
7473 
7474   PetscFunctionBegin;
7475   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7476   PetscValidType(mat, 1);
7477   PetscValidLogicalCollectiveInt(mat, n, 2);
7478   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7479   if (n) {
7480     PetscAssertPointer(is, 3);
7481     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7482   }
7483   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7484   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7485   MatCheckPreallocated(mat, 1);
7486 
7487   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7488   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7489   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7490   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7491   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7492   if (bs == cbs) {
7493     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7494   }
7495   PetscFunctionReturn(PETSC_SUCCESS);
7496 }
7497 
7498 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7499 
7500 /*@
7501   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7502   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7503   additional overlap.
7504 
7505   Collective
7506 
7507   Input Parameters:
7508 + mat - the matrix
7509 . n   - the number of index sets
7510 . is  - the array of index sets (these index sets will changed during the call)
7511 - ov  - the additional overlap requested
7512 
7513   `   Options Database Key:
7514 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7515 
7516   Level: developer
7517 
7518 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7519 @*/
7520 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7521 {
7522   PetscInt i;
7523 
7524   PetscFunctionBegin;
7525   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7526   PetscValidType(mat, 1);
7527   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7528   if (n) {
7529     PetscAssertPointer(is, 3);
7530     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7531   }
7532   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7533   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7534   MatCheckPreallocated(mat, 1);
7535   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7536   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7537   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7538   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7539   PetscFunctionReturn(PETSC_SUCCESS);
7540 }
7541 
7542 /*@
7543   MatGetBlockSize - Returns the matrix block size.
7544 
7545   Not Collective
7546 
7547   Input Parameter:
7548 . mat - the matrix
7549 
7550   Output Parameter:
7551 . bs - block size
7552 
7553   Level: intermediate
7554 
7555   Notes:
7556   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7557 
7558   If the block size has not been set yet this routine returns 1.
7559 
7560 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7561 @*/
7562 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7563 {
7564   PetscFunctionBegin;
7565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7566   PetscAssertPointer(bs, 2);
7567   *bs = mat->rmap->bs;
7568   PetscFunctionReturn(PETSC_SUCCESS);
7569 }
7570 
7571 /*@
7572   MatGetBlockSizes - Returns the matrix block row and column sizes.
7573 
7574   Not Collective
7575 
7576   Input Parameter:
7577 . mat - the matrix
7578 
7579   Output Parameters:
7580 + rbs - row block size
7581 - cbs - column block size
7582 
7583   Level: intermediate
7584 
7585   Notes:
7586   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7587   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7588 
7589   If a block size has not been set yet this routine returns 1.
7590 
7591 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7592 @*/
7593 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7594 {
7595   PetscFunctionBegin;
7596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7597   if (rbs) PetscAssertPointer(rbs, 2);
7598   if (cbs) PetscAssertPointer(cbs, 3);
7599   if (rbs) *rbs = mat->rmap->bs;
7600   if (cbs) *cbs = mat->cmap->bs;
7601   PetscFunctionReturn(PETSC_SUCCESS);
7602 }
7603 
7604 /*@
7605   MatSetBlockSize - Sets the matrix block size.
7606 
7607   Logically Collective
7608 
7609   Input Parameters:
7610 + mat - the matrix
7611 - bs  - block size
7612 
7613   Level: intermediate
7614 
7615   Notes:
7616   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7617   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7618 
7619   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7620   is compatible with the matrix local sizes.
7621 
7622 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7623 @*/
7624 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7625 {
7626   PetscFunctionBegin;
7627   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7628   PetscValidLogicalCollectiveInt(mat, bs, 2);
7629   PetscCall(MatSetBlockSizes(mat, bs, bs));
7630   PetscFunctionReturn(PETSC_SUCCESS);
7631 }
7632 
7633 typedef struct {
7634   PetscInt         n;
7635   IS              *is;
7636   Mat             *mat;
7637   PetscObjectState nonzerostate;
7638   Mat              C;
7639 } EnvelopeData;
7640 
7641 static PetscErrorCode EnvelopeDataDestroy(void **ptr)
7642 {
7643   EnvelopeData *edata = (EnvelopeData *)*ptr;
7644 
7645   PetscFunctionBegin;
7646   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7647   PetscCall(PetscFree(edata->is));
7648   PetscCall(PetscFree(edata));
7649   PetscFunctionReturn(PETSC_SUCCESS);
7650 }
7651 
7652 /*@
7653   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7654   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7655 
7656   Collective
7657 
7658   Input Parameter:
7659 . mat - the matrix
7660 
7661   Level: intermediate
7662 
7663   Notes:
7664   There can be zeros within the blocks
7665 
7666   The blocks can overlap between processes, including laying on more than two processes
7667 
7668 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7669 @*/
7670 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7671 {
7672   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7673   PetscInt          *diag, *odiag, sc;
7674   VecScatter         scatter;
7675   PetscScalar       *seqv;
7676   const PetscScalar *parv;
7677   const PetscInt    *ia, *ja;
7678   PetscBool          set, flag, done;
7679   Mat                AA = mat, A;
7680   MPI_Comm           comm;
7681   PetscMPIInt        rank, size, tag;
7682   MPI_Status         status;
7683   PetscContainer     container;
7684   EnvelopeData      *edata;
7685   Vec                seq, par;
7686   IS                 isglobal;
7687 
7688   PetscFunctionBegin;
7689   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7690   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7691   if (!set || !flag) {
7692     /* TODO: only needs nonzero structure of transpose */
7693     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7694     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7695   }
7696   PetscCall(MatAIJGetLocalMat(AA, &A));
7697   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7698   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7699 
7700   PetscCall(MatGetLocalSize(mat, &n, NULL));
7701   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7702   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7703   PetscCallMPI(MPI_Comm_size(comm, &size));
7704   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7705 
7706   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7707 
7708   if (rank > 0) {
7709     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7710     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7711   }
7712   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7713   for (i = 0; i < n; i++) {
7714     env = PetscMax(env, ja[ia[i + 1] - 1]);
7715     II  = rstart + i;
7716     if (env == II) {
7717       starts[lblocks]  = tbs;
7718       sizes[lblocks++] = 1 + II - tbs;
7719       tbs              = 1 + II;
7720     }
7721   }
7722   if (rank < size - 1) {
7723     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7724     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7725   }
7726 
7727   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7728   if (!set || !flag) PetscCall(MatDestroy(&AA));
7729   PetscCall(MatDestroy(&A));
7730 
7731   PetscCall(PetscNew(&edata));
7732   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7733   edata->n = lblocks;
7734   /* create IS needed for extracting blocks from the original matrix */
7735   PetscCall(PetscMalloc1(lblocks, &edata->is));
7736   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7737 
7738   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7739   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7740   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7741   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7742   PetscCall(MatSetType(edata->C, MATAIJ));
7743 
7744   /* Communicate the start and end of each row, from each block to the correct rank */
7745   /* TODO: Use PetscSF instead of VecScatter */
7746   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7747   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7748   PetscCall(VecGetArrayWrite(seq, &seqv));
7749   for (PetscInt i = 0; i < lblocks; i++) {
7750     for (PetscInt j = 0; j < sizes[i]; j++) {
7751       seqv[cnt]     = starts[i];
7752       seqv[cnt + 1] = starts[i] + sizes[i];
7753       cnt += 2;
7754     }
7755   }
7756   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7757   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7758   sc -= cnt;
7759   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7760   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7761   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7762   PetscCall(ISDestroy(&isglobal));
7763   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7764   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7765   PetscCall(VecScatterDestroy(&scatter));
7766   PetscCall(VecDestroy(&seq));
7767   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7768   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7769   PetscCall(VecGetArrayRead(par, &parv));
7770   cnt = 0;
7771   PetscCall(MatGetSize(mat, NULL, &n));
7772   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7773     PetscInt start, end, d = 0, od = 0;
7774 
7775     start = (PetscInt)PetscRealPart(parv[cnt]);
7776     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7777     cnt += 2;
7778 
7779     if (start < cstart) {
7780       od += cstart - start + n - cend;
7781       d += cend - cstart;
7782     } else if (start < cend) {
7783       od += n - cend;
7784       d += cend - start;
7785     } else od += n - start;
7786     if (end <= cstart) {
7787       od -= cstart - end + n - cend;
7788       d -= cend - cstart;
7789     } else if (end < cend) {
7790       od -= n - cend;
7791       d -= cend - end;
7792     } else od -= n - end;
7793 
7794     odiag[i] = od;
7795     diag[i]  = d;
7796   }
7797   PetscCall(VecRestoreArrayRead(par, &parv));
7798   PetscCall(VecDestroy(&par));
7799   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7800   PetscCall(PetscFree2(diag, odiag));
7801   PetscCall(PetscFree2(sizes, starts));
7802 
7803   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7804   PetscCall(PetscContainerSetPointer(container, edata));
7805   PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy));
7806   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7807   PetscCall(PetscObjectDereference((PetscObject)container));
7808   PetscFunctionReturn(PETSC_SUCCESS);
7809 }
7810 
7811 /*@
7812   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7813 
7814   Collective
7815 
7816   Input Parameters:
7817 + A     - the matrix
7818 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7819 
7820   Output Parameter:
7821 . C - matrix with inverted block diagonal of `A`
7822 
7823   Level: advanced
7824 
7825   Note:
7826   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7827 
7828 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7829 @*/
7830 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7831 {
7832   PetscContainer   container;
7833   EnvelopeData    *edata;
7834   PetscObjectState nonzerostate;
7835 
7836   PetscFunctionBegin;
7837   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7838   if (!container) {
7839     PetscCall(MatComputeVariableBlockEnvelope(A));
7840     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7841   }
7842   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7843   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7844   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7845   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7846 
7847   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7848   *C = edata->C;
7849 
7850   for (PetscInt i = 0; i < edata->n; i++) {
7851     Mat          D;
7852     PetscScalar *dvalues;
7853 
7854     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7855     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7856     PetscCall(MatSeqDenseInvert(D));
7857     PetscCall(MatDenseGetArray(D, &dvalues));
7858     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7859     PetscCall(MatDestroy(&D));
7860   }
7861   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7862   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7863   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7864   PetscFunctionReturn(PETSC_SUCCESS);
7865 }
7866 
7867 /*@
7868   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7869 
7870   Not Collective
7871 
7872   Input Parameters:
7873 + mat     - the matrix
7874 . nblocks - the number of blocks on this process, each block can only exist on a single process
7875 - bsizes  - the block sizes
7876 
7877   Level: intermediate
7878 
7879   Notes:
7880   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7881 
7882   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.
7883 
7884 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7885           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7886 @*/
7887 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7888 {
7889   PetscInt ncnt = 0, nlocal;
7890 
7891   PetscFunctionBegin;
7892   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7893   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7894   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);
7895   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7896   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);
7897   PetscCall(PetscFree(mat->bsizes));
7898   mat->nblocks = nblocks;
7899   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7900   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7901   PetscFunctionReturn(PETSC_SUCCESS);
7902 }
7903 
7904 /*@C
7905   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7906 
7907   Not Collective; No Fortran Support
7908 
7909   Input Parameter:
7910 . mat - the matrix
7911 
7912   Output Parameters:
7913 + nblocks - the number of blocks on this process
7914 - bsizes  - the block sizes
7915 
7916   Level: intermediate
7917 
7918 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7919 @*/
7920 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7921 {
7922   PetscFunctionBegin;
7923   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7924   if (nblocks) *nblocks = mat->nblocks;
7925   if (bsizes) *bsizes = mat->bsizes;
7926   PetscFunctionReturn(PETSC_SUCCESS);
7927 }
7928 
7929 /*@
7930   MatSetBlockSizes - Sets the matrix block row and column sizes.
7931 
7932   Logically Collective
7933 
7934   Input Parameters:
7935 + mat - the matrix
7936 . rbs - row block size
7937 - cbs - column block size
7938 
7939   Level: intermediate
7940 
7941   Notes:
7942   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7943   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7944   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7945 
7946   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7947   are compatible with the matrix local sizes.
7948 
7949   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7950 
7951 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7952 @*/
7953 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7954 {
7955   PetscFunctionBegin;
7956   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7957   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7958   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7959   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7960   if (mat->rmap->refcnt) {
7961     ISLocalToGlobalMapping l2g  = NULL;
7962     PetscLayout            nmap = NULL;
7963 
7964     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7965     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7966     PetscCall(PetscLayoutDestroy(&mat->rmap));
7967     mat->rmap          = nmap;
7968     mat->rmap->mapping = l2g;
7969   }
7970   if (mat->cmap->refcnt) {
7971     ISLocalToGlobalMapping l2g  = NULL;
7972     PetscLayout            nmap = NULL;
7973 
7974     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7975     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7976     PetscCall(PetscLayoutDestroy(&mat->cmap));
7977     mat->cmap          = nmap;
7978     mat->cmap->mapping = l2g;
7979   }
7980   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7981   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7982   PetscFunctionReturn(PETSC_SUCCESS);
7983 }
7984 
7985 /*@
7986   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7987 
7988   Logically Collective
7989 
7990   Input Parameters:
7991 + mat     - the matrix
7992 . fromRow - matrix from which to copy row block size
7993 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7994 
7995   Level: developer
7996 
7997 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7998 @*/
7999 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
8000 {
8001   PetscFunctionBegin;
8002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8003   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
8004   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
8005   PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
8006   PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
8007   PetscFunctionReturn(PETSC_SUCCESS);
8008 }
8009 
8010 /*@
8011   MatResidual - Default routine to calculate the residual r = b - Ax
8012 
8013   Collective
8014 
8015   Input Parameters:
8016 + mat - the matrix
8017 . b   - the right-hand-side
8018 - x   - the approximate solution
8019 
8020   Output Parameter:
8021 . r - location to store the residual
8022 
8023   Level: developer
8024 
8025 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8026 @*/
8027 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8028 {
8029   PetscFunctionBegin;
8030   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8031   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8032   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8033   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8034   PetscValidType(mat, 1);
8035   MatCheckPreallocated(mat, 1);
8036   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8037   if (!mat->ops->residual) {
8038     PetscCall(MatMult(mat, x, r));
8039     PetscCall(VecAYPX(r, -1.0, b));
8040   } else {
8041     PetscUseTypeMethod(mat, residual, b, x, r);
8042   }
8043   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8044   PetscFunctionReturn(PETSC_SUCCESS);
8045 }
8046 
8047 /*@C
8048   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8049 
8050   Collective
8051 
8052   Input Parameters:
8053 + mat             - the matrix
8054 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8055 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8056 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8057                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8058                  always used.
8059 
8060   Output Parameters:
8061 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8062 . 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
8063 . ja   - the column indices, use `NULL` if not needed
8064 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8065            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8066 
8067   Level: developer
8068 
8069   Notes:
8070   You CANNOT change any of the ia[] or ja[] values.
8071 
8072   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8073 
8074   Fortran Notes:
8075   Use
8076 .vb
8077     PetscInt, pointer :: ia(:),ja(:)
8078     call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8079     ! Access the ith and jth entries via ia(i) and ja(j)
8080 .ve
8081 
8082 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8083 @*/
8084 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8085 {
8086   PetscFunctionBegin;
8087   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8088   PetscValidType(mat, 1);
8089   if (n) PetscAssertPointer(n, 5);
8090   if (ia) PetscAssertPointer(ia, 6);
8091   if (ja) PetscAssertPointer(ja, 7);
8092   if (done) PetscAssertPointer(done, 8);
8093   MatCheckPreallocated(mat, 1);
8094   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8095   else {
8096     if (done) *done = PETSC_TRUE;
8097     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8098     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8099     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8100   }
8101   PetscFunctionReturn(PETSC_SUCCESS);
8102 }
8103 
8104 /*@C
8105   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8106 
8107   Collective
8108 
8109   Input Parameters:
8110 + mat             - the matrix
8111 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8112 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8113                 symmetrized
8114 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8115                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8116                  always used.
8117 . n               - number of columns in the (possibly compressed) matrix
8118 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8119 - ja              - the row indices
8120 
8121   Output Parameter:
8122 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8123 
8124   Level: developer
8125 
8126 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8127 @*/
8128 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8129 {
8130   PetscFunctionBegin;
8131   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8132   PetscValidType(mat, 1);
8133   PetscAssertPointer(n, 5);
8134   if (ia) PetscAssertPointer(ia, 6);
8135   if (ja) PetscAssertPointer(ja, 7);
8136   PetscAssertPointer(done, 8);
8137   MatCheckPreallocated(mat, 1);
8138   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8139   else {
8140     *done = PETSC_TRUE;
8141     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8142   }
8143   PetscFunctionReturn(PETSC_SUCCESS);
8144 }
8145 
8146 /*@C
8147   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8148 
8149   Collective
8150 
8151   Input Parameters:
8152 + mat             - the matrix
8153 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8154 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8155 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8156                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8157                     always used.
8158 . n               - size of (possibly compressed) matrix
8159 . ia              - the row pointers
8160 - ja              - the column indices
8161 
8162   Output Parameter:
8163 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8164 
8165   Level: developer
8166 
8167   Note:
8168   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8169   us of the array after it has been restored. If you pass `NULL`, it will
8170   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8171 
8172 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8173 @*/
8174 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8175 {
8176   PetscFunctionBegin;
8177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8178   PetscValidType(mat, 1);
8179   if (ia) PetscAssertPointer(ia, 6);
8180   if (ja) PetscAssertPointer(ja, 7);
8181   if (done) PetscAssertPointer(done, 8);
8182   MatCheckPreallocated(mat, 1);
8183 
8184   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8185   else {
8186     if (done) *done = PETSC_TRUE;
8187     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8188     if (n) *n = 0;
8189     if (ia) *ia = NULL;
8190     if (ja) *ja = NULL;
8191   }
8192   PetscFunctionReturn(PETSC_SUCCESS);
8193 }
8194 
8195 /*@C
8196   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8197 
8198   Collective
8199 
8200   Input Parameters:
8201 + mat             - the matrix
8202 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8203 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8204 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8205                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8206                     always used.
8207 
8208   Output Parameters:
8209 + n    - size of (possibly compressed) matrix
8210 . ia   - the column pointers
8211 . ja   - the row indices
8212 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8213 
8214   Level: developer
8215 
8216 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8217 @*/
8218 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8219 {
8220   PetscFunctionBegin;
8221   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8222   PetscValidType(mat, 1);
8223   if (ia) PetscAssertPointer(ia, 6);
8224   if (ja) PetscAssertPointer(ja, 7);
8225   PetscAssertPointer(done, 8);
8226   MatCheckPreallocated(mat, 1);
8227 
8228   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8229   else {
8230     *done = PETSC_TRUE;
8231     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8232     if (n) *n = 0;
8233     if (ia) *ia = NULL;
8234     if (ja) *ja = NULL;
8235   }
8236   PetscFunctionReturn(PETSC_SUCCESS);
8237 }
8238 
8239 /*@
8240   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8241   `MatGetColumnIJ()`.
8242 
8243   Collective
8244 
8245   Input Parameters:
8246 + mat        - the matrix
8247 . ncolors    - maximum color value
8248 . n          - number of entries in colorarray
8249 - colorarray - array indicating color for each column
8250 
8251   Output Parameter:
8252 . iscoloring - coloring generated using colorarray information
8253 
8254   Level: developer
8255 
8256 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8257 @*/
8258 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8259 {
8260   PetscFunctionBegin;
8261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8262   PetscValidType(mat, 1);
8263   PetscAssertPointer(colorarray, 4);
8264   PetscAssertPointer(iscoloring, 5);
8265   MatCheckPreallocated(mat, 1);
8266 
8267   if (!mat->ops->coloringpatch) {
8268     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8269   } else {
8270     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8271   }
8272   PetscFunctionReturn(PETSC_SUCCESS);
8273 }
8274 
8275 /*@
8276   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8277 
8278   Logically Collective
8279 
8280   Input Parameter:
8281 . mat - the factored matrix to be reset
8282 
8283   Level: developer
8284 
8285   Notes:
8286   This routine should be used only with factored matrices formed by in-place
8287   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8288   format).  This option can save memory, for example, when solving nonlinear
8289   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8290   ILU(0) preconditioner.
8291 
8292   One can specify in-place ILU(0) factorization by calling
8293 .vb
8294      PCType(pc,PCILU);
8295      PCFactorSeUseInPlace(pc);
8296 .ve
8297   or by using the options -pc_type ilu -pc_factor_in_place
8298 
8299   In-place factorization ILU(0) can also be used as a local
8300   solver for the blocks within the block Jacobi or additive Schwarz
8301   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8302   for details on setting local solver options.
8303 
8304   Most users should employ the `KSP` interface for linear solvers
8305   instead of working directly with matrix algebra routines such as this.
8306   See, e.g., `KSPCreate()`.
8307 
8308 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8309 @*/
8310 PetscErrorCode MatSetUnfactored(Mat mat)
8311 {
8312   PetscFunctionBegin;
8313   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8314   PetscValidType(mat, 1);
8315   MatCheckPreallocated(mat, 1);
8316   mat->factortype = MAT_FACTOR_NONE;
8317   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8318   PetscUseTypeMethod(mat, setunfactored);
8319   PetscFunctionReturn(PETSC_SUCCESS);
8320 }
8321 
8322 /*@
8323   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8324   as the original matrix.
8325 
8326   Collective
8327 
8328   Input Parameters:
8329 + mat   - the original matrix
8330 . isrow - parallel `IS` containing the rows this processor should obtain
8331 . 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.
8332 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8333 
8334   Output Parameter:
8335 . newmat - the new submatrix, of the same type as the original matrix
8336 
8337   Level: advanced
8338 
8339   Notes:
8340   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8341 
8342   Some matrix types place restrictions on the row and column indices, such
8343   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;
8344   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8345 
8346   The index sets may not have duplicate entries.
8347 
8348   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8349   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8350   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8351   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8352   you are finished using it.
8353 
8354   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8355   the input matrix.
8356 
8357   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8358 
8359   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8360   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8361 
8362   Example usage:
8363   Consider the following 8x8 matrix with 34 non-zero values, that is
8364   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8365   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8366   as follows
8367 .vb
8368             1  2  0  |  0  3  0  |  0  4
8369     Proc0   0  5  6  |  7  0  0  |  8  0
8370             9  0 10  | 11  0  0  | 12  0
8371     -------------------------------------
8372            13  0 14  | 15 16 17  |  0  0
8373     Proc1   0 18  0  | 19 20 21  |  0  0
8374             0  0  0  | 22 23  0  | 24  0
8375     -------------------------------------
8376     Proc2  25 26 27  |  0  0 28  | 29  0
8377            30  0  0  | 31 32 33  |  0 34
8378 .ve
8379 
8380   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8381 
8382 .vb
8383             2  0  |  0  3  0  |  0
8384     Proc0   5  6  |  7  0  0  |  8
8385     -------------------------------
8386     Proc1  18  0  | 19 20 21  |  0
8387     -------------------------------
8388     Proc2  26 27  |  0  0 28  | 29
8389             0  0  | 31 32 33  |  0
8390 .ve
8391 
8392 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8393 @*/
8394 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8395 {
8396   PetscMPIInt size;
8397   Mat        *local;
8398   IS          iscoltmp;
8399   PetscBool   flg;
8400 
8401   PetscFunctionBegin;
8402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8403   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8404   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8405   PetscAssertPointer(newmat, 5);
8406   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8407   PetscValidType(mat, 1);
8408   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8409   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8410 
8411   MatCheckPreallocated(mat, 1);
8412   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8413 
8414   if (!iscol || isrow == iscol) {
8415     PetscBool   stride;
8416     PetscMPIInt grabentirematrix = 0, grab;
8417     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8418     if (stride) {
8419       PetscInt first, step, n, rstart, rend;
8420       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8421       if (step == 1) {
8422         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8423         if (rstart == first) {
8424           PetscCall(ISGetLocalSize(isrow, &n));
8425           if (n == rend - rstart) grabentirematrix = 1;
8426         }
8427       }
8428     }
8429     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8430     if (grab) {
8431       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8432       if (cll == MAT_INITIAL_MATRIX) {
8433         *newmat = mat;
8434         PetscCall(PetscObjectReference((PetscObject)mat));
8435       }
8436       PetscFunctionReturn(PETSC_SUCCESS);
8437     }
8438   }
8439 
8440   if (!iscol) {
8441     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8442   } else {
8443     iscoltmp = iscol;
8444   }
8445 
8446   /* if original matrix is on just one processor then use submatrix generated */
8447   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8448     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8449     goto setproperties;
8450   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8451     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8452     *newmat = *local;
8453     PetscCall(PetscFree(local));
8454     goto setproperties;
8455   } else if (!mat->ops->createsubmatrix) {
8456     /* Create a new matrix type that implements the operation using the full matrix */
8457     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8458     switch (cll) {
8459     case MAT_INITIAL_MATRIX:
8460       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8461       break;
8462     case MAT_REUSE_MATRIX:
8463       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8464       break;
8465     default:
8466       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8467     }
8468     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8469     goto setproperties;
8470   }
8471 
8472   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8473   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8474   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8475 
8476 setproperties:
8477   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8478     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8479     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8480   }
8481   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8482   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8483   PetscFunctionReturn(PETSC_SUCCESS);
8484 }
8485 
8486 /*@
8487   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8488 
8489   Not Collective
8490 
8491   Input Parameters:
8492 + A - the matrix we wish to propagate options from
8493 - B - the matrix we wish to propagate options to
8494 
8495   Level: beginner
8496 
8497   Note:
8498   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8499 
8500 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8501 @*/
8502 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8503 {
8504   PetscFunctionBegin;
8505   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8506   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8507   B->symmetry_eternal            = A->symmetry_eternal;
8508   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8509   B->symmetric                   = A->symmetric;
8510   B->structurally_symmetric      = A->structurally_symmetric;
8511   B->spd                         = A->spd;
8512   B->hermitian                   = A->hermitian;
8513   PetscFunctionReturn(PETSC_SUCCESS);
8514 }
8515 
8516 /*@
8517   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8518   used during the assembly process to store values that belong to
8519   other processors.
8520 
8521   Not Collective
8522 
8523   Input Parameters:
8524 + mat   - the matrix
8525 . size  - the initial size of the stash.
8526 - bsize - the initial size of the block-stash(if used).
8527 
8528   Options Database Keys:
8529 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8530 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8531 
8532   Level: intermediate
8533 
8534   Notes:
8535   The block-stash is used for values set with `MatSetValuesBlocked()` while
8536   the stash is used for values set with `MatSetValues()`
8537 
8538   Run with the option -info and look for output of the form
8539   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8540   to determine the appropriate value, MM, to use for size and
8541   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8542   to determine the value, BMM to use for bsize
8543 
8544 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8545 @*/
8546 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8547 {
8548   PetscFunctionBegin;
8549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8550   PetscValidType(mat, 1);
8551   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8552   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8553   PetscFunctionReturn(PETSC_SUCCESS);
8554 }
8555 
8556 /*@
8557   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8558   the matrix
8559 
8560   Neighbor-wise Collective
8561 
8562   Input Parameters:
8563 + A - the matrix
8564 . x - the vector to be multiplied by the interpolation operator
8565 - y - the vector to be added to the result
8566 
8567   Output Parameter:
8568 . w - the resulting vector
8569 
8570   Level: intermediate
8571 
8572   Notes:
8573   `w` may be the same vector as `y`.
8574 
8575   This allows one to use either the restriction or interpolation (its transpose)
8576   matrix to do the interpolation
8577 
8578 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8579 @*/
8580 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8581 {
8582   PetscInt M, N, Ny;
8583 
8584   PetscFunctionBegin;
8585   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8586   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8587   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8588   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8589   PetscCall(MatGetSize(A, &M, &N));
8590   PetscCall(VecGetSize(y, &Ny));
8591   if (M == Ny) {
8592     PetscCall(MatMultAdd(A, x, y, w));
8593   } else {
8594     PetscCall(MatMultTransposeAdd(A, x, y, w));
8595   }
8596   PetscFunctionReturn(PETSC_SUCCESS);
8597 }
8598 
8599 /*@
8600   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8601   the matrix
8602 
8603   Neighbor-wise Collective
8604 
8605   Input Parameters:
8606 + A - the matrix
8607 - x - the vector to be interpolated
8608 
8609   Output Parameter:
8610 . y - the resulting vector
8611 
8612   Level: intermediate
8613 
8614   Note:
8615   This allows one to use either the restriction or interpolation (its transpose)
8616   matrix to do the interpolation
8617 
8618 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8619 @*/
8620 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8621 {
8622   PetscInt M, N, Ny;
8623 
8624   PetscFunctionBegin;
8625   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8626   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8627   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8628   PetscCall(MatGetSize(A, &M, &N));
8629   PetscCall(VecGetSize(y, &Ny));
8630   if (M == Ny) {
8631     PetscCall(MatMult(A, x, y));
8632   } else {
8633     PetscCall(MatMultTranspose(A, x, y));
8634   }
8635   PetscFunctionReturn(PETSC_SUCCESS);
8636 }
8637 
8638 /*@
8639   MatRestrict - $y = A*x$ or $A^T*x$
8640 
8641   Neighbor-wise Collective
8642 
8643   Input Parameters:
8644 + A - the matrix
8645 - x - the vector to be restricted
8646 
8647   Output Parameter:
8648 . y - the resulting vector
8649 
8650   Level: intermediate
8651 
8652   Note:
8653   This allows one to use either the restriction or interpolation (its transpose)
8654   matrix to do the restriction
8655 
8656 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8657 @*/
8658 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8659 {
8660   PetscInt M, N, Nx;
8661 
8662   PetscFunctionBegin;
8663   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8664   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8665   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8666   PetscCall(MatGetSize(A, &M, &N));
8667   PetscCall(VecGetSize(x, &Nx));
8668   if (M == Nx) {
8669     PetscCall(MatMultTranspose(A, x, y));
8670   } else {
8671     PetscCall(MatMult(A, x, y));
8672   }
8673   PetscFunctionReturn(PETSC_SUCCESS);
8674 }
8675 
8676 /*@
8677   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8678 
8679   Neighbor-wise Collective
8680 
8681   Input Parameters:
8682 + A - the matrix
8683 . x - the input dense matrix to be multiplied
8684 - w - the input dense matrix to be added to the result
8685 
8686   Output Parameter:
8687 . y - the output dense matrix
8688 
8689   Level: intermediate
8690 
8691   Note:
8692   This allows one to use either the restriction or interpolation (its transpose)
8693   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8694   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8695 
8696 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8697 @*/
8698 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8699 {
8700   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8701   PetscBool trans = PETSC_TRUE;
8702   MatReuse  reuse = MAT_INITIAL_MATRIX;
8703 
8704   PetscFunctionBegin;
8705   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8706   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8707   PetscValidType(x, 2);
8708   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8709   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8710   PetscCall(MatGetSize(A, &M, &N));
8711   PetscCall(MatGetSize(x, &Mx, &Nx));
8712   if (N == Mx) trans = PETSC_FALSE;
8713   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);
8714   Mo = trans ? N : M;
8715   if (*y) {
8716     PetscCall(MatGetSize(*y, &My, &Ny));
8717     if (Mo == My && Nx == Ny) {
8718       reuse = MAT_REUSE_MATRIX;
8719     } else {
8720       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);
8721       PetscCall(MatDestroy(y));
8722     }
8723   }
8724 
8725   if (w && *y == w) { /* this is to minimize changes in PCMG */
8726     PetscBool flg;
8727 
8728     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8729     if (w) {
8730       PetscInt My, Ny, Mw, Nw;
8731 
8732       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8733       PetscCall(MatGetSize(*y, &My, &Ny));
8734       PetscCall(MatGetSize(w, &Mw, &Nw));
8735       if (!flg || My != Mw || Ny != Nw) w = NULL;
8736     }
8737     if (!w) {
8738       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8739       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8740       PetscCall(PetscObjectDereference((PetscObject)w));
8741     } else {
8742       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8743     }
8744   }
8745   if (!trans) {
8746     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8747   } else {
8748     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8749   }
8750   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8751   PetscFunctionReturn(PETSC_SUCCESS);
8752 }
8753 
8754 /*@
8755   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8756 
8757   Neighbor-wise Collective
8758 
8759   Input Parameters:
8760 + A - the matrix
8761 - x - the input dense matrix
8762 
8763   Output Parameter:
8764 . y - the output dense matrix
8765 
8766   Level: intermediate
8767 
8768   Note:
8769   This allows one to use either the restriction or interpolation (its transpose)
8770   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8771   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8772 
8773 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8774 @*/
8775 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8776 {
8777   PetscFunctionBegin;
8778   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8779   PetscFunctionReturn(PETSC_SUCCESS);
8780 }
8781 
8782 /*@
8783   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8784 
8785   Neighbor-wise Collective
8786 
8787   Input Parameters:
8788 + A - the matrix
8789 - x - the input dense matrix
8790 
8791   Output Parameter:
8792 . y - the output dense matrix
8793 
8794   Level: intermediate
8795 
8796   Note:
8797   This allows one to use either the restriction or interpolation (its transpose)
8798   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8799   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8800 
8801 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8802 @*/
8803 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8804 {
8805   PetscFunctionBegin;
8806   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8807   PetscFunctionReturn(PETSC_SUCCESS);
8808 }
8809 
8810 /*@
8811   MatGetNullSpace - retrieves the null space of a matrix.
8812 
8813   Logically Collective
8814 
8815   Input Parameters:
8816 + mat    - the matrix
8817 - nullsp - the null space object
8818 
8819   Level: developer
8820 
8821 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8822 @*/
8823 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8824 {
8825   PetscFunctionBegin;
8826   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8827   PetscAssertPointer(nullsp, 2);
8828   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8829   PetscFunctionReturn(PETSC_SUCCESS);
8830 }
8831 
8832 /*@C
8833   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8834 
8835   Logically Collective
8836 
8837   Input Parameters:
8838 + n   - the number of matrices
8839 - mat - the array of matrices
8840 
8841   Output Parameters:
8842 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
8843 
8844   Level: developer
8845 
8846   Note:
8847   Call `MatRestoreNullspaces()` to provide these to another array of matrices
8848 
8849 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8850           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8851 @*/
8852 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8853 {
8854   PetscFunctionBegin;
8855   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8856   PetscAssertPointer(mat, 2);
8857   PetscAssertPointer(nullsp, 3);
8858 
8859   PetscCall(PetscCalloc1(3 * n, nullsp));
8860   for (PetscInt i = 0; i < n; i++) {
8861     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8862     (*nullsp)[i] = mat[i]->nullsp;
8863     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
8864     (*nullsp)[n + i] = mat[i]->nearnullsp;
8865     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
8866     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
8867     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
8868   }
8869   PetscFunctionReturn(PETSC_SUCCESS);
8870 }
8871 
8872 /*@C
8873   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
8874 
8875   Logically Collective
8876 
8877   Input Parameters:
8878 + n      - the number of matrices
8879 . mat    - the array of matrices
8880 - nullsp - an array of null spaces
8881 
8882   Level: developer
8883 
8884   Note:
8885   Call `MatGetNullSpaces()` to create `nullsp`
8886 
8887 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8888           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
8889 @*/
8890 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8891 {
8892   PetscFunctionBegin;
8893   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8894   PetscAssertPointer(mat, 2);
8895   PetscAssertPointer(nullsp, 3);
8896   PetscAssertPointer(*nullsp, 3);
8897 
8898   for (PetscInt i = 0; i < n; i++) {
8899     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8900     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
8901     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
8902     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
8903     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
8904     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
8905     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
8906   }
8907   PetscCall(PetscFree(*nullsp));
8908   PetscFunctionReturn(PETSC_SUCCESS);
8909 }
8910 
8911 /*@
8912   MatSetNullSpace - attaches a null space to a matrix.
8913 
8914   Logically Collective
8915 
8916   Input Parameters:
8917 + mat    - the matrix
8918 - nullsp - the null space object
8919 
8920   Level: advanced
8921 
8922   Notes:
8923   This null space is used by the `KSP` linear solvers to solve singular systems.
8924 
8925   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`
8926 
8927   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
8928   to zero but the linear system will still be solved in a least squares sense.
8929 
8930   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8931   the domain of a matrix A (from $R^n$ to $R^m$ (m rows, n columns) $R^n$ = the direct sum of the null space of A, n(A), + the range of $A^T$, $R(A^T)$.
8932   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
8933   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
8934   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$).
8935   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8936 
8937   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8938   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8939   routine also automatically calls `MatSetTransposeNullSpace()`.
8940 
8941   The user should call `MatNullSpaceDestroy()`.
8942 
8943 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8944           `KSPSetPCSide()`
8945 @*/
8946 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8947 {
8948   PetscFunctionBegin;
8949   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8950   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8951   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8952   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8953   mat->nullsp = nullsp;
8954   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8955   PetscFunctionReturn(PETSC_SUCCESS);
8956 }
8957 
8958 /*@
8959   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8960 
8961   Logically Collective
8962 
8963   Input Parameters:
8964 + mat    - the matrix
8965 - nullsp - the null space object
8966 
8967   Level: developer
8968 
8969 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8970 @*/
8971 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8972 {
8973   PetscFunctionBegin;
8974   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8975   PetscValidType(mat, 1);
8976   PetscAssertPointer(nullsp, 2);
8977   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8978   PetscFunctionReturn(PETSC_SUCCESS);
8979 }
8980 
8981 /*@
8982   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8983 
8984   Logically Collective
8985 
8986   Input Parameters:
8987 + mat    - the matrix
8988 - nullsp - the null space object
8989 
8990   Level: advanced
8991 
8992   Notes:
8993   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8994 
8995   See `MatSetNullSpace()`
8996 
8997 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8998 @*/
8999 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9000 {
9001   PetscFunctionBegin;
9002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9003   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9004   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9005   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9006   mat->transnullsp = nullsp;
9007   PetscFunctionReturn(PETSC_SUCCESS);
9008 }
9009 
9010 /*@
9011   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9012   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9013 
9014   Logically Collective
9015 
9016   Input Parameters:
9017 + mat    - the matrix
9018 - nullsp - the null space object
9019 
9020   Level: advanced
9021 
9022   Notes:
9023   Overwrites any previous near null space that may have been attached
9024 
9025   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9026 
9027 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9028 @*/
9029 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9030 {
9031   PetscFunctionBegin;
9032   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9033   PetscValidType(mat, 1);
9034   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9035   MatCheckPreallocated(mat, 1);
9036   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9037   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9038   mat->nearnullsp = nullsp;
9039   PetscFunctionReturn(PETSC_SUCCESS);
9040 }
9041 
9042 /*@
9043   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9044 
9045   Not Collective
9046 
9047   Input Parameter:
9048 . mat - the matrix
9049 
9050   Output Parameter:
9051 . nullsp - the null space object, `NULL` if not set
9052 
9053   Level: advanced
9054 
9055 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9056 @*/
9057 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9058 {
9059   PetscFunctionBegin;
9060   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9061   PetscValidType(mat, 1);
9062   PetscAssertPointer(nullsp, 2);
9063   MatCheckPreallocated(mat, 1);
9064   *nullsp = mat->nearnullsp;
9065   PetscFunctionReturn(PETSC_SUCCESS);
9066 }
9067 
9068 /*@
9069   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9070 
9071   Collective
9072 
9073   Input Parameters:
9074 + mat  - the matrix
9075 . row  - row/column permutation
9076 - info - information on desired factorization process
9077 
9078   Level: developer
9079 
9080   Notes:
9081   Probably really in-place only when level of fill is zero, otherwise allocates
9082   new space to store factored matrix and deletes previous memory.
9083 
9084   Most users should employ the `KSP` interface for linear solvers
9085   instead of working directly with matrix algebra routines such as this.
9086   See, e.g., `KSPCreate()`.
9087 
9088   Developer Note:
9089   The Fortran interface is not autogenerated as the
9090   interface definition cannot be generated correctly [due to `MatFactorInfo`]
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