xref: /petsc/src/mat/interface/matrix.c (revision ebd42cec637123bc092b1c9bcaec243b575fa0f3)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_CreateGraph;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU;
43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48 
49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50 
51 /*@
52   MatSetRandom - Sets all components of a matrix to random numbers.
53 
54   Logically Collective
55 
56   Input Parameters:
57 + x    - the matrix
58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
59           it will create one internally.
60 
61   Example:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68   Level: intermediate
69 
70   Notes:
71   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
72 
73   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
74 
75   It generates an error if used on unassembled sparse matrices that have not been preallocated.
76 
77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
78 @*/
79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81   PetscRandom randObj = NULL;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86   PetscValidType(x, 1);
87   MatCheckPreallocated(x, 1);
88 
89   if (!rctx) {
90     MPI_Comm comm;
91     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92     PetscCall(PetscRandomCreate(comm, &randObj));
93     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94     PetscCall(PetscRandomSetFromOptions(randObj));
95     rctx = randObj;
96   }
97   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98   PetscUseTypeMethod(x, setrandom, rctx);
99   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100 
101   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103   PetscCall(PetscRandomDestroy(&randObj));
104   PetscFunctionReturn(PETSC_SUCCESS);
105 }
106 
107 /*@
108   MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type
109 
110   Logically Collective
111 
112   Input Parameter:
113 . A - A matrix in unassembled, hash table form
114 
115   Output Parameter:
116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()`
117 
118   Example:
119 .vb
120      PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B));
121      PetscCall(MatCopyHashToXAIJ(A, B));
122 .ve
123 
124   Level: advanced
125 
126   Notes:
127   If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled
128 
129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE`
130 @*/
131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
135   PetscUseTypeMethod(A, copyhashtoxaij, B);
136   PetscFunctionReturn(PETSC_SUCCESS);
137 }
138 
139 /*@
140   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
141 
142   Logically Collective
143 
144   Input Parameter:
145 . mat - the factored matrix
146 
147   Output Parameters:
148 + pivot - the pivot value computed
149 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
150          the share the matrix
151 
152   Level: advanced
153 
154   Notes:
155   This routine does not work for factorizations done with external packages.
156 
157   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
158 
159   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
160 
161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
163 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
164 @*/
165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
166 {
167   PetscFunctionBegin;
168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
169   PetscAssertPointer(pivot, 2);
170   PetscAssertPointer(row, 3);
171   *pivot = mat->factorerror_zeropivot_value;
172   *row   = mat->factorerror_zeropivot_row;
173   PetscFunctionReturn(PETSC_SUCCESS);
174 }
175 
176 /*@
177   MatFactorGetError - gets the error code from a factorization
178 
179   Logically Collective
180 
181   Input Parameter:
182 . mat - the factored matrix
183 
184   Output Parameter:
185 . err - the error code
186 
187   Level: advanced
188 
189   Note:
190   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
191 
192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
193           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
194 @*/
195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
196 {
197   PetscFunctionBegin;
198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
199   PetscAssertPointer(err, 2);
200   *err = mat->factorerrortype;
201   PetscFunctionReturn(PETSC_SUCCESS);
202 }
203 
204 /*@
205   MatFactorClearError - clears the error code in a factorization
206 
207   Logically Collective
208 
209   Input Parameter:
210 . mat - the factored matrix
211 
212   Level: developer
213 
214   Note:
215   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
216 
217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
218           `MatGetErrorCode()`, `MatFactorError`
219 @*/
220 PetscErrorCode MatFactorClearError(Mat mat)
221 {
222   PetscFunctionBegin;
223   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
224   mat->factorerrortype             = MAT_FACTOR_NOERROR;
225   mat->factorerror_zeropivot_value = 0.0;
226   mat->factorerror_zeropivot_row   = 0;
227   PetscFunctionReturn(PETSC_SUCCESS);
228 }
229 
230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
231 {
232   Vec                r, l;
233   const PetscScalar *al;
234   PetscInt           i, nz, gnz, N, n, st;
235 
236   PetscFunctionBegin;
237   PetscCall(MatCreateVecs(mat, &r, &l));
238   if (!cols) { /* nonzero rows */
239     PetscCall(MatGetOwnershipRange(mat, &st, NULL));
240     PetscCall(MatGetSize(mat, &N, NULL));
241     PetscCall(MatGetLocalSize(mat, &n, NULL));
242     PetscCall(VecSet(l, 0.0));
243     PetscCall(VecSetRandom(r, NULL));
244     PetscCall(MatMult(mat, r, l));
245     PetscCall(VecGetArrayRead(l, &al));
246   } else { /* nonzero columns */
247     PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
248     PetscCall(MatGetSize(mat, NULL, &N));
249     PetscCall(MatGetLocalSize(mat, NULL, &n));
250     PetscCall(VecSet(r, 0.0));
251     PetscCall(VecSetRandom(l, NULL));
252     PetscCall(MatMultTranspose(mat, l, r));
253     PetscCall(VecGetArrayRead(r, &al));
254   }
255   if (tol <= 0.0) {
256     for (i = 0, nz = 0; i < n; i++)
257       if (al[i] != 0.0) nz++;
258   } else {
259     for (i = 0, nz = 0; i < n; i++)
260       if (PetscAbsScalar(al[i]) > tol) nz++;
261   }
262   PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
263   if (gnz != N) {
264     PetscInt *nzr;
265     PetscCall(PetscMalloc1(nz, &nzr));
266     if (nz) {
267       if (tol < 0) {
268         for (i = 0, nz = 0; i < n; i++)
269           if (al[i] != 0.0) nzr[nz++] = i + st;
270       } else {
271         for (i = 0, nz = 0; i < n; i++)
272           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
273       }
274     }
275     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
276   } else *nonzero = NULL;
277   if (!cols) { /* nonzero rows */
278     PetscCall(VecRestoreArrayRead(l, &al));
279   } else {
280     PetscCall(VecRestoreArrayRead(r, &al));
281   }
282   PetscCall(VecDestroy(&l));
283   PetscCall(VecDestroy(&r));
284   PetscFunctionReturn(PETSC_SUCCESS);
285 }
286 
287 /*@
288   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
289 
290   Input Parameter:
291 . mat - the matrix
292 
293   Output Parameter:
294 . keptrows - the rows that are not completely zero
295 
296   Level: intermediate
297 
298   Note:
299   `keptrows` is set to `NULL` if all rows are nonzero.
300 
301   Developer Note:
302   If `keptrows` is not `NULL`, it must be sorted.
303 
304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
305  @*/
306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
307 {
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
310   PetscValidType(mat, 1);
311   PetscAssertPointer(keptrows, 2);
312   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
313   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
314   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
315   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
316   if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE));
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321   MatFindZeroRows - Locate all rows that are completely zero in the matrix
322 
323   Input Parameter:
324 . mat - the matrix
325 
326   Output Parameter:
327 . zerorows - the rows that are completely zero
328 
329   Level: intermediate
330 
331   Note:
332   `zerorows` is set to `NULL` if no rows are zero.
333 
334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
335  @*/
336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
337 {
338   IS       keptrows;
339   PetscInt m, n;
340 
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
343   PetscValidType(mat, 1);
344   PetscAssertPointer(zerorows, 2);
345   PetscCall(MatFindNonzeroRows(mat, &keptrows));
346   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
347      In keeping with this convention, we set zerorows to NULL if there are no zero
348      rows. */
349   if (keptrows == NULL) {
350     *zerorows = NULL;
351   } else {
352     PetscCall(MatGetOwnershipRange(mat, &m, &n));
353     PetscCall(ISComplement(keptrows, m, n, zerorows));
354     PetscCall(ISDestroy(&keptrows));
355   }
356   PetscFunctionReturn(PETSC_SUCCESS);
357 }
358 
359 /*@
360   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
361 
362   Not Collective
363 
364   Input Parameter:
365 . A - the matrix
366 
367   Output Parameter:
368 . a - the diagonal part (which is a SEQUENTIAL matrix)
369 
370   Level: advanced
371 
372   Notes:
373   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
374 
375   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
376 
377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
378 @*/
379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
380 {
381   PetscFunctionBegin;
382   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
383   PetscValidType(A, 1);
384   PetscAssertPointer(a, 2);
385   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
386   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
387   else {
388     PetscMPIInt size;
389 
390     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
391     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
392     *a = A;
393   }
394   PetscFunctionReturn(PETSC_SUCCESS);
395 }
396 
397 /*@
398   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
399 
400   Collective
401 
402   Input Parameter:
403 . mat - the matrix
404 
405   Output Parameter:
406 . trace - the sum of the diagonal entries
407 
408   Level: advanced
409 
410 .seealso: [](ch_matrices), `Mat`
411 @*/
412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
413 {
414   Vec diag;
415 
416   PetscFunctionBegin;
417   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
418   PetscAssertPointer(trace, 2);
419   PetscCall(MatCreateVecs(mat, &diag, NULL));
420   PetscCall(MatGetDiagonal(mat, diag));
421   PetscCall(VecSum(diag, trace));
422   PetscCall(VecDestroy(&diag));
423   PetscFunctionReturn(PETSC_SUCCESS);
424 }
425 
426 /*@
427   MatRealPart - Zeros out the imaginary part of the matrix
428 
429   Logically Collective
430 
431   Input Parameter:
432 . mat - the matrix
433 
434   Level: advanced
435 
436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
437 @*/
438 PetscErrorCode MatRealPart(Mat mat)
439 {
440   PetscFunctionBegin;
441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
442   PetscValidType(mat, 1);
443   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
444   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
445   MatCheckPreallocated(mat, 1);
446   PetscUseTypeMethod(mat, realpart);
447   PetscFunctionReturn(PETSC_SUCCESS);
448 }
449 
450 /*@C
451   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
452 
453   Collective
454 
455   Input Parameter:
456 . mat - the matrix
457 
458   Output Parameters:
459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
460 - ghosts  - the global indices of the ghost points
461 
462   Level: advanced
463 
464   Note:
465   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
466 
467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
468 @*/
469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
470 {
471   PetscFunctionBegin;
472   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
473   PetscValidType(mat, 1);
474   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
475   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
476   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
477   else {
478     if (nghosts) *nghosts = 0;
479     if (ghosts) *ghosts = NULL;
480   }
481   PetscFunctionReturn(PETSC_SUCCESS);
482 }
483 
484 /*@
485   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
486 
487   Logically Collective
488 
489   Input Parameter:
490 . mat - the matrix
491 
492   Level: advanced
493 
494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
495 @*/
496 PetscErrorCode MatImaginaryPart(Mat mat)
497 {
498   PetscFunctionBegin;
499   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
500   PetscValidType(mat, 1);
501   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
502   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
503   MatCheckPreallocated(mat, 1);
504   PetscUseTypeMethod(mat, imaginarypart);
505   PetscFunctionReturn(PETSC_SUCCESS);
506 }
507 
508 /*@
509   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
510 
511   Not Collective
512 
513   Input Parameter:
514 . mat - the matrix
515 
516   Output Parameters:
517 + missing - is any diagonal entry missing
518 - dd      - first diagonal entry that is missing (optional) on this process
519 
520   Level: advanced
521 
522   Note:
523   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
524 
525 .seealso: [](ch_matrices), `Mat`
526 @*/
527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
528 {
529   PetscFunctionBegin;
530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
531   PetscValidType(mat, 1);
532   PetscAssertPointer(missing, 2);
533   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
534   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
535   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
536   PetscFunctionReturn(PETSC_SUCCESS);
537 }
538 
539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
540 /*@C
541   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
542   for each row that you get to ensure that your application does
543   not bleed memory.
544 
545   Not Collective
546 
547   Input Parameters:
548 + mat - the matrix
549 - row - the row to get
550 
551   Output Parameters:
552 + ncols - if not `NULL`, the number of nonzeros in `row`
553 . cols  - if not `NULL`, the column numbers
554 - vals  - if not `NULL`, the numerical values
555 
556   Level: advanced
557 
558   Notes:
559   This routine is provided for people who need to have direct access
560   to the structure of a matrix.  We hope that we provide enough
561   high-level matrix routines that few users will need it.
562 
563   `MatGetRow()` always returns 0-based column indices, regardless of
564   whether the internal representation is 0-based (default) or 1-based.
565 
566   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
567   not wish to extract these quantities.
568 
569   The user can only examine the values extracted with `MatGetRow()`;
570   the values CANNOT be altered.  To change the matrix entries, one
571   must use `MatSetValues()`.
572 
573   You can only have one call to `MatGetRow()` outstanding for a particular
574   matrix at a time, per processor. `MatGetRow()` can only obtain rows
575   associated with the given processor, it cannot get rows from the
576   other processors; for that we suggest using `MatCreateSubMatrices()`, then
577   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
578   is in the global number of rows.
579 
580   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
581 
582   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
583 
584   Fortran Note:
585 .vb
586   PetscInt, pointer :: cols(:)
587   PetscScalar, pointer :: vals(:)
588 .ve
589 
590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
591 @*/
592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
593 {
594   PetscInt incols;
595 
596   PetscFunctionBegin;
597   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
598   PetscValidType(mat, 1);
599   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
600   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
601   MatCheckPreallocated(mat, 1);
602   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
603   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
604   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
605   if (ncols) *ncols = incols;
606   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
607   PetscFunctionReturn(PETSC_SUCCESS);
608 }
609 
610 /*@
611   MatConjugate - replaces the matrix values with their complex conjugates
612 
613   Logically Collective
614 
615   Input Parameter:
616 . mat - the matrix
617 
618   Level: advanced
619 
620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
621 @*/
622 PetscErrorCode MatConjugate(Mat mat)
623 {
624   PetscFunctionBegin;
625   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
626   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
627   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
628     PetscUseTypeMethod(mat, conjugate);
629     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
630   }
631   PetscFunctionReturn(PETSC_SUCCESS);
632 }
633 
634 /*@C
635   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
636 
637   Not Collective
638 
639   Input Parameters:
640 + mat   - the matrix
641 . row   - the row to get
642 . ncols - the number of nonzeros
643 . cols  - the columns of the nonzeros
644 - vals  - if nonzero the column values
645 
646   Level: advanced
647 
648   Notes:
649   This routine should be called after you have finished examining the entries.
650 
651   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
652   us of the array after it has been restored. If you pass `NULL`, it will
653   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
654 
655   Fortran Note:
656 .vb
657   PetscInt, pointer :: cols(:)
658   PetscScalar, pointer :: vals(:)
659 .ve
660 
661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
662 @*/
663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
664 {
665   PetscFunctionBegin;
666   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
667   if (ncols) PetscAssertPointer(ncols, 3);
668   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
669   PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
670   if (ncols) *ncols = 0;
671   if (cols) *cols = NULL;
672   if (vals) *vals = NULL;
673   PetscFunctionReturn(PETSC_SUCCESS);
674 }
675 
676 /*@
677   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
678   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
679 
680   Not Collective
681 
682   Input Parameter:
683 . mat - the matrix
684 
685   Level: advanced
686 
687   Note:
688   The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
689 
690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
691 @*/
692 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
693 {
694   PetscFunctionBegin;
695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
696   PetscValidType(mat, 1);
697   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
698   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
699   MatCheckPreallocated(mat, 1);
700   PetscTryTypeMethod(mat, getrowuppertriangular);
701   PetscFunctionReturn(PETSC_SUCCESS);
702 }
703 
704 /*@
705   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
706 
707   Not Collective
708 
709   Input Parameter:
710 . mat - the matrix
711 
712   Level: advanced
713 
714   Note:
715   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
716 
717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
718 @*/
719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
720 {
721   PetscFunctionBegin;
722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
723   PetscValidType(mat, 1);
724   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
725   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
726   MatCheckPreallocated(mat, 1);
727   PetscTryTypeMethod(mat, restorerowuppertriangular);
728   PetscFunctionReturn(PETSC_SUCCESS);
729 }
730 
731 /*@
732   MatSetOptionsPrefix - Sets the prefix used for searching for all
733   `Mat` options in the database.
734 
735   Logically Collective
736 
737   Input Parameters:
738 + A      - the matrix
739 - prefix - the prefix to prepend to all option names
740 
741   Level: advanced
742 
743   Notes:
744   A hyphen (-) must NOT be given at the beginning of the prefix name.
745   The first character of all runtime options is AUTOMATICALLY the hyphen.
746 
747   This is NOT used for options for the factorization of the matrix. Normally the
748   prefix is automatically passed in from the PC calling the factorization. To set
749   it directly use  `MatSetOptionsPrefixFactor()`
750 
751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
752 @*/
753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
754 {
755   PetscFunctionBegin;
756   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
757   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
758   PetscFunctionReturn(PETSC_SUCCESS);
759 }
760 
761 /*@
762   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
763   for matrices created with `MatGetFactor()`
764 
765   Logically Collective
766 
767   Input Parameters:
768 + A      - the matrix
769 - prefix - the prefix to prepend to all option names for the factored matrix
770 
771   Level: developer
772 
773   Notes:
774   A hyphen (-) must NOT be given at the beginning of the prefix name.
775   The first character of all runtime options is AUTOMATICALLY the hyphen.
776 
777   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
778   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
779 
780 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
781 @*/
782 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
783 {
784   PetscFunctionBegin;
785   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
786   if (prefix) {
787     PetscAssertPointer(prefix, 2);
788     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
789     if (prefix != A->factorprefix) {
790       PetscCall(PetscFree(A->factorprefix));
791       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
792     }
793   } else PetscCall(PetscFree(A->factorprefix));
794   PetscFunctionReturn(PETSC_SUCCESS);
795 }
796 
797 /*@
798   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
799   for matrices created with `MatGetFactor()`
800 
801   Logically Collective
802 
803   Input Parameters:
804 + A      - the matrix
805 - prefix - the prefix to prepend to all option names for the factored matrix
806 
807   Level: developer
808 
809   Notes:
810   A hyphen (-) must NOT be given at the beginning of the prefix name.
811   The first character of all runtime options is AUTOMATICALLY the hyphen.
812 
813   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
814   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
815 
816 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
817           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
818           `MatSetOptionsPrefix()`
819 @*/
820 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
821 {
822   size_t len1, len2, new_len;
823 
824   PetscFunctionBegin;
825   PetscValidHeader(A, 1);
826   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
827   if (!A->factorprefix) {
828     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
829     PetscFunctionReturn(PETSC_SUCCESS);
830   }
831   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
832 
833   PetscCall(PetscStrlen(A->factorprefix, &len1));
834   PetscCall(PetscStrlen(prefix, &len2));
835   new_len = len1 + len2 + 1;
836   PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
837   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
838   PetscFunctionReturn(PETSC_SUCCESS);
839 }
840 
841 /*@
842   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
843   matrix options in the database.
844 
845   Logically Collective
846 
847   Input Parameters:
848 + A      - the matrix
849 - prefix - the prefix to prepend to all option names
850 
851   Level: advanced
852 
853   Note:
854   A hyphen (-) must NOT be given at the beginning of the prefix name.
855   The first character of all runtime options is AUTOMATICALLY the hyphen.
856 
857 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
858 @*/
859 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
860 {
861   PetscFunctionBegin;
862   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
863   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
864   PetscFunctionReturn(PETSC_SUCCESS);
865 }
866 
867 /*@
868   MatGetOptionsPrefix - Gets the prefix used for searching for all
869   matrix options in the database.
870 
871   Not Collective
872 
873   Input Parameter:
874 . A - the matrix
875 
876   Output Parameter:
877 . prefix - pointer to the prefix string used
878 
879   Level: advanced
880 
881 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
882 @*/
883 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
884 {
885   PetscFunctionBegin;
886   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
887   PetscAssertPointer(prefix, 2);
888   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
889   PetscFunctionReturn(PETSC_SUCCESS);
890 }
891 
892 /*@
893   MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()`
894 
895   Not Collective
896 
897   Input Parameter:
898 . A - the matrix
899 
900   Output Parameter:
901 . state - the object state
902 
903   Level: advanced
904 
905   Note:
906   Object state is an integer which gets increased every time
907   the object is changed. By saving and later querying the object state
908   one can determine whether information about the object is still current.
909 
910   See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed.
911 
912 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()`
913 @*/
914 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
915 {
916   PetscFunctionBegin;
917   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
918   PetscAssertPointer(state, 2);
919   PetscCall(PetscObjectStateGet((PetscObject)A, state));
920   PetscFunctionReturn(PETSC_SUCCESS);
921 }
922 
923 /*@
924   MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()`
925 
926   Collective
927 
928   Input Parameter:
929 . A - the matrix
930 
931   Level: beginner
932 
933   Notes:
934   After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the
935   matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()`
936   makes all of the preallocation space available
937 
938   Current values in the matrix are lost in this call
939 
940   Currently only supported for  `MATAIJ` matrices.
941 
942 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
943 @*/
944 PetscErrorCode MatResetPreallocation(Mat A)
945 {
946   PetscFunctionBegin;
947   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
948   PetscValidType(A, 1);
949   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
950   PetscFunctionReturn(PETSC_SUCCESS);
951 }
952 
953 /*@
954   MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`.
955 
956   Collective
957 
958   Input Parameter:
959 . A - the matrix
960 
961   Level: intermediate
962 
963   Notes:
964   The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
965 
966   Currently only supported for `MATAIJ` matrices.
967 
968 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()`
969 @*/
970 PetscErrorCode MatResetHash(Mat A)
971 {
972   PetscFunctionBegin;
973   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
974   PetscValidType(A, 1);
975   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset to hash state after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()");
976   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
977   PetscUseMethod(A, "MatResetHash_C", (Mat), (A));
978   /* These flags are used to determine whether certain setups occur */
979   A->was_assembled = PETSC_FALSE;
980   A->assembled     = PETSC_FALSE;
981   /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */
982   PetscCall(PetscObjectStateIncrease((PetscObject)A));
983   PetscFunctionReturn(PETSC_SUCCESS);
984 }
985 
986 /*@
987   MatSetUp - Sets up the internal matrix data structures for later use by the matrix
988 
989   Collective
990 
991   Input Parameter:
992 . A - the matrix
993 
994   Level: advanced
995 
996   Notes:
997   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
998   setting values in the matrix.
999 
1000   This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users
1001 
1002 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
1003 @*/
1004 PetscErrorCode MatSetUp(Mat A)
1005 {
1006   PetscFunctionBegin;
1007   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1008   if (!((PetscObject)A)->type_name) {
1009     PetscMPIInt size;
1010 
1011     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1012     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
1013   }
1014   if (!A->preallocated) PetscTryTypeMethod(A, setup);
1015   PetscCall(PetscLayoutSetUp(A->rmap));
1016   PetscCall(PetscLayoutSetUp(A->cmap));
1017   A->preallocated = PETSC_TRUE;
1018   PetscFunctionReturn(PETSC_SUCCESS);
1019 }
1020 
1021 #if defined(PETSC_HAVE_SAWS)
1022   #include <petscviewersaws.h>
1023 #endif
1024 
1025 /*
1026    If threadsafety is on extraneous matrices may be printed
1027 
1028    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
1029 */
1030 #if !defined(PETSC_HAVE_THREADSAFETY)
1031 static PetscInt insidematview = 0;
1032 #endif
1033 
1034 /*@
1035   MatViewFromOptions - View properties of the matrix based on options set in the options database
1036 
1037   Collective
1038 
1039   Input Parameters:
1040 + A    - the matrix
1041 . obj  - optional additional object that provides the options prefix to use
1042 - name - command line option
1043 
1044   Options Database Key:
1045 . -mat_view [viewertype]:... - the viewer and its options
1046 
1047   Level: intermediate
1048 
1049   Note:
1050 .vb
1051     If no value is provided ascii:stdout is used
1052        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1053                                                   for example ascii::ascii_info prints just the information about the object not all details
1054                                                   unless :append is given filename opens in write mode, overwriting what was already there
1055        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1056        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1057        socket[:port]                             defaults to the standard output port
1058        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1059 .ve
1060 
1061 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1062 @*/
1063 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1064 {
1065   PetscFunctionBegin;
1066   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1067 #if !defined(PETSC_HAVE_THREADSAFETY)
1068   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1069 #endif
1070   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1071   PetscFunctionReturn(PETSC_SUCCESS);
1072 }
1073 
1074 /*@
1075   MatView - display information about a matrix in a variety ways
1076 
1077   Collective on viewer
1078 
1079   Input Parameters:
1080 + mat    - the matrix
1081 - viewer - visualization context
1082 
1083   Options Database Keys:
1084 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1085 . -mat_view ::ascii_info_detail    - Prints more detailed info
1086 . -mat_view                        - Prints matrix in ASCII format
1087 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1088 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1089 . -display <name>                  - Sets display name (default is host)
1090 . -draw_pause <sec>                - Sets number of seconds to pause after display
1091 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1092 . -viewer_socket_machine <machine> - -
1093 . -viewer_socket_port <port>       - -
1094 . -mat_view binary                 - save matrix to file in binary format
1095 - -viewer_binary_filename <name>   - -
1096 
1097   Level: beginner
1098 
1099   Notes:
1100   The available visualization contexts include
1101 +    `PETSC_VIEWER_STDOUT_SELF`   - for sequential matrices
1102 .    `PETSC_VIEWER_STDOUT_WORLD`  - for parallel matrices created on `PETSC_COMM_WORLD`
1103 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1104 -     `PETSC_VIEWER_DRAW_WORLD`   - graphical display of nonzero structure
1105 
1106   The user can open alternative visualization contexts with
1107 +    `PetscViewerASCIIOpen()`  - Outputs matrix to a specified file
1108 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a  specified file; corresponding input uses `MatLoad()`
1109 .    `PetscViewerDrawOpen()`   - Outputs nonzero matrix nonzero structure to an X window display
1110 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer.
1111 
1112   The user can call `PetscViewerPushFormat()` to specify the output
1113   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1114   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1115 +    `PETSC_VIEWER_DEFAULT`           - default, prints matrix contents
1116 .    `PETSC_VIEWER_ASCII_MATLAB`      - prints matrix contents in MATLAB format
1117 .    `PETSC_VIEWER_ASCII_DENSE`       - prints entire matrix including zeros
1118 .    `PETSC_VIEWER_ASCII_COMMON`      - prints matrix contents, using a sparse  format common among all matrix types
1119 .    `PETSC_VIEWER_ASCII_IMPL`        - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default)
1120 .    `PETSC_VIEWER_ASCII_INFO`        - prints basic information about the matrix size and structure (not the matrix entries)
1121 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries)
1122 
1123   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1124   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1125 
1126   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1127 
1128   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1129   viewer is used.
1130 
1131   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1132   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1133 
1134   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1135   and then use the following mouse functions.
1136 .vb
1137   left mouse: zoom in
1138   middle mouse: zoom out
1139   right mouse: continue with the simulation
1140 .ve
1141 
1142 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1143           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1144 @*/
1145 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1146 {
1147   PetscInt          rows, cols, rbs, cbs;
1148   PetscBool         isascii, isstring, issaws;
1149   PetscViewerFormat format;
1150   PetscMPIInt       size;
1151 
1152   PetscFunctionBegin;
1153   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1154   PetscValidType(mat, 1);
1155   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1156   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1157 
1158   PetscCall(PetscViewerGetFormat(viewer, &format));
1159   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1160   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1161 
1162 #if !defined(PETSC_HAVE_THREADSAFETY)
1163   insidematview++;
1164 #endif
1165   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1166   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1167   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1168   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1169 
1170   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1171   if (isascii) {
1172     if (!mat->preallocated) {
1173       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1174 #if !defined(PETSC_HAVE_THREADSAFETY)
1175       insidematview--;
1176 #endif
1177       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1178       PetscFunctionReturn(PETSC_SUCCESS);
1179     }
1180     if (!mat->assembled) {
1181       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1182 #if !defined(PETSC_HAVE_THREADSAFETY)
1183       insidematview--;
1184 #endif
1185       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1186       PetscFunctionReturn(PETSC_SUCCESS);
1187     }
1188     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1189     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1190       MatNullSpace nullsp, transnullsp;
1191 
1192       PetscCall(PetscViewerASCIIPushTab(viewer));
1193       PetscCall(MatGetSize(mat, &rows, &cols));
1194       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1195       if (rbs != 1 || cbs != 1) {
1196         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : ""));
1197         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1198       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1199       if (mat->factortype) {
1200         MatSolverType solver;
1201         PetscCall(MatFactorGetSolverType(mat, &solver));
1202         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1203       }
1204       if (mat->ops->getinfo) {
1205         MatInfo info;
1206         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1207         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1208         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1209       }
1210       PetscCall(MatGetNullSpace(mat, &nullsp));
1211       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1212       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1213       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1214       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1215       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1216       PetscCall(PetscViewerASCIIPushTab(viewer));
1217       PetscCall(MatProductView(mat, viewer));
1218       PetscCall(PetscViewerASCIIPopTab(viewer));
1219       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1220         IS tmp;
1221 
1222         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1223         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1224         PetscCall(PetscViewerASCIIPushTab(viewer));
1225         PetscCall(ISView(tmp, viewer));
1226         PetscCall(PetscViewerASCIIPopTab(viewer));
1227         PetscCall(ISDestroy(&tmp));
1228       }
1229     }
1230   } else if (issaws) {
1231 #if defined(PETSC_HAVE_SAWS)
1232     PetscMPIInt rank;
1233 
1234     PetscCall(PetscObjectName((PetscObject)mat));
1235     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1236     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1237 #endif
1238   } else if (isstring) {
1239     const char *type;
1240     PetscCall(MatGetType(mat, &type));
1241     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1242     PetscTryTypeMethod(mat, view, viewer);
1243   }
1244   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1245     PetscCall(PetscViewerASCIIPushTab(viewer));
1246     PetscUseTypeMethod(mat, viewnative, viewer);
1247     PetscCall(PetscViewerASCIIPopTab(viewer));
1248   } else if (mat->ops->view) {
1249     PetscCall(PetscViewerASCIIPushTab(viewer));
1250     PetscUseTypeMethod(mat, view, viewer);
1251     PetscCall(PetscViewerASCIIPopTab(viewer));
1252   }
1253   if (isascii) {
1254     PetscCall(PetscViewerGetFormat(viewer, &format));
1255     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1256   }
1257   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1258 #if !defined(PETSC_HAVE_THREADSAFETY)
1259   insidematview--;
1260 #endif
1261   PetscFunctionReturn(PETSC_SUCCESS);
1262 }
1263 
1264 #if defined(PETSC_USE_DEBUG)
1265   #include <../src/sys/totalview/tv_data_display.h>
1266 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1267 {
1268   TV_add_row("Local rows", "int", &mat->rmap->n);
1269   TV_add_row("Local columns", "int", &mat->cmap->n);
1270   TV_add_row("Global rows", "int", &mat->rmap->N);
1271   TV_add_row("Global columns", "int", &mat->cmap->N);
1272   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1273   return TV_format_OK;
1274 }
1275 #endif
1276 
1277 /*@
1278   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1279   with `MatView()`.  The matrix format is determined from the options database.
1280   Generates a parallel MPI matrix if the communicator has more than one
1281   processor.  The default matrix type is `MATAIJ`.
1282 
1283   Collective
1284 
1285   Input Parameters:
1286 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1287             or some related function before a call to `MatLoad()`
1288 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1289 
1290   Options Database Key:
1291 . -matload_block_size <bs> - set block size
1292 
1293   Level: beginner
1294 
1295   Notes:
1296   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1297   `Mat` before calling this routine if you wish to set it from the options database.
1298 
1299   `MatLoad()` automatically loads into the options database any options
1300   given in the file filename.info where filename is the name of the file
1301   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1302   file will be ignored if you use the -viewer_binary_skip_info option.
1303 
1304   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1305   sets the default matrix type AIJ and sets the local and global sizes.
1306   If type and/or size is already set, then the same are used.
1307 
1308   In parallel, each processor can load a subset of rows (or the
1309   entire matrix).  This routine is especially useful when a large
1310   matrix is stored on disk and only part of it is desired on each
1311   processor.  For example, a parallel solver may access only some of
1312   the rows from each processor.  The algorithm used here reads
1313   relatively small blocks of data rather than reading the entire
1314   matrix and then subsetting it.
1315 
1316   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1317   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1318   or the sequence like
1319 .vb
1320     `PetscViewer` v;
1321     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1322     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1323     `PetscViewerSetFromOptions`(v);
1324     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1325     `PetscViewerFileSetName`(v,"datafile");
1326 .ve
1327   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1328 .vb
1329   -viewer_type {binary, hdf5}
1330 .ve
1331 
1332   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1333   and src/mat/tutorials/ex10.c with the second approach.
1334 
1335   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1336   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1337   Multiple objects, both matrices and vectors, can be stored within the same file.
1338   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1339 
1340   Most users should not need to know the details of the binary storage
1341   format, since `MatLoad()` and `MatView()` completely hide these details.
1342   But for anyone who is interested, the standard binary matrix storage
1343   format is
1344 
1345 .vb
1346     PetscInt    MAT_FILE_CLASSID
1347     PetscInt    number of rows
1348     PetscInt    number of columns
1349     PetscInt    total number of nonzeros
1350     PetscInt    *number nonzeros in each row
1351     PetscInt    *column indices of all nonzeros (starting index is zero)
1352     PetscScalar *values of all nonzeros
1353 .ve
1354   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1355   stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this
1356   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1357 
1358   PETSc automatically does the byte swapping for
1359   machines that store the bytes reversed. Thus if you write your own binary
1360   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1361   and `PetscBinaryWrite()` to see how this may be done.
1362 
1363   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1364   Each processor's chunk is loaded independently by its owning MPI process.
1365   Multiple objects, both matrices and vectors, can be stored within the same file.
1366   They are looked up by their PetscObject name.
1367 
1368   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1369   by default the same structure and naming of the AIJ arrays and column count
1370   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1371 .vb
1372   save example.mat A b -v7.3
1373 .ve
1374   can be directly read by this routine (see Reference 1 for details).
1375 
1376   Depending on your MATLAB version, this format might be a default,
1377   otherwise you can set it as default in Preferences.
1378 
1379   Unless -nocompression flag is used to save the file in MATLAB,
1380   PETSc must be configured with ZLIB package.
1381 
1382   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1383 
1384   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1385 
1386   Corresponding `MatView()` is not yet implemented.
1387 
1388   The loaded matrix is actually a transpose of the original one in MATLAB,
1389   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1390   With this format, matrix is automatically transposed by PETSc,
1391   unless the matrix is marked as SPD or symmetric
1392   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1393 
1394   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1395 
1396 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1397  @*/
1398 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1399 {
1400   PetscBool flg;
1401 
1402   PetscFunctionBegin;
1403   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1404   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1405 
1406   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1407 
1408   flg = PETSC_FALSE;
1409   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1410   if (flg) {
1411     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1412     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1413   }
1414   flg = PETSC_FALSE;
1415   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1416   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1417 
1418   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1419   PetscUseTypeMethod(mat, load, viewer);
1420   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1421   PetscFunctionReturn(PETSC_SUCCESS);
1422 }
1423 
1424 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1425 {
1426   Mat_Redundant *redund = *redundant;
1427 
1428   PetscFunctionBegin;
1429   if (redund) {
1430     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1431       PetscCall(ISDestroy(&redund->isrow));
1432       PetscCall(ISDestroy(&redund->iscol));
1433       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1434     } else {
1435       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1436       PetscCall(PetscFree(redund->sbuf_j));
1437       PetscCall(PetscFree(redund->sbuf_a));
1438       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1439         PetscCall(PetscFree(redund->rbuf_j[i]));
1440         PetscCall(PetscFree(redund->rbuf_a[i]));
1441       }
1442       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1443     }
1444 
1445     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1446     PetscCall(PetscFree(redund));
1447   }
1448   PetscFunctionReturn(PETSC_SUCCESS);
1449 }
1450 
1451 /*@
1452   MatDestroy - Frees space taken by a matrix.
1453 
1454   Collective
1455 
1456   Input Parameter:
1457 . A - the matrix
1458 
1459   Level: beginner
1460 
1461   Developer Note:
1462   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1463   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1464   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1465   if changes are needed here.
1466 
1467 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1468 @*/
1469 PetscErrorCode MatDestroy(Mat *A)
1470 {
1471   PetscFunctionBegin;
1472   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1473   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1474   if (--((PetscObject)*A)->refct > 0) {
1475     *A = NULL;
1476     PetscFunctionReturn(PETSC_SUCCESS);
1477   }
1478 
1479   /* if memory was published with SAWs then destroy it */
1480   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1481   PetscTryTypeMethod(*A, destroy);
1482 
1483   PetscCall(PetscFree((*A)->factorprefix));
1484   PetscCall(PetscFree((*A)->defaultvectype));
1485   PetscCall(PetscFree((*A)->defaultrandtype));
1486   PetscCall(PetscFree((*A)->bsizes));
1487   PetscCall(PetscFree((*A)->solvertype));
1488   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1489   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1490   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1491   PetscCall(MatProductClear(*A));
1492   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1493   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1494   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1495   PetscCall(MatDestroy(&(*A)->schur));
1496   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1497   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1498   PetscCall(PetscHeaderDestroy(A));
1499   PetscFunctionReturn(PETSC_SUCCESS);
1500 }
1501 
1502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1503 /*@
1504   MatSetValues - Inserts or adds a block of values into a matrix.
1505   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1506   MUST be called after all calls to `MatSetValues()` have been completed.
1507 
1508   Not Collective
1509 
1510   Input Parameters:
1511 + mat  - the matrix
1512 . v    - a logically two-dimensional array of values
1513 . m    - the number of rows
1514 . idxm - the global indices of the rows
1515 . n    - the number of columns
1516 . idxn - the global indices of the columns
1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1518 
1519   Level: beginner
1520 
1521   Notes:
1522   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1523 
1524   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1525   options cannot be mixed without intervening calls to the assembly
1526   routines.
1527 
1528   `MatSetValues()` uses 0-based row and column numbers in Fortran
1529   as well as in C.
1530 
1531   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1532   simply ignored. This allows easily inserting element stiffness matrices
1533   with homogeneous Dirichlet boundary conditions that you don't want represented
1534   in the matrix.
1535 
1536   Efficiency Alert:
1537   The routine `MatSetValuesBlocked()` may offer much better efficiency
1538   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1539 
1540   Fortran Notes:
1541   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1542 .vb
1543   call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
1544 .ve
1545 
1546   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1547 
1548   Developer Note:
1549   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1550   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1551 
1552 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1553           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1554 @*/
1555 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1556 {
1557   PetscFunctionBeginHot;
1558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1559   PetscValidType(mat, 1);
1560   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1561   PetscAssertPointer(idxm, 3);
1562   PetscAssertPointer(idxn, 5);
1563   MatCheckPreallocated(mat, 1);
1564 
1565   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1566   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1567 
1568   if (PetscDefined(USE_DEBUG)) {
1569     PetscInt i, j;
1570 
1571     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1572     if (v) {
1573       for (i = 0; i < m; i++) {
1574         for (j = 0; j < n; j++) {
1575           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1576 #if defined(PETSC_USE_COMPLEX)
1577             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1578 #else
1579             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1580 #endif
1581         }
1582       }
1583     }
1584     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1585     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1586   }
1587 
1588   if (mat->assembled) {
1589     mat->was_assembled = PETSC_TRUE;
1590     mat->assembled     = PETSC_FALSE;
1591   }
1592   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1593   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1594   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1595   PetscFunctionReturn(PETSC_SUCCESS);
1596 }
1597 
1598 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1599 /*@
1600   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1601   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1602   MUST be called after all calls to `MatSetValues()` have been completed.
1603 
1604   Not Collective
1605 
1606   Input Parameters:
1607 + mat  - the matrix
1608 . v    - a logically two-dimensional array of values
1609 . ism  - the rows to provide
1610 . isn  - the columns to provide
1611 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1612 
1613   Level: beginner
1614 
1615   Notes:
1616   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1617 
1618   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1619   options cannot be mixed without intervening calls to the assembly
1620   routines.
1621 
1622   `MatSetValues()` uses 0-based row and column numbers in Fortran
1623   as well as in C.
1624 
1625   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1626   simply ignored. This allows easily inserting element stiffness matrices
1627   with homogeneous Dirichlet boundary conditions that you don't want represented
1628   in the matrix.
1629 
1630   Efficiency Alert:
1631   The routine `MatSetValuesBlocked()` may offer much better efficiency
1632   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1633 
1634   This is currently not optimized for any particular `ISType`
1635 
1636 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1637           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1638 @*/
1639 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1640 {
1641   PetscInt        m, n;
1642   const PetscInt *rows, *cols;
1643 
1644   PetscFunctionBeginHot;
1645   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1646   PetscCall(ISGetIndices(ism, &rows));
1647   PetscCall(ISGetIndices(isn, &cols));
1648   PetscCall(ISGetLocalSize(ism, &m));
1649   PetscCall(ISGetLocalSize(isn, &n));
1650   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1651   PetscCall(ISRestoreIndices(ism, &rows));
1652   PetscCall(ISRestoreIndices(isn, &cols));
1653   PetscFunctionReturn(PETSC_SUCCESS);
1654 }
1655 
1656 /*@
1657   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1658   values into a matrix
1659 
1660   Not Collective
1661 
1662   Input Parameters:
1663 + mat - the matrix
1664 . row - the (block) row to set
1665 - v   - a logically two-dimensional array of values
1666 
1667   Level: intermediate
1668 
1669   Notes:
1670   The values, `v`, are column-oriented (for the block version) and sorted
1671 
1672   All the nonzero values in `row` must be provided
1673 
1674   The matrix must have previously had its column indices set, likely by having been assembled.
1675 
1676   `row` must belong to this MPI process
1677 
1678 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1679           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1680 @*/
1681 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1682 {
1683   PetscInt globalrow;
1684 
1685   PetscFunctionBegin;
1686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1687   PetscValidType(mat, 1);
1688   PetscAssertPointer(v, 3);
1689   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1690   PetscCall(MatSetValuesRow(mat, globalrow, v));
1691   PetscFunctionReturn(PETSC_SUCCESS);
1692 }
1693 
1694 /*@
1695   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1696   values into a matrix
1697 
1698   Not Collective
1699 
1700   Input Parameters:
1701 + mat - the matrix
1702 . row - the (block) row to set
1703 - v   - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1704 
1705   Level: advanced
1706 
1707   Notes:
1708   The values, `v`, are column-oriented for the block version.
1709 
1710   All the nonzeros in `row` must be provided
1711 
1712   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1713 
1714   `row` must belong to this process
1715 
1716 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1717           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1718 @*/
1719 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1720 {
1721   PetscFunctionBeginHot;
1722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1723   PetscValidType(mat, 1);
1724   MatCheckPreallocated(mat, 1);
1725   PetscAssertPointer(v, 3);
1726   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1727   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1728   mat->insertmode = INSERT_VALUES;
1729 
1730   if (mat->assembled) {
1731     mat->was_assembled = PETSC_TRUE;
1732     mat->assembled     = PETSC_FALSE;
1733   }
1734   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1735   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1736   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1737   PetscFunctionReturn(PETSC_SUCCESS);
1738 }
1739 
1740 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1741 /*@
1742   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1743   Using structured grid indexing
1744 
1745   Not Collective
1746 
1747   Input Parameters:
1748 + mat  - the matrix
1749 . m    - number of rows being entered
1750 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1751 . n    - number of columns being entered
1752 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1753 . v    - a logically two-dimensional array of values
1754 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1755 
1756   Level: beginner
1757 
1758   Notes:
1759   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1760 
1761   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1762   options cannot be mixed without intervening calls to the assembly
1763   routines.
1764 
1765   The grid coordinates are across the entire grid, not just the local portion
1766 
1767   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1768   as well as in C.
1769 
1770   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1771 
1772   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1773   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1774 
1775   The columns and rows in the stencil passed in MUST be contained within the
1776   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1777   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1778   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1779   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1780 
1781   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1782   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1783   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1784   `DM_BOUNDARY_PERIODIC` boundary type.
1785 
1786   For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1787   a single value per point) you can skip filling those indices.
1788 
1789   Inspired by the structured grid interface to the HYPRE package
1790   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1791 
1792   Efficiency Alert:
1793   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1794   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1795 
1796 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1797           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1798 @*/
1799 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1800 {
1801   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1802   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1803   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1804 
1805   PetscFunctionBegin;
1806   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1808   PetscValidType(mat, 1);
1809   PetscAssertPointer(idxm, 3);
1810   PetscAssertPointer(idxn, 5);
1811 
1812   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1813     jdxm = buf;
1814     jdxn = buf + m;
1815   } else {
1816     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1817     jdxm = bufm;
1818     jdxn = bufn;
1819   }
1820   for (i = 0; i < m; i++) {
1821     for (j = 0; j < 3 - sdim; j++) dxm++;
1822     tmp = *dxm++ - starts[0];
1823     for (j = 0; j < dim - 1; j++) {
1824       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1825       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1826     }
1827     if (mat->stencil.noc) dxm++;
1828     jdxm[i] = tmp;
1829   }
1830   for (i = 0; i < n; i++) {
1831     for (j = 0; j < 3 - sdim; j++) dxn++;
1832     tmp = *dxn++ - starts[0];
1833     for (j = 0; j < dim - 1; j++) {
1834       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1835       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1836     }
1837     if (mat->stencil.noc) dxn++;
1838     jdxn[i] = tmp;
1839   }
1840   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1841   PetscCall(PetscFree2(bufm, bufn));
1842   PetscFunctionReturn(PETSC_SUCCESS);
1843 }
1844 
1845 /*@
1846   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1847   Using structured grid indexing
1848 
1849   Not Collective
1850 
1851   Input Parameters:
1852 + mat  - the matrix
1853 . m    - number of rows being entered
1854 . idxm - grid coordinates for matrix rows being entered
1855 . n    - number of columns being entered
1856 . idxn - grid coordinates for matrix columns being entered
1857 . v    - a logically two-dimensional array of values
1858 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1859 
1860   Level: beginner
1861 
1862   Notes:
1863   By default the values, `v`, are row-oriented and unsorted.
1864   See `MatSetOption()` for other options.
1865 
1866   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1867   options cannot be mixed without intervening calls to the assembly
1868   routines.
1869 
1870   The grid coordinates are across the entire grid, not just the local portion
1871 
1872   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1873   as well as in C.
1874 
1875   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1876 
1877   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1878   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1879 
1880   The columns and rows in the stencil passed in MUST be contained within the
1881   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1882   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1883   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1884   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1885 
1886   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1887   simply ignored. This allows easily inserting element stiffness matrices
1888   with homogeneous Dirichlet boundary conditions that you don't want represented
1889   in the matrix.
1890 
1891   Inspired by the structured grid interface to the HYPRE package
1892   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1893 
1894   Fortran Note:
1895   `idxm` and `idxn` should be declared as
1896 .vb
1897     MatStencil idxm(4,m),idxn(4,n)
1898 .ve
1899   and the values inserted using
1900 .vb
1901     idxm(MatStencil_i,1) = i
1902     idxm(MatStencil_j,1) = j
1903     idxm(MatStencil_k,1) = k
1904    etc
1905 .ve
1906 
1907 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1908           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1909           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1910 @*/
1911 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1912 {
1913   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1914   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1915   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1916 
1917   PetscFunctionBegin;
1918   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1919   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1920   PetscValidType(mat, 1);
1921   PetscAssertPointer(idxm, 3);
1922   PetscAssertPointer(idxn, 5);
1923   PetscAssertPointer(v, 6);
1924 
1925   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1926     jdxm = buf;
1927     jdxn = buf + m;
1928   } else {
1929     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1930     jdxm = bufm;
1931     jdxn = bufn;
1932   }
1933   for (i = 0; i < m; i++) {
1934     for (j = 0; j < 3 - sdim; j++) dxm++;
1935     tmp = *dxm++ - starts[0];
1936     for (j = 0; j < sdim - 1; j++) {
1937       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1938       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1939     }
1940     dxm++;
1941     jdxm[i] = tmp;
1942   }
1943   for (i = 0; i < n; i++) {
1944     for (j = 0; j < 3 - sdim; j++) dxn++;
1945     tmp = *dxn++ - starts[0];
1946     for (j = 0; j < sdim - 1; j++) {
1947       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1948       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1949     }
1950     dxn++;
1951     jdxn[i] = tmp;
1952   }
1953   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1954   PetscCall(PetscFree2(bufm, bufn));
1955   PetscFunctionReturn(PETSC_SUCCESS);
1956 }
1957 
1958 /*@
1959   MatSetStencil - Sets the grid information for setting values into a matrix via
1960   `MatSetValuesStencil()`
1961 
1962   Not Collective
1963 
1964   Input Parameters:
1965 + mat    - the matrix
1966 . dim    - dimension of the grid 1, 2, or 3
1967 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1968 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1969 - dof    - number of degrees of freedom per node
1970 
1971   Level: beginner
1972 
1973   Notes:
1974   Inspired by the structured grid interface to the HYPRE package
1975   (www.llnl.gov/CASC/hyper)
1976 
1977   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1978   user.
1979 
1980 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1981           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1982 @*/
1983 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1984 {
1985   PetscFunctionBegin;
1986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1987   PetscAssertPointer(dims, 3);
1988   PetscAssertPointer(starts, 4);
1989 
1990   mat->stencil.dim = dim + (dof > 1);
1991   for (PetscInt i = 0; i < dim; i++) {
1992     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1993     mat->stencil.starts[i] = starts[dim - i - 1];
1994   }
1995   mat->stencil.dims[dim]   = dof;
1996   mat->stencil.starts[dim] = 0;
1997   mat->stencil.noc         = (PetscBool)(dof == 1);
1998   PetscFunctionReturn(PETSC_SUCCESS);
1999 }
2000 
2001 /*@
2002   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
2003 
2004   Not Collective
2005 
2006   Input Parameters:
2007 + mat  - the matrix
2008 . 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 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2219           `MatSetValuesLocal()`, `MatGetValues()`
2220 @*/
2221 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2222 {
2223   PetscFunctionBeginHot;
2224   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2225   PetscValidType(mat, 1);
2226   MatCheckPreallocated(mat, 1);
2227   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2228   PetscAssertPointer(irow, 3);
2229   PetscAssertPointer(icol, 5);
2230   if (PetscDefined(USE_DEBUG)) {
2231     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2232     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2233   }
2234   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2235   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2236   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2237   else {
2238     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2239     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2240       irowm = buf;
2241       icolm = buf + nrow;
2242     } else {
2243       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2244       irowm = bufr;
2245       icolm = bufc;
2246     }
2247     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2248     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2249     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2250     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2251     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2252     PetscCall(PetscFree2(bufr, bufc));
2253   }
2254   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2255   PetscFunctionReturn(PETSC_SUCCESS);
2256 }
2257 
2258 /*@
2259   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2260   the same size. Currently, this can only be called once and creates the given matrix.
2261 
2262   Not Collective
2263 
2264   Input Parameters:
2265 + mat  - the matrix
2266 . nb   - the number of blocks
2267 . bs   - the number of rows (and columns) in each block
2268 . rows - a concatenation of the rows for each block
2269 - v    - a concatenation of logically two-dimensional arrays of values
2270 
2271   Level: advanced
2272 
2273   Notes:
2274   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2275 
2276   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2277 
2278 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2279           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2280 @*/
2281 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2282 {
2283   PetscFunctionBegin;
2284   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2285   PetscValidType(mat, 1);
2286   PetscAssertPointer(rows, 4);
2287   PetscAssertPointer(v, 5);
2288   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2289 
2290   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2291   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2292   else {
2293     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2294   }
2295   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2296   PetscFunctionReturn(PETSC_SUCCESS);
2297 }
2298 
2299 /*@
2300   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2301   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2302   using a local (per-processor) numbering.
2303 
2304   Not Collective
2305 
2306   Input Parameters:
2307 + x        - the matrix
2308 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2309 - cmapping - column mapping
2310 
2311   Level: intermediate
2312 
2313   Note:
2314   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2315 
2316 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2317 @*/
2318 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2319 {
2320   PetscFunctionBegin;
2321   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2322   PetscValidType(x, 1);
2323   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2324   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2325   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2326   else {
2327     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2328     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2329   }
2330   PetscFunctionReturn(PETSC_SUCCESS);
2331 }
2332 
2333 /*@
2334   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2335 
2336   Not Collective
2337 
2338   Input Parameter:
2339 . A - the matrix
2340 
2341   Output Parameters:
2342 + rmapping - row mapping
2343 - cmapping - column mapping
2344 
2345   Level: advanced
2346 
2347 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2348 @*/
2349 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2350 {
2351   PetscFunctionBegin;
2352   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2353   PetscValidType(A, 1);
2354   if (rmapping) {
2355     PetscAssertPointer(rmapping, 2);
2356     *rmapping = A->rmap->mapping;
2357   }
2358   if (cmapping) {
2359     PetscAssertPointer(cmapping, 3);
2360     *cmapping = A->cmap->mapping;
2361   }
2362   PetscFunctionReturn(PETSC_SUCCESS);
2363 }
2364 
2365 /*@
2366   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2367 
2368   Logically Collective
2369 
2370   Input Parameters:
2371 + A    - the matrix
2372 . rmap - row layout
2373 - cmap - column layout
2374 
2375   Level: advanced
2376 
2377   Note:
2378   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2379 
2380 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2381 @*/
2382 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2383 {
2384   PetscFunctionBegin;
2385   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2386   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2387   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2388   PetscFunctionReturn(PETSC_SUCCESS);
2389 }
2390 
2391 /*@
2392   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2393 
2394   Not Collective
2395 
2396   Input Parameter:
2397 . A - the matrix
2398 
2399   Output Parameters:
2400 + rmap - row layout
2401 - cmap - column layout
2402 
2403   Level: advanced
2404 
2405 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2406 @*/
2407 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2408 {
2409   PetscFunctionBegin;
2410   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2411   PetscValidType(A, 1);
2412   if (rmap) {
2413     PetscAssertPointer(rmap, 2);
2414     *rmap = A->rmap;
2415   }
2416   if (cmap) {
2417     PetscAssertPointer(cmap, 3);
2418     *cmap = A->cmap;
2419   }
2420   PetscFunctionReturn(PETSC_SUCCESS);
2421 }
2422 
2423 /*@
2424   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2425   using a local numbering of the rows and columns.
2426 
2427   Not Collective
2428 
2429   Input Parameters:
2430 + mat  - the matrix
2431 . nrow - number of rows
2432 . irow - the row local indices
2433 . ncol - number of columns
2434 . icol - the column local indices
2435 . y    - a logically two-dimensional array of values
2436 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2437 
2438   Level: intermediate
2439 
2440   Notes:
2441   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2442 
2443   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2444   options cannot be mixed without intervening calls to the assembly
2445   routines.
2446 
2447   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2448   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2449 
2450   Fortran Notes:
2451   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2452 .vb
2453   call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2454 .ve
2455 
2456   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2457 
2458 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2459           `MatGetValuesLocal()`
2460 @*/
2461 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2462 {
2463   PetscFunctionBeginHot;
2464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2465   PetscValidType(mat, 1);
2466   MatCheckPreallocated(mat, 1);
2467   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2468   PetscAssertPointer(irow, 3);
2469   PetscAssertPointer(icol, 5);
2470   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2471   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2472   if (PetscDefined(USE_DEBUG)) {
2473     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2474     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2475   }
2476 
2477   if (mat->assembled) {
2478     mat->was_assembled = PETSC_TRUE;
2479     mat->assembled     = PETSC_FALSE;
2480   }
2481   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2482   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2483   else {
2484     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2485     const PetscInt *irowm, *icolm;
2486 
2487     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2488       bufr  = buf;
2489       bufc  = buf + nrow;
2490       irowm = bufr;
2491       icolm = bufc;
2492     } else {
2493       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2494       irowm = bufr;
2495       icolm = bufc;
2496     }
2497     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2498     else irowm = irow;
2499     if (mat->cmap->mapping) {
2500       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2501         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2502       } else icolm = irowm;
2503     } else icolm = icol;
2504     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2505     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2506   }
2507   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2508   PetscFunctionReturn(PETSC_SUCCESS);
2509 }
2510 
2511 /*@
2512   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2513   using a local ordering of the nodes a block at a time.
2514 
2515   Not Collective
2516 
2517   Input Parameters:
2518 + mat  - the matrix
2519 . nrow - number of rows
2520 . irow - the row local indices
2521 . ncol - number of columns
2522 . icol - the column local indices
2523 . y    - a logically two-dimensional array of values
2524 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2525 
2526   Level: intermediate
2527 
2528   Notes:
2529   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2530   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2531 
2532   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2533   options cannot be mixed without intervening calls to the assembly
2534   routines.
2535 
2536   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2537   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2538 
2539   Fortran Notes:
2540   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2541 .vb
2542   call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2543 .ve
2544 
2545   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2546 
2547 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2548           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2549 @*/
2550 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2551 {
2552   PetscFunctionBeginHot;
2553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2554   PetscValidType(mat, 1);
2555   MatCheckPreallocated(mat, 1);
2556   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2557   PetscAssertPointer(irow, 3);
2558   PetscAssertPointer(icol, 5);
2559   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2560   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2561   if (PetscDefined(USE_DEBUG)) {
2562     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2563     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);
2564   }
2565 
2566   if (mat->assembled) {
2567     mat->was_assembled = PETSC_TRUE;
2568     mat->assembled     = PETSC_FALSE;
2569   }
2570   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2571     PetscInt irbs, rbs;
2572     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2573     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2574     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2575   }
2576   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2577     PetscInt icbs, cbs;
2578     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2579     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2580     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2581   }
2582   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2583   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2584   else {
2585     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2586     const PetscInt *irowm, *icolm;
2587 
2588     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2589       bufr  = buf;
2590       bufc  = buf + nrow;
2591       irowm = bufr;
2592       icolm = bufc;
2593     } else {
2594       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2595       irowm = bufr;
2596       icolm = bufc;
2597     }
2598     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2599     else irowm = irow;
2600     if (mat->cmap->mapping) {
2601       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2602         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2603       } else icolm = irowm;
2604     } else icolm = icol;
2605     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2606     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2607   }
2608   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2609   PetscFunctionReturn(PETSC_SUCCESS);
2610 }
2611 
2612 /*@
2613   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2614 
2615   Collective
2616 
2617   Input Parameters:
2618 + mat - the matrix
2619 - x   - the vector to be multiplied
2620 
2621   Output Parameter:
2622 . y - the result
2623 
2624   Level: developer
2625 
2626   Note:
2627   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2628   call `MatMultDiagonalBlock`(A,y,y).
2629 
2630 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2631 @*/
2632 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2633 {
2634   PetscFunctionBegin;
2635   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2636   PetscValidType(mat, 1);
2637   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2638   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2639 
2640   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2641   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2642   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2643   MatCheckPreallocated(mat, 1);
2644 
2645   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2646   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2647   PetscFunctionReturn(PETSC_SUCCESS);
2648 }
2649 
2650 /*@
2651   MatMult - Computes the matrix-vector product, $y = Ax$.
2652 
2653   Neighbor-wise Collective
2654 
2655   Input Parameters:
2656 + mat - the matrix
2657 - x   - the vector to be multiplied
2658 
2659   Output Parameter:
2660 . y - the result
2661 
2662   Level: beginner
2663 
2664   Note:
2665   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2666   call `MatMult`(A,y,y).
2667 
2668 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2669 @*/
2670 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2671 {
2672   PetscFunctionBegin;
2673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2674   PetscValidType(mat, 1);
2675   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2676   VecCheckAssembled(x);
2677   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2678   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2679   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2680   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2681   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);
2682   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);
2683   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);
2684   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);
2685   PetscCall(VecSetErrorIfLocked(y, 3));
2686   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2687   MatCheckPreallocated(mat, 1);
2688 
2689   PetscCall(VecLockReadPush(x));
2690   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2691   PetscUseTypeMethod(mat, mult, x, y);
2692   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2693   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2694   PetscCall(VecLockReadPop(x));
2695   PetscFunctionReturn(PETSC_SUCCESS);
2696 }
2697 
2698 /*@
2699   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2700 
2701   Neighbor-wise Collective
2702 
2703   Input Parameters:
2704 + mat - the matrix
2705 - x   - the vector to be multiplied
2706 
2707   Output Parameter:
2708 . y - the result
2709 
2710   Level: beginner
2711 
2712   Notes:
2713   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2714   call `MatMultTranspose`(A,y,y).
2715 
2716   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2717   use `MatMultHermitianTranspose()`
2718 
2719 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2720 @*/
2721 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2722 {
2723   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2724 
2725   PetscFunctionBegin;
2726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2727   PetscValidType(mat, 1);
2728   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2729   VecCheckAssembled(x);
2730   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2731 
2732   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2733   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2734   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2735   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);
2736   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);
2737   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);
2738   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);
2739   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2740   MatCheckPreallocated(mat, 1);
2741 
2742   if (!mat->ops->multtranspose) {
2743     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2744     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);
2745   } else op = mat->ops->multtranspose;
2746   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2747   PetscCall(VecLockReadPush(x));
2748   PetscCall((*op)(mat, x, y));
2749   PetscCall(VecLockReadPop(x));
2750   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2751   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2752   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2753   PetscFunctionReturn(PETSC_SUCCESS);
2754 }
2755 
2756 /*@
2757   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2758 
2759   Neighbor-wise Collective
2760 
2761   Input Parameters:
2762 + mat - the matrix
2763 - x   - the vector to be multiplied
2764 
2765   Output Parameter:
2766 . y - the result
2767 
2768   Level: beginner
2769 
2770   Notes:
2771   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2772   call `MatMultHermitianTranspose`(A,y,y).
2773 
2774   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2775 
2776   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2777 
2778 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2779 @*/
2780 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2781 {
2782   PetscFunctionBegin;
2783   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2784   PetscValidType(mat, 1);
2785   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2786   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2787 
2788   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2789   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2790   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2791   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);
2792   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);
2793   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);
2794   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);
2795   MatCheckPreallocated(mat, 1);
2796 
2797   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2798 #if defined(PETSC_USE_COMPLEX)
2799   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2800     PetscCall(VecLockReadPush(x));
2801     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2802     else PetscUseTypeMethod(mat, mult, x, y);
2803     PetscCall(VecLockReadPop(x));
2804   } else {
2805     Vec w;
2806     PetscCall(VecDuplicate(x, &w));
2807     PetscCall(VecCopy(x, w));
2808     PetscCall(VecConjugate(w));
2809     PetscCall(MatMultTranspose(mat, w, y));
2810     PetscCall(VecDestroy(&w));
2811     PetscCall(VecConjugate(y));
2812   }
2813   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2814 #else
2815   PetscCall(MatMultTranspose(mat, x, y));
2816 #endif
2817   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2818   PetscFunctionReturn(PETSC_SUCCESS);
2819 }
2820 
2821 /*@
2822   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2823 
2824   Neighbor-wise Collective
2825 
2826   Input Parameters:
2827 + mat - the matrix
2828 . v1  - the vector to be multiplied by `mat`
2829 - v2  - the vector to be added to the result
2830 
2831   Output Parameter:
2832 . v3 - the result
2833 
2834   Level: beginner
2835 
2836   Note:
2837   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2838   call `MatMultAdd`(A,v1,v2,v1).
2839 
2840 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2841 @*/
2842 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2843 {
2844   PetscFunctionBegin;
2845   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2846   PetscValidType(mat, 1);
2847   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2848   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2849   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2850 
2851   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2852   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2853   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);
2854   /* 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);
2855      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); */
2856   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);
2857   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);
2858   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2859   MatCheckPreallocated(mat, 1);
2860 
2861   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2862   PetscCall(VecLockReadPush(v1));
2863   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2864   PetscCall(VecLockReadPop(v1));
2865   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2866   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2867   PetscFunctionReturn(PETSC_SUCCESS);
2868 }
2869 
2870 /*@
2871   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2872 
2873   Neighbor-wise Collective
2874 
2875   Input Parameters:
2876 + mat - the matrix
2877 . v1  - the vector to be multiplied by the transpose of the matrix
2878 - v2  - the vector to be added to the result
2879 
2880   Output Parameter:
2881 . v3 - the result
2882 
2883   Level: beginner
2884 
2885   Note:
2886   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2887   call `MatMultTransposeAdd`(A,v1,v2,v1).
2888 
2889 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2890 @*/
2891 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2892 {
2893   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2894 
2895   PetscFunctionBegin;
2896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2897   PetscValidType(mat, 1);
2898   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2899   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2900   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2901 
2902   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2903   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2904   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);
2905   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);
2906   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);
2907   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2908   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2909   MatCheckPreallocated(mat, 1);
2910 
2911   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2912   PetscCall(VecLockReadPush(v1));
2913   PetscCall((*op)(mat, v1, v2, v3));
2914   PetscCall(VecLockReadPop(v1));
2915   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2916   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2917   PetscFunctionReturn(PETSC_SUCCESS);
2918 }
2919 
2920 /*@
2921   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2922 
2923   Neighbor-wise Collective
2924 
2925   Input Parameters:
2926 + mat - the matrix
2927 . v1  - the vector to be multiplied by the Hermitian transpose
2928 - v2  - the vector to be added to the result
2929 
2930   Output Parameter:
2931 . v3 - the result
2932 
2933   Level: beginner
2934 
2935   Note:
2936   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2937   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2938 
2939 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2940 @*/
2941 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2942 {
2943   PetscFunctionBegin;
2944   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2945   PetscValidType(mat, 1);
2946   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2947   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2948   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2949 
2950   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2951   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2952   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2953   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);
2954   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);
2955   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);
2956   MatCheckPreallocated(mat, 1);
2957 
2958   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2959   PetscCall(VecLockReadPush(v1));
2960   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2961   else {
2962     Vec w, z;
2963     PetscCall(VecDuplicate(v1, &w));
2964     PetscCall(VecCopy(v1, w));
2965     PetscCall(VecConjugate(w));
2966     PetscCall(VecDuplicate(v3, &z));
2967     PetscCall(MatMultTranspose(mat, w, z));
2968     PetscCall(VecDestroy(&w));
2969     PetscCall(VecConjugate(z));
2970     if (v2 != v3) {
2971       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2972     } else {
2973       PetscCall(VecAXPY(v3, 1.0, z));
2974     }
2975     PetscCall(VecDestroy(&z));
2976   }
2977   PetscCall(VecLockReadPop(v1));
2978   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2979   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2980   PetscFunctionReturn(PETSC_SUCCESS);
2981 }
2982 
2983 /*@
2984   MatGetFactorType - gets the type of factorization a matrix is
2985 
2986   Not Collective
2987 
2988   Input Parameter:
2989 . mat - the matrix
2990 
2991   Output Parameter:
2992 . 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`
2993 
2994   Level: intermediate
2995 
2996 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2997           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2998 @*/
2999 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
3000 {
3001   PetscFunctionBegin;
3002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3003   PetscValidType(mat, 1);
3004   PetscAssertPointer(t, 2);
3005   *t = mat->factortype;
3006   PetscFunctionReturn(PETSC_SUCCESS);
3007 }
3008 
3009 /*@
3010   MatSetFactorType - sets the type of factorization a matrix is
3011 
3012   Logically Collective
3013 
3014   Input Parameters:
3015 + mat - the matrix
3016 - 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`
3017 
3018   Level: intermediate
3019 
3020 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3021           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3022 @*/
3023 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
3024 {
3025   PetscFunctionBegin;
3026   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3027   PetscValidType(mat, 1);
3028   mat->factortype = t;
3029   PetscFunctionReturn(PETSC_SUCCESS);
3030 }
3031 
3032 /*@
3033   MatGetInfo - Returns information about matrix storage (number of
3034   nonzeros, memory, etc.).
3035 
3036   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3037 
3038   Input Parameters:
3039 + mat  - the matrix
3040 - 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)
3041 
3042   Output Parameter:
3043 . info - matrix information context
3044 
3045   Options Database Key:
3046 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3047 
3048   Level: intermediate
3049 
3050   Notes:
3051   The `MatInfo` context contains a variety of matrix data, including
3052   number of nonzeros allocated and used, number of mallocs during
3053   matrix assembly, etc.  Additional information for factored matrices
3054   is provided (such as the fill ratio, number of mallocs during
3055   factorization, etc.).
3056 
3057   Example:
3058   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3059   data within the `MatInfo` context.  For example,
3060 .vb
3061       MatInfo info;
3062       Mat     A;
3063       double  mal, nz_a, nz_u;
3064 
3065       MatGetInfo(A, MAT_LOCAL, &info);
3066       mal  = info.mallocs;
3067       nz_a = info.nz_allocated;
3068 .ve
3069 
3070 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3071 @*/
3072 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3073 {
3074   PetscFunctionBegin;
3075   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3076   PetscValidType(mat, 1);
3077   PetscAssertPointer(info, 3);
3078   MatCheckPreallocated(mat, 1);
3079   PetscUseTypeMethod(mat, getinfo, flag, info);
3080   PetscFunctionReturn(PETSC_SUCCESS);
3081 }
3082 
3083 /*
3084    This is used by external packages where it is not easy to get the info from the actual
3085    matrix factorization.
3086 */
3087 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3088 {
3089   PetscFunctionBegin;
3090   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3091   PetscFunctionReturn(PETSC_SUCCESS);
3092 }
3093 
3094 /*@
3095   MatLUFactor - Performs in-place LU factorization of matrix.
3096 
3097   Collective
3098 
3099   Input Parameters:
3100 + mat  - the matrix
3101 . row  - row permutation
3102 . col  - column permutation
3103 - info - options for factorization, includes
3104 .vb
3105           fill - expected fill as ratio of original fill.
3106           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3107                    Run with the option -info to determine an optimal value to use
3108 .ve
3109 
3110   Level: developer
3111 
3112   Notes:
3113   Most users should employ the `KSP` interface for linear solvers
3114   instead of working directly with matrix algebra routines such as this.
3115   See, e.g., `KSPCreate()`.
3116 
3117   This changes the state of the matrix to a factored matrix; it cannot be used
3118   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3119 
3120   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3121   when not using `KSP`.
3122 
3123   Fortran Note:
3124   A valid (non-null) `info` argument must be provided
3125 
3126 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3127           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3128 @*/
3129 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3130 {
3131   MatFactorInfo tinfo;
3132 
3133   PetscFunctionBegin;
3134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3135   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3136   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3137   if (info) PetscAssertPointer(info, 4);
3138   PetscValidType(mat, 1);
3139   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3140   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3141   MatCheckPreallocated(mat, 1);
3142   if (!info) {
3143     PetscCall(MatFactorInfoInitialize(&tinfo));
3144     info = &tinfo;
3145   }
3146 
3147   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3148   PetscUseTypeMethod(mat, lufactor, row, col, info);
3149   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3150   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3151   PetscFunctionReturn(PETSC_SUCCESS);
3152 }
3153 
3154 /*@
3155   MatILUFactor - Performs in-place ILU factorization of matrix.
3156 
3157   Collective
3158 
3159   Input Parameters:
3160 + mat  - the matrix
3161 . row  - row permutation
3162 . col  - column permutation
3163 - info - structure containing
3164 .vb
3165       levels - number of levels of fill.
3166       expected fill - as ratio of original fill.
3167       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3168                 missing diagonal entries)
3169 .ve
3170 
3171   Level: developer
3172 
3173   Notes:
3174   Most users should employ the `KSP` interface for linear solvers
3175   instead of working directly with matrix algebra routines such as this.
3176   See, e.g., `KSPCreate()`.
3177 
3178   Probably really in-place only when level of fill is zero, otherwise allocates
3179   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3180   when not using `KSP`.
3181 
3182   Fortran Note:
3183   A valid (non-null) `info` argument must be provided
3184 
3185 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3186 @*/
3187 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3188 {
3189   PetscFunctionBegin;
3190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3191   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3192   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3193   PetscAssertPointer(info, 4);
3194   PetscValidType(mat, 1);
3195   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3196   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3197   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3198   MatCheckPreallocated(mat, 1);
3199 
3200   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3201   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3202   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3203   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3204   PetscFunctionReturn(PETSC_SUCCESS);
3205 }
3206 
3207 /*@
3208   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3209   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3210 
3211   Collective
3212 
3213   Input Parameters:
3214 + fact - the factor matrix obtained with `MatGetFactor()`
3215 . mat  - the matrix
3216 . row  - the row permutation
3217 . col  - the column permutation
3218 - info - options for factorization, includes
3219 .vb
3220           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3221           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3222 .ve
3223 
3224   Level: developer
3225 
3226   Notes:
3227   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3228 
3229   Most users should employ the simplified `KSP` interface for linear solvers
3230   instead of working directly with matrix algebra routines such as this.
3231   See, e.g., `KSPCreate()`.
3232 
3233   Fortran Note:
3234   A valid (non-null) `info` argument must be provided
3235 
3236 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3237 @*/
3238 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3239 {
3240   MatFactorInfo tinfo;
3241 
3242   PetscFunctionBegin;
3243   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3245   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3246   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3247   if (info) PetscAssertPointer(info, 5);
3248   PetscValidType(fact, 1);
3249   PetscValidType(mat, 2);
3250   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3251   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3252   MatCheckPreallocated(mat, 2);
3253   if (!info) {
3254     PetscCall(MatFactorInfoInitialize(&tinfo));
3255     info = &tinfo;
3256   }
3257 
3258   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3259   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3260   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3261   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3262   PetscFunctionReturn(PETSC_SUCCESS);
3263 }
3264 
3265 /*@
3266   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3267   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3268 
3269   Collective
3270 
3271   Input Parameters:
3272 + fact - the factor matrix obtained with `MatGetFactor()`
3273 . mat  - the matrix
3274 - info - options for factorization
3275 
3276   Level: developer
3277 
3278   Notes:
3279   See `MatLUFactor()` for in-place factorization.  See
3280   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3281 
3282   Most users should employ the `KSP` interface for linear solvers
3283   instead of working directly with matrix algebra routines such as this.
3284   See, e.g., `KSPCreate()`.
3285 
3286   Fortran Note:
3287   A valid (non-null) `info` argument must be provided
3288 
3289 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3290 @*/
3291 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3292 {
3293   MatFactorInfo tinfo;
3294 
3295   PetscFunctionBegin;
3296   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3297   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3298   PetscValidType(fact, 1);
3299   PetscValidType(mat, 2);
3300   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3301   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,
3302              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3303 
3304   MatCheckPreallocated(mat, 2);
3305   if (!info) {
3306     PetscCall(MatFactorInfoInitialize(&tinfo));
3307     info = &tinfo;
3308   }
3309 
3310   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3311   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3312   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3313   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3314   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3315   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3316   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3317   PetscFunctionReturn(PETSC_SUCCESS);
3318 }
3319 
3320 /*@
3321   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3322   symmetric matrix.
3323 
3324   Collective
3325 
3326   Input Parameters:
3327 + mat  - the matrix
3328 . perm - row and column permutations
3329 - info - expected fill as ratio of original fill
3330 
3331   Level: developer
3332 
3333   Notes:
3334   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3335   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3336 
3337   Most users should employ the `KSP` interface for linear solvers
3338   instead of working directly with matrix algebra routines such as this.
3339   See, e.g., `KSPCreate()`.
3340 
3341   Fortran Note:
3342   A valid (non-null) `info` argument must be provided
3343 
3344 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3345           `MatGetOrdering()`
3346 @*/
3347 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3348 {
3349   MatFactorInfo tinfo;
3350 
3351   PetscFunctionBegin;
3352   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3353   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3354   if (info) PetscAssertPointer(info, 3);
3355   PetscValidType(mat, 1);
3356   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3357   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3358   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3359   MatCheckPreallocated(mat, 1);
3360   if (!info) {
3361     PetscCall(MatFactorInfoInitialize(&tinfo));
3362     info = &tinfo;
3363   }
3364 
3365   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3366   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3367   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3368   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3369   PetscFunctionReturn(PETSC_SUCCESS);
3370 }
3371 
3372 /*@
3373   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3374   of a symmetric matrix.
3375 
3376   Collective
3377 
3378   Input Parameters:
3379 + fact - the factor matrix obtained with `MatGetFactor()`
3380 . mat  - the matrix
3381 . perm - row and column permutations
3382 - info - options for factorization, includes
3383 .vb
3384           fill - expected fill as ratio of original fill.
3385           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3386                    Run with the option -info to determine an optimal value to use
3387 .ve
3388 
3389   Level: developer
3390 
3391   Notes:
3392   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3393   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3394 
3395   Most users should employ the `KSP` interface for linear solvers
3396   instead of working directly with matrix algebra routines such as this.
3397   See, e.g., `KSPCreate()`.
3398 
3399   Fortran Note:
3400   A valid (non-null) `info` argument must be provided
3401 
3402 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3403           `MatGetOrdering()`
3404 @*/
3405 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3406 {
3407   MatFactorInfo tinfo;
3408 
3409   PetscFunctionBegin;
3410   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3411   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3412   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3413   if (info) PetscAssertPointer(info, 4);
3414   PetscValidType(fact, 1);
3415   PetscValidType(mat, 2);
3416   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3417   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3418   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3419   MatCheckPreallocated(mat, 2);
3420   if (!info) {
3421     PetscCall(MatFactorInfoInitialize(&tinfo));
3422     info = &tinfo;
3423   }
3424 
3425   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3426   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3427   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3428   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3429   PetscFunctionReturn(PETSC_SUCCESS);
3430 }
3431 
3432 /*@
3433   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3434   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3435   `MatCholeskyFactorSymbolic()`.
3436 
3437   Collective
3438 
3439   Input Parameters:
3440 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3441 . mat  - the initial matrix that is to be factored
3442 - info - options for factorization
3443 
3444   Level: developer
3445 
3446   Note:
3447   Most users should employ the `KSP` interface for linear solvers
3448   instead of working directly with matrix algebra routines such as this.
3449   See, e.g., `KSPCreate()`.
3450 
3451   Fortran Note:
3452   A valid (non-null) `info` argument must be provided
3453 
3454 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3455 @*/
3456 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3457 {
3458   MatFactorInfo tinfo;
3459 
3460   PetscFunctionBegin;
3461   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3463   PetscValidType(fact, 1);
3464   PetscValidType(mat, 2);
3465   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3466   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,
3467              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3468   MatCheckPreallocated(mat, 2);
3469   if (!info) {
3470     PetscCall(MatFactorInfoInitialize(&tinfo));
3471     info = &tinfo;
3472   }
3473 
3474   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3475   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3476   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3477   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3478   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3479   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3480   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3481   PetscFunctionReturn(PETSC_SUCCESS);
3482 }
3483 
3484 /*@
3485   MatQRFactor - Performs in-place QR factorization of matrix.
3486 
3487   Collective
3488 
3489   Input Parameters:
3490 + mat  - the matrix
3491 . col  - column permutation
3492 - info - options for factorization, includes
3493 .vb
3494           fill - expected fill as ratio of original fill.
3495           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3496                    Run with the option -info to determine an optimal value to use
3497 .ve
3498 
3499   Level: developer
3500 
3501   Notes:
3502   Most users should employ the `KSP` interface for linear solvers
3503   instead of working directly with matrix algebra routines such as this.
3504   See, e.g., `KSPCreate()`.
3505 
3506   This changes the state of the matrix to a factored matrix; it cannot be used
3507   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3508 
3509   Fortran Note:
3510   A valid (non-null) `info` argument must be provided
3511 
3512 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3513           `MatSetUnfactored()`
3514 @*/
3515 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3516 {
3517   PetscFunctionBegin;
3518   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3519   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3520   if (info) PetscAssertPointer(info, 3);
3521   PetscValidType(mat, 1);
3522   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3523   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3524   MatCheckPreallocated(mat, 1);
3525   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3526   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3527   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3528   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3529   PetscFunctionReturn(PETSC_SUCCESS);
3530 }
3531 
3532 /*@
3533   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3534   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3535 
3536   Collective
3537 
3538   Input Parameters:
3539 + fact - the factor matrix obtained with `MatGetFactor()`
3540 . mat  - the matrix
3541 . col  - column permutation
3542 - info - options for factorization, includes
3543 .vb
3544           fill - expected fill as ratio of original fill.
3545           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3546                    Run with the option -info to determine an optimal value to use
3547 .ve
3548 
3549   Level: developer
3550 
3551   Note:
3552   Most users should employ the `KSP` interface for linear solvers
3553   instead of working directly with matrix algebra routines such as this.
3554   See, e.g., `KSPCreate()`.
3555 
3556   Fortran Note:
3557   A valid (non-null) `info` argument must be provided
3558 
3559 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3560 @*/
3561 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3562 {
3563   MatFactorInfo tinfo;
3564 
3565   PetscFunctionBegin;
3566   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3567   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3568   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3569   if (info) PetscAssertPointer(info, 4);
3570   PetscValidType(fact, 1);
3571   PetscValidType(mat, 2);
3572   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3573   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3574   MatCheckPreallocated(mat, 2);
3575   if (!info) {
3576     PetscCall(MatFactorInfoInitialize(&tinfo));
3577     info = &tinfo;
3578   }
3579 
3580   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3581   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3582   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3583   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3584   PetscFunctionReturn(PETSC_SUCCESS);
3585 }
3586 
3587 /*@
3588   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3589   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3590 
3591   Collective
3592 
3593   Input Parameters:
3594 + fact - the factor matrix obtained with `MatGetFactor()`
3595 . mat  - the matrix
3596 - info - options for factorization
3597 
3598   Level: developer
3599 
3600   Notes:
3601   See `MatQRFactor()` for in-place factorization.
3602 
3603   Most users should employ the `KSP` interface for linear solvers
3604   instead of working directly with matrix algebra routines such as this.
3605   See, e.g., `KSPCreate()`.
3606 
3607   Fortran Note:
3608   A valid (non-null) `info` argument must be provided
3609 
3610 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3611 @*/
3612 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3613 {
3614   MatFactorInfo tinfo;
3615 
3616   PetscFunctionBegin;
3617   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3618   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3619   PetscValidType(fact, 1);
3620   PetscValidType(mat, 2);
3621   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3622   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,
3623              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3624 
3625   MatCheckPreallocated(mat, 2);
3626   if (!info) {
3627     PetscCall(MatFactorInfoInitialize(&tinfo));
3628     info = &tinfo;
3629   }
3630 
3631   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3632   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3633   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3634   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3635   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3636   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3637   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3638   PetscFunctionReturn(PETSC_SUCCESS);
3639 }
3640 
3641 /*@
3642   MatSolve - Solves $A x = b$, given a factored matrix.
3643 
3644   Neighbor-wise Collective
3645 
3646   Input Parameters:
3647 + mat - the factored matrix
3648 - b   - the right-hand-side vector
3649 
3650   Output Parameter:
3651 . x - the result vector
3652 
3653   Level: developer
3654 
3655   Notes:
3656   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3657   call `MatSolve`(A,x,x).
3658 
3659   Most users should employ the `KSP` interface for linear solvers
3660   instead of working directly with matrix algebra routines such as this.
3661   See, e.g., `KSPCreate()`.
3662 
3663 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3664 @*/
3665 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3666 {
3667   PetscFunctionBegin;
3668   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3669   PetscValidType(mat, 1);
3670   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3671   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3672   PetscCheckSameComm(mat, 1, b, 2);
3673   PetscCheckSameComm(mat, 1, x, 3);
3674   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3675   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);
3676   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);
3677   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);
3678   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3679   MatCheckPreallocated(mat, 1);
3680 
3681   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3682   PetscCall(VecFlag(x, mat->factorerrortype));
3683   if (mat->factorerrortype) {
3684     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3685   } else PetscUseTypeMethod(mat, solve, b, x);
3686   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3687   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3688   PetscFunctionReturn(PETSC_SUCCESS);
3689 }
3690 
3691 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3692 {
3693   Vec      b, x;
3694   PetscInt N, i;
3695   PetscErrorCode (*f)(Mat, Vec, Vec);
3696   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3697 
3698   PetscFunctionBegin;
3699   if (A->factorerrortype) {
3700     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3701     PetscCall(MatSetInf(X));
3702     PetscFunctionReturn(PETSC_SUCCESS);
3703   }
3704   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3705   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3706   PetscCall(MatBoundToCPU(A, &Abound));
3707   if (!Abound) {
3708     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3709     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3710   }
3711 #if PetscDefined(HAVE_CUDA)
3712   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3713   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3714 #elif PetscDefined(HAVE_HIP)
3715   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3716   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3717 #endif
3718   PetscCall(MatGetSize(B, NULL, &N));
3719   for (i = 0; i < N; i++) {
3720     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3721     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3722     PetscCall((*f)(A, b, x));
3723     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3724     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3725   }
3726   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3727   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3728   PetscFunctionReturn(PETSC_SUCCESS);
3729 }
3730 
3731 /*@
3732   MatMatSolve - Solves $A X = B$, given a factored matrix.
3733 
3734   Neighbor-wise Collective
3735 
3736   Input Parameters:
3737 + A - the factored matrix
3738 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3739 
3740   Output Parameter:
3741 . X - the result matrix (dense matrix)
3742 
3743   Level: developer
3744 
3745   Note:
3746   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3747   otherwise, `B` and `X` cannot be the same.
3748 
3749 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3750 @*/
3751 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3752 {
3753   PetscFunctionBegin;
3754   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3755   PetscValidType(A, 1);
3756   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3757   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3758   PetscCheckSameComm(A, 1, B, 2);
3759   PetscCheckSameComm(A, 1, X, 3);
3760   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);
3761   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);
3762   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");
3763   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3764   MatCheckPreallocated(A, 1);
3765 
3766   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3767   if (!A->ops->matsolve) {
3768     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3769     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3770   } else PetscUseTypeMethod(A, matsolve, B, X);
3771   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3772   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3773   PetscFunctionReturn(PETSC_SUCCESS);
3774 }
3775 
3776 /*@
3777   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3778 
3779   Neighbor-wise Collective
3780 
3781   Input Parameters:
3782 + A - the factored matrix
3783 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3784 
3785   Output Parameter:
3786 . X - the result matrix (dense matrix)
3787 
3788   Level: developer
3789 
3790   Note:
3791   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3792   call `MatMatSolveTranspose`(A,X,X).
3793 
3794 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3795 @*/
3796 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3797 {
3798   PetscFunctionBegin;
3799   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3800   PetscValidType(A, 1);
3801   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3802   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3803   PetscCheckSameComm(A, 1, B, 2);
3804   PetscCheckSameComm(A, 1, X, 3);
3805   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3806   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);
3807   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);
3808   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);
3809   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");
3810   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3811   MatCheckPreallocated(A, 1);
3812 
3813   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3814   if (!A->ops->matsolvetranspose) {
3815     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3816     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3817   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3818   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3819   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3820   PetscFunctionReturn(PETSC_SUCCESS);
3821 }
3822 
3823 /*@
3824   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3825 
3826   Neighbor-wise Collective
3827 
3828   Input Parameters:
3829 + A  - the factored matrix
3830 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3831 
3832   Output Parameter:
3833 . X - the result matrix (dense matrix)
3834 
3835   Level: developer
3836 
3837   Note:
3838   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
3839   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3840 
3841 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3842 @*/
3843 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3844 {
3845   PetscFunctionBegin;
3846   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3847   PetscValidType(A, 1);
3848   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3849   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3850   PetscCheckSameComm(A, 1, Bt, 2);
3851   PetscCheckSameComm(A, 1, X, 3);
3852 
3853   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3854   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);
3855   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);
3856   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");
3857   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3858   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3859   MatCheckPreallocated(A, 1);
3860 
3861   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3862   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3863   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3864   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3865   PetscFunctionReturn(PETSC_SUCCESS);
3866 }
3867 
3868 /*@
3869   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3870   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3871 
3872   Neighbor-wise Collective
3873 
3874   Input Parameters:
3875 + mat - the factored matrix
3876 - b   - the right-hand-side vector
3877 
3878   Output Parameter:
3879 . x - the result vector
3880 
3881   Level: developer
3882 
3883   Notes:
3884   `MatSolve()` should be used for most applications, as it performs
3885   a forward solve followed by a backward solve.
3886 
3887   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3888   call `MatForwardSolve`(A,x,x).
3889 
3890   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3891   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3892   `MatForwardSolve()` solves $U^T*D y = b$, and
3893   `MatBackwardSolve()` solves $U x = y$.
3894   Thus they do not provide a symmetric preconditioner.
3895 
3896 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3897 @*/
3898 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3899 {
3900   PetscFunctionBegin;
3901   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3902   PetscValidType(mat, 1);
3903   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3904   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3905   PetscCheckSameComm(mat, 1, b, 2);
3906   PetscCheckSameComm(mat, 1, x, 3);
3907   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3908   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);
3909   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);
3910   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);
3911   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3912   MatCheckPreallocated(mat, 1);
3913 
3914   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3915   PetscUseTypeMethod(mat, forwardsolve, b, x);
3916   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3917   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3918   PetscFunctionReturn(PETSC_SUCCESS);
3919 }
3920 
3921 /*@
3922   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3923   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3924 
3925   Neighbor-wise Collective
3926 
3927   Input Parameters:
3928 + mat - the factored matrix
3929 - b   - the right-hand-side vector
3930 
3931   Output Parameter:
3932 . x - the result vector
3933 
3934   Level: developer
3935 
3936   Notes:
3937   `MatSolve()` should be used for most applications, as it performs
3938   a forward solve followed by a backward solve.
3939 
3940   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3941   call `MatBackwardSolve`(A,x,x).
3942 
3943   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3944   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3945   `MatForwardSolve()` solves $U^T*D y = b$, and
3946   `MatBackwardSolve()` solves $U x = y$.
3947   Thus they do not provide a symmetric preconditioner.
3948 
3949 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3950 @*/
3951 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3952 {
3953   PetscFunctionBegin;
3954   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3955   PetscValidType(mat, 1);
3956   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3957   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3958   PetscCheckSameComm(mat, 1, b, 2);
3959   PetscCheckSameComm(mat, 1, x, 3);
3960   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3961   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);
3962   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);
3963   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);
3964   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3965   MatCheckPreallocated(mat, 1);
3966 
3967   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3968   PetscUseTypeMethod(mat, backwardsolve, b, x);
3969   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3970   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3971   PetscFunctionReturn(PETSC_SUCCESS);
3972 }
3973 
3974 /*@
3975   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3976 
3977   Neighbor-wise Collective
3978 
3979   Input Parameters:
3980 + mat - the factored matrix
3981 . b   - the right-hand-side vector
3982 - y   - the vector to be added to
3983 
3984   Output Parameter:
3985 . x - the result vector
3986 
3987   Level: developer
3988 
3989   Note:
3990   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3991   call `MatSolveAdd`(A,x,y,x).
3992 
3993 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3994 @*/
3995 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3996 {
3997   PetscScalar one = 1.0;
3998   Vec         tmp;
3999 
4000   PetscFunctionBegin;
4001   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4002   PetscValidType(mat, 1);
4003   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4004   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4005   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4006   PetscCheckSameComm(mat, 1, b, 2);
4007   PetscCheckSameComm(mat, 1, y, 3);
4008   PetscCheckSameComm(mat, 1, x, 4);
4009   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4010   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);
4011   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);
4012   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);
4013   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);
4014   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);
4015   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4016   MatCheckPreallocated(mat, 1);
4017 
4018   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4019   PetscCall(VecFlag(x, mat->factorerrortype));
4020   if (mat->factorerrortype) {
4021     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4022   } else if (mat->ops->solveadd) {
4023     PetscUseTypeMethod(mat, solveadd, b, y, x);
4024   } else {
4025     /* do the solve then the add manually */
4026     if (x != y) {
4027       PetscCall(MatSolve(mat, b, x));
4028       PetscCall(VecAXPY(x, one, y));
4029     } else {
4030       PetscCall(VecDuplicate(x, &tmp));
4031       PetscCall(VecCopy(x, tmp));
4032       PetscCall(MatSolve(mat, b, x));
4033       PetscCall(VecAXPY(x, one, tmp));
4034       PetscCall(VecDestroy(&tmp));
4035     }
4036   }
4037   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4038   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4039   PetscFunctionReturn(PETSC_SUCCESS);
4040 }
4041 
4042 /*@
4043   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4044 
4045   Neighbor-wise Collective
4046 
4047   Input Parameters:
4048 + mat - the factored matrix
4049 - b   - the right-hand-side vector
4050 
4051   Output Parameter:
4052 . x - the result vector
4053 
4054   Level: developer
4055 
4056   Notes:
4057   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4058   call `MatSolveTranspose`(A,x,x).
4059 
4060   Most users should employ the `KSP` interface for linear solvers
4061   instead of working directly with matrix algebra routines such as this.
4062   See, e.g., `KSPCreate()`.
4063 
4064 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4065 @*/
4066 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4067 {
4068   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4069 
4070   PetscFunctionBegin;
4071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4072   PetscValidType(mat, 1);
4073   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4074   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4075   PetscCheckSameComm(mat, 1, b, 2);
4076   PetscCheckSameComm(mat, 1, x, 3);
4077   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4078   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);
4079   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);
4080   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4081   MatCheckPreallocated(mat, 1);
4082   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4083   PetscCall(VecFlag(x, mat->factorerrortype));
4084   if (mat->factorerrortype) {
4085     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4086   } else {
4087     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4088     PetscCall((*f)(mat, b, x));
4089   }
4090   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4091   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4092   PetscFunctionReturn(PETSC_SUCCESS);
4093 }
4094 
4095 /*@
4096   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4097   factored matrix.
4098 
4099   Neighbor-wise Collective
4100 
4101   Input Parameters:
4102 + mat - the factored matrix
4103 . b   - the right-hand-side vector
4104 - y   - the vector to be added to
4105 
4106   Output Parameter:
4107 . x - the result vector
4108 
4109   Level: developer
4110 
4111   Note:
4112   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4113   call `MatSolveTransposeAdd`(A,x,y,x).
4114 
4115 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4116 @*/
4117 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4118 {
4119   PetscScalar one = 1.0;
4120   Vec         tmp;
4121   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4122 
4123   PetscFunctionBegin;
4124   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4125   PetscValidType(mat, 1);
4126   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4127   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4128   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4129   PetscCheckSameComm(mat, 1, b, 2);
4130   PetscCheckSameComm(mat, 1, y, 3);
4131   PetscCheckSameComm(mat, 1, x, 4);
4132   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4133   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);
4134   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);
4135   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);
4136   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);
4137   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4138   MatCheckPreallocated(mat, 1);
4139 
4140   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4141   PetscCall(VecFlag(x, mat->factorerrortype));
4142   if (mat->factorerrortype) {
4143     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4144   } else if (f) {
4145     PetscCall((*f)(mat, b, y, x));
4146   } else {
4147     /* do the solve then the add manually */
4148     if (x != y) {
4149       PetscCall(MatSolveTranspose(mat, b, x));
4150       PetscCall(VecAXPY(x, one, y));
4151     } else {
4152       PetscCall(VecDuplicate(x, &tmp));
4153       PetscCall(VecCopy(x, tmp));
4154       PetscCall(MatSolveTranspose(mat, b, x));
4155       PetscCall(VecAXPY(x, one, tmp));
4156       PetscCall(VecDestroy(&tmp));
4157     }
4158   }
4159   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4160   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4161   PetscFunctionReturn(PETSC_SUCCESS);
4162 }
4163 
4164 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4165 /*@
4166   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4167 
4168   Neighbor-wise Collective
4169 
4170   Input Parameters:
4171 + mat   - the matrix
4172 . b     - the right-hand side
4173 . omega - the relaxation factor
4174 . flag  - flag indicating the type of SOR (see below)
4175 . shift - diagonal shift
4176 . its   - the number of iterations
4177 - lits  - the number of local iterations
4178 
4179   Output Parameter:
4180 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4181 
4182   SOR Flags:
4183 +     `SOR_FORWARD_SWEEP` - forward SOR
4184 .     `SOR_BACKWARD_SWEEP` - backward SOR
4185 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4186 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4187 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4188 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4189 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4190 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4191   upper/lower triangular part of matrix to
4192   vector (with omega)
4193 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4194 
4195   Level: developer
4196 
4197   Notes:
4198   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4199   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4200   on each processor.
4201 
4202   Application programmers will not generally use `MatSOR()` directly,
4203   but instead will employ the `KSP`/`PC` interface.
4204 
4205   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4206 
4207   Most users should employ the `KSP` interface for linear solvers
4208   instead of working directly with matrix algebra routines such as this.
4209   See, e.g., `KSPCreate()`.
4210 
4211   Vectors `x` and `b` CANNOT be the same
4212 
4213   The flags are implemented as bitwise inclusive or operations.
4214   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4215   to specify a zero initial guess for SSOR.
4216 
4217   Developer Note:
4218   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4219 
4220 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4221 @*/
4222 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4223 {
4224   PetscFunctionBegin;
4225   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4226   PetscValidType(mat, 1);
4227   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4228   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4229   PetscCheckSameComm(mat, 1, b, 2);
4230   PetscCheckSameComm(mat, 1, x, 8);
4231   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4232   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4233   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);
4234   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);
4235   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);
4236   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4237   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4238   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4239 
4240   MatCheckPreallocated(mat, 1);
4241   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4242   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4243   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4244   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4245   PetscFunctionReturn(PETSC_SUCCESS);
4246 }
4247 
4248 /*
4249       Default matrix copy routine.
4250 */
4251 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4252 {
4253   PetscInt           i, rstart = 0, rend = 0, nz;
4254   const PetscInt    *cwork;
4255   const PetscScalar *vwork;
4256 
4257   PetscFunctionBegin;
4258   if (B->assembled) PetscCall(MatZeroEntries(B));
4259   if (str == SAME_NONZERO_PATTERN) {
4260     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4261     for (i = rstart; i < rend; i++) {
4262       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4263       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4264       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4265     }
4266   } else {
4267     PetscCall(MatAYPX(B, 0.0, A, str));
4268   }
4269   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4270   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4271   PetscFunctionReturn(PETSC_SUCCESS);
4272 }
4273 
4274 /*@
4275   MatCopy - Copies a matrix to another matrix.
4276 
4277   Collective
4278 
4279   Input Parameters:
4280 + A   - the matrix
4281 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4282 
4283   Output Parameter:
4284 . B - where the copy is put
4285 
4286   Level: intermediate
4287 
4288   Notes:
4289   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4290 
4291   `MatCopy()` copies the matrix entries of a matrix to another existing
4292   matrix (after first zeroing the second matrix).  A related routine is
4293   `MatConvert()`, which first creates a new matrix and then copies the data.
4294 
4295 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4296 @*/
4297 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4298 {
4299   PetscInt i;
4300 
4301   PetscFunctionBegin;
4302   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4303   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4304   PetscValidType(A, 1);
4305   PetscValidType(B, 2);
4306   PetscCheckSameComm(A, 1, B, 2);
4307   MatCheckPreallocated(B, 2);
4308   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4309   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4310   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,
4311              A->cmap->N, B->cmap->N);
4312   MatCheckPreallocated(A, 1);
4313   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4314 
4315   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4316   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4317   else PetscCall(MatCopy_Basic(A, B, str));
4318 
4319   B->stencil.dim = A->stencil.dim;
4320   B->stencil.noc = A->stencil.noc;
4321   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4322     B->stencil.dims[i]   = A->stencil.dims[i];
4323     B->stencil.starts[i] = A->stencil.starts[i];
4324   }
4325 
4326   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4327   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4328   PetscFunctionReturn(PETSC_SUCCESS);
4329 }
4330 
4331 /*@
4332   MatConvert - Converts a matrix to another matrix, either of the same
4333   or different type.
4334 
4335   Collective
4336 
4337   Input Parameters:
4338 + mat     - the matrix
4339 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4340             same type as the original matrix.
4341 - reuse   - denotes if the destination matrix is to be created or reused.
4342             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
4343             `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).
4344 
4345   Output Parameter:
4346 . M - pointer to place new matrix
4347 
4348   Level: intermediate
4349 
4350   Notes:
4351   `MatConvert()` first creates a new matrix and then copies the data from
4352   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4353   entries of one matrix to another already existing matrix context.
4354 
4355   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4356   the MPI communicator of the generated matrix is always the same as the communicator
4357   of the input matrix.
4358 
4359 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4360 @*/
4361 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4362 {
4363   PetscBool  sametype, issame, flg;
4364   PetscBool3 issymmetric, ishermitian;
4365   char       convname[256], mtype[256];
4366   Mat        B;
4367 
4368   PetscFunctionBegin;
4369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4370   PetscValidType(mat, 1);
4371   PetscAssertPointer(M, 4);
4372   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4373   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4374   MatCheckPreallocated(mat, 1);
4375 
4376   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4377   if (flg) newtype = mtype;
4378 
4379   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4380   PetscCall(PetscStrcmp(newtype, "same", &issame));
4381   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4382   if (reuse == MAT_REUSE_MATRIX) {
4383     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4384     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4385   }
4386 
4387   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4388     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4389     PetscFunctionReturn(PETSC_SUCCESS);
4390   }
4391 
4392   /* Cache Mat options because some converters use MatHeaderReplace  */
4393   issymmetric = mat->symmetric;
4394   ishermitian = mat->hermitian;
4395 
4396   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4397     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4398     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4399   } else {
4400     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4401     const char *prefix[3]                                 = {"seq", "mpi", ""};
4402     PetscInt    i;
4403     /*
4404        Order of precedence:
4405        0) See if newtype is a superclass of the current matrix.
4406        1) See if a specialized converter is known to the current matrix.
4407        2) See if a specialized converter is known to the desired matrix class.
4408        3) See if a good general converter is registered for the desired class
4409           (as of 6/27/03 only MATMPIADJ falls into this category).
4410        4) See if a good general converter is known for the current matrix.
4411        5) Use a really basic converter.
4412     */
4413 
4414     /* 0) See if newtype is a superclass of the current matrix.
4415           i.e mat is mpiaij and newtype is aij */
4416     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4417       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4418       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4419       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4420       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4421       if (flg) {
4422         if (reuse == MAT_INPLACE_MATRIX) {
4423           PetscCall(PetscInfo(mat, "Early return\n"));
4424           PetscFunctionReturn(PETSC_SUCCESS);
4425         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4426           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4427           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4428           PetscFunctionReturn(PETSC_SUCCESS);
4429         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4430           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4431           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4432           PetscFunctionReturn(PETSC_SUCCESS);
4433         }
4434       }
4435     }
4436     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4437     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4438       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4439       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4440       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4441       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4442       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4443       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4444       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4445       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4446       if (conv) goto foundconv;
4447     }
4448 
4449     /* 2)  See if a specialized converter is known to the desired matrix class. */
4450     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4451     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4452     PetscCall(MatSetType(B, newtype));
4453     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4454       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4455       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4456       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4457       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4458       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4459       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4460       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4461       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4462       if (conv) {
4463         PetscCall(MatDestroy(&B));
4464         goto foundconv;
4465       }
4466     }
4467 
4468     /* 3) See if a good general converter is registered for the desired class */
4469     conv = B->ops->convertfrom;
4470     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4471     PetscCall(MatDestroy(&B));
4472     if (conv) goto foundconv;
4473 
4474     /* 4) See if a good general converter is known for the current matrix */
4475     if (mat->ops->convert) conv = mat->ops->convert;
4476     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4477     if (conv) goto foundconv;
4478 
4479     /* 5) Use a really basic converter. */
4480     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4481     conv = MatConvert_Basic;
4482 
4483   foundconv:
4484     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4485     PetscCall((*conv)(mat, newtype, reuse, M));
4486     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4487       /* the block sizes must be same if the mappings are copied over */
4488       (*M)->rmap->bs = mat->rmap->bs;
4489       (*M)->cmap->bs = mat->cmap->bs;
4490       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4491       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4492       (*M)->rmap->mapping = mat->rmap->mapping;
4493       (*M)->cmap->mapping = mat->cmap->mapping;
4494     }
4495     (*M)->stencil.dim = mat->stencil.dim;
4496     (*M)->stencil.noc = mat->stencil.noc;
4497     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4498       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4499       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4500     }
4501     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4502   }
4503   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4504 
4505   /* Copy Mat options */
4506   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4507   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4508   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4509   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4510   PetscFunctionReturn(PETSC_SUCCESS);
4511 }
4512 
4513 /*@
4514   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4515 
4516   Not Collective
4517 
4518   Input Parameter:
4519 . mat - the matrix, must be a factored matrix
4520 
4521   Output Parameter:
4522 . type - the string name of the package (do not free this string)
4523 
4524   Level: intermediate
4525 
4526 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4527 @*/
4528 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4529 {
4530   PetscErrorCode (*conv)(Mat, MatSolverType *);
4531 
4532   PetscFunctionBegin;
4533   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4534   PetscValidType(mat, 1);
4535   PetscAssertPointer(type, 2);
4536   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4537   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4538   if (conv) PetscCall((*conv)(mat, type));
4539   else *type = MATSOLVERPETSC;
4540   PetscFunctionReturn(PETSC_SUCCESS);
4541 }
4542 
4543 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4544 struct _MatSolverTypeForSpecifcType {
4545   MatType mtype;
4546   /* no entry for MAT_FACTOR_NONE */
4547   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4548   MatSolverTypeForSpecifcType next;
4549 };
4550 
4551 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4552 struct _MatSolverTypeHolder {
4553   char                       *name;
4554   MatSolverTypeForSpecifcType handlers;
4555   MatSolverTypeHolder         next;
4556 };
4557 
4558 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4559 
4560 /*@C
4561   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4562 
4563   Logically Collective, No Fortran Support
4564 
4565   Input Parameters:
4566 + package      - name of the package, for example `petsc` or `superlu`
4567 . mtype        - the matrix type that works with this package
4568 . ftype        - the type of factorization supported by the package
4569 - createfactor - routine that will create the factored matrix ready to be used
4570 
4571   Level: developer
4572 
4573 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4574   `MatGetFactor()`
4575 @*/
4576 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4577 {
4578   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4579   PetscBool                   flg;
4580   MatSolverTypeForSpecifcType inext, iprev = NULL;
4581 
4582   PetscFunctionBegin;
4583   PetscCall(MatInitializePackage());
4584   if (!next) {
4585     PetscCall(PetscNew(&MatSolverTypeHolders));
4586     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4587     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4588     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4589     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4590     PetscFunctionReturn(PETSC_SUCCESS);
4591   }
4592   while (next) {
4593     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4594     if (flg) {
4595       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4596       inext = next->handlers;
4597       while (inext) {
4598         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4599         if (flg) {
4600           inext->createfactor[(int)ftype - 1] = createfactor;
4601           PetscFunctionReturn(PETSC_SUCCESS);
4602         }
4603         iprev = inext;
4604         inext = inext->next;
4605       }
4606       PetscCall(PetscNew(&iprev->next));
4607       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4608       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4609       PetscFunctionReturn(PETSC_SUCCESS);
4610     }
4611     prev = next;
4612     next = next->next;
4613   }
4614   PetscCall(PetscNew(&prev->next));
4615   PetscCall(PetscStrallocpy(package, &prev->next->name));
4616   PetscCall(PetscNew(&prev->next->handlers));
4617   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4618   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4619   PetscFunctionReturn(PETSC_SUCCESS);
4620 }
4621 
4622 /*@C
4623   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4624 
4625   Input Parameters:
4626 + 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
4627 . ftype - the type of factorization supported by the type
4628 - mtype - the matrix type that works with this type
4629 
4630   Output Parameters:
4631 + foundtype    - `PETSC_TRUE` if the type was registered
4632 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4633 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4634 
4635   Calling sequence of `createfactor`:
4636 + A     - the matrix providing the factor matrix
4637 . ftype - the `MatFactorType` of the factor requested
4638 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4639 
4640   Level: developer
4641 
4642   Note:
4643   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4644   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4645   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4646 
4647 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4648           `MatInitializePackage()`
4649 @*/
4650 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4651 {
4652   MatSolverTypeHolder         next = MatSolverTypeHolders;
4653   PetscBool                   flg;
4654   MatSolverTypeForSpecifcType inext;
4655 
4656   PetscFunctionBegin;
4657   if (foundtype) *foundtype = PETSC_FALSE;
4658   if (foundmtype) *foundmtype = PETSC_FALSE;
4659   if (createfactor) *createfactor = NULL;
4660 
4661   if (type) {
4662     while (next) {
4663       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4664       if (flg) {
4665         if (foundtype) *foundtype = PETSC_TRUE;
4666         inext = next->handlers;
4667         while (inext) {
4668           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4669           if (flg) {
4670             if (foundmtype) *foundmtype = PETSC_TRUE;
4671             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4672             PetscFunctionReturn(PETSC_SUCCESS);
4673           }
4674           inext = inext->next;
4675         }
4676       }
4677       next = next->next;
4678     }
4679   } else {
4680     while (next) {
4681       inext = next->handlers;
4682       while (inext) {
4683         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4684         if (flg && inext->createfactor[(int)ftype - 1]) {
4685           if (foundtype) *foundtype = PETSC_TRUE;
4686           if (foundmtype) *foundmtype = PETSC_TRUE;
4687           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4688           PetscFunctionReturn(PETSC_SUCCESS);
4689         }
4690         inext = inext->next;
4691       }
4692       next = next->next;
4693     }
4694     /* try with base classes inext->mtype */
4695     next = MatSolverTypeHolders;
4696     while (next) {
4697       inext = next->handlers;
4698       while (inext) {
4699         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4700         if (flg && inext->createfactor[(int)ftype - 1]) {
4701           if (foundtype) *foundtype = PETSC_TRUE;
4702           if (foundmtype) *foundmtype = PETSC_TRUE;
4703           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4704           PetscFunctionReturn(PETSC_SUCCESS);
4705         }
4706         inext = inext->next;
4707       }
4708       next = next->next;
4709     }
4710   }
4711   PetscFunctionReturn(PETSC_SUCCESS);
4712 }
4713 
4714 PetscErrorCode MatSolverTypeDestroy(void)
4715 {
4716   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4717   MatSolverTypeForSpecifcType inext, iprev;
4718 
4719   PetscFunctionBegin;
4720   while (next) {
4721     PetscCall(PetscFree(next->name));
4722     inext = next->handlers;
4723     while (inext) {
4724       PetscCall(PetscFree(inext->mtype));
4725       iprev = inext;
4726       inext = inext->next;
4727       PetscCall(PetscFree(iprev));
4728     }
4729     prev = next;
4730     next = next->next;
4731     PetscCall(PetscFree(prev));
4732   }
4733   MatSolverTypeHolders = NULL;
4734   PetscFunctionReturn(PETSC_SUCCESS);
4735 }
4736 
4737 /*@
4738   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4739 
4740   Logically Collective
4741 
4742   Input Parameter:
4743 . mat - the matrix
4744 
4745   Output Parameter:
4746 . flg - `PETSC_TRUE` if uses the ordering
4747 
4748   Level: developer
4749 
4750   Note:
4751   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4752   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4753 
4754 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4755 @*/
4756 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4757 {
4758   PetscFunctionBegin;
4759   *flg = mat->canuseordering;
4760   PetscFunctionReturn(PETSC_SUCCESS);
4761 }
4762 
4763 /*@
4764   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4765 
4766   Logically Collective
4767 
4768   Input Parameters:
4769 + mat   - the matrix obtained with `MatGetFactor()`
4770 - ftype - the factorization type to be used
4771 
4772   Output Parameter:
4773 . otype - the preferred ordering type
4774 
4775   Level: developer
4776 
4777 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4778 @*/
4779 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4780 {
4781   PetscFunctionBegin;
4782   *otype = mat->preferredordering[ftype];
4783   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4784   PetscFunctionReturn(PETSC_SUCCESS);
4785 }
4786 
4787 /*@
4788   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4789 
4790   Collective
4791 
4792   Input Parameters:
4793 + mat   - the matrix
4794 . 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
4795           the other criteria is returned
4796 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4797 
4798   Output Parameter:
4799 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4800 
4801   Options Database Keys:
4802 + -pc_factor_mat_solver_type <type>    - choose the type at run time. When using `KSP` solvers
4803 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device
4804 - -pc_factor_mat_solve_on_host <bool>  - do mat solve on host (with device matrices). Default is doing it on device
4805 
4806   Level: intermediate
4807 
4808   Notes:
4809   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4810   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4811 
4812   Users usually access the factorization solvers via `KSP`
4813 
4814   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4815   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
4816 
4817   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4818   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4819   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4820 
4821   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4822   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4823   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4824 
4825   Developer Note:
4826   This should actually be called `MatCreateFactor()` since it creates a new factor object
4827 
4828 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4829           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4830           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4831 @*/
4832 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4833 {
4834   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4835   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4836 
4837   PetscFunctionBegin;
4838   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4839   PetscValidType(mat, 1);
4840 
4841   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4842   MatCheckPreallocated(mat, 1);
4843 
4844   PetscCall(MatIsShell(mat, &shell));
4845   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4846   if (hasop) {
4847     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4848     PetscFunctionReturn(PETSC_SUCCESS);
4849   }
4850 
4851   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4852   if (!foundtype) {
4853     if (type) {
4854       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],
4855               ((PetscObject)mat)->type_name, type);
4856     } else {
4857       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);
4858     }
4859   }
4860   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4861   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);
4862 
4863   PetscCall((*conv)(mat, ftype, f));
4864   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4865   PetscFunctionReturn(PETSC_SUCCESS);
4866 }
4867 
4868 /*@
4869   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4870 
4871   Not Collective
4872 
4873   Input Parameters:
4874 + mat   - the matrix
4875 . type  - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default)
4876 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4877 
4878   Output Parameter:
4879 . flg - PETSC_TRUE if the factorization is available
4880 
4881   Level: intermediate
4882 
4883   Notes:
4884   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4885   such as pastix, superlu, mumps etc.
4886 
4887   PETSc must have been ./configure to use the external solver, using the option --download-package
4888 
4889   Developer Note:
4890   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4891 
4892 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4893           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4894 @*/
4895 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4896 {
4897   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4898 
4899   PetscFunctionBegin;
4900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4901   PetscAssertPointer(flg, 4);
4902 
4903   *flg = PETSC_FALSE;
4904   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4905 
4906   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4907   MatCheckPreallocated(mat, 1);
4908 
4909   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4910   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4911   PetscFunctionReturn(PETSC_SUCCESS);
4912 }
4913 
4914 /*@
4915   MatDuplicate - Duplicates a matrix including the non-zero structure.
4916 
4917   Collective
4918 
4919   Input Parameters:
4920 + mat - the matrix
4921 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4922         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4923 
4924   Output Parameter:
4925 . M - pointer to place new matrix
4926 
4927   Level: intermediate
4928 
4929   Notes:
4930   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4931 
4932   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4933 
4934   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.
4935 
4936   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4937   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4938   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4939 
4940 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4941 @*/
4942 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4943 {
4944   Mat         B;
4945   VecType     vtype;
4946   PetscInt    i;
4947   PetscObject dm, container_h, container_d;
4948   void (*viewf)(void);
4949 
4950   PetscFunctionBegin;
4951   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4952   PetscValidType(mat, 1);
4953   PetscAssertPointer(M, 3);
4954   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4955   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4956   MatCheckPreallocated(mat, 1);
4957 
4958   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4959   PetscUseTypeMethod(mat, duplicate, op, M);
4960   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4961   B = *M;
4962 
4963   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4964   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4965   PetscCall(MatGetVecType(mat, &vtype));
4966   PetscCall(MatSetVecType(B, vtype));
4967 
4968   B->stencil.dim = mat->stencil.dim;
4969   B->stencil.noc = mat->stencil.noc;
4970   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4971     B->stencil.dims[i]   = mat->stencil.dims[i];
4972     B->stencil.starts[i] = mat->stencil.starts[i];
4973   }
4974 
4975   B->nooffproczerorows = mat->nooffproczerorows;
4976   B->nooffprocentries  = mat->nooffprocentries;
4977 
4978   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4979   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4980   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4981   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4982   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4983   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4984   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
4985   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4986   PetscFunctionReturn(PETSC_SUCCESS);
4987 }
4988 
4989 /*@
4990   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4991 
4992   Logically Collective
4993 
4994   Input Parameter:
4995 . mat - the matrix
4996 
4997   Output Parameter:
4998 . v - the diagonal of the matrix
4999 
5000   Level: intermediate
5001 
5002   Note:
5003   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5004   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5005   is larger than `ndiag`, the values of the remaining entries are unspecified.
5006 
5007   Currently only correct in parallel for square matrices.
5008 
5009 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5010 @*/
5011 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5012 {
5013   PetscFunctionBegin;
5014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5015   PetscValidType(mat, 1);
5016   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5017   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5018   MatCheckPreallocated(mat, 1);
5019   if (PetscDefined(USE_DEBUG)) {
5020     PetscInt nv, row, col, ndiag;
5021 
5022     PetscCall(VecGetLocalSize(v, &nv));
5023     PetscCall(MatGetLocalSize(mat, &row, &col));
5024     ndiag = PetscMin(row, col);
5025     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);
5026   }
5027 
5028   PetscUseTypeMethod(mat, getdiagonal, v);
5029   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5030   PetscFunctionReturn(PETSC_SUCCESS);
5031 }
5032 
5033 /*@
5034   MatGetRowMin - Gets the minimum value (of the real part) of each
5035   row of the matrix
5036 
5037   Logically Collective
5038 
5039   Input Parameter:
5040 . mat - the matrix
5041 
5042   Output Parameters:
5043 + v   - the vector for storing the maximums
5044 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5045 
5046   Level: intermediate
5047 
5048   Note:
5049   The result of this call are the same as if one converted the matrix to dense format
5050   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5051 
5052   This code is only implemented for a couple of matrix formats.
5053 
5054 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5055           `MatGetRowMax()`
5056 @*/
5057 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5058 {
5059   PetscFunctionBegin;
5060   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5061   PetscValidType(mat, 1);
5062   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5063   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5064 
5065   if (!mat->cmap->N) {
5066     PetscCall(VecSet(v, PETSC_MAX_REAL));
5067     if (idx) {
5068       PetscInt i, m = mat->rmap->n;
5069       for (i = 0; i < m; i++) idx[i] = -1;
5070     }
5071   } else {
5072     MatCheckPreallocated(mat, 1);
5073   }
5074   PetscUseTypeMethod(mat, getrowmin, v, idx);
5075   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5076   PetscFunctionReturn(PETSC_SUCCESS);
5077 }
5078 
5079 /*@
5080   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5081   row of the matrix
5082 
5083   Logically Collective
5084 
5085   Input Parameter:
5086 . mat - the matrix
5087 
5088   Output Parameters:
5089 + v   - the vector for storing the minimums
5090 - idx - the indices of the column found for each row (or `NULL` if not needed)
5091 
5092   Level: intermediate
5093 
5094   Notes:
5095   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5096   row is 0 (the first column).
5097 
5098   This code is only implemented for a couple of matrix formats.
5099 
5100 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5101 @*/
5102 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5103 {
5104   PetscFunctionBegin;
5105   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5106   PetscValidType(mat, 1);
5107   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5108   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5109   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5110 
5111   if (!mat->cmap->N) {
5112     PetscCall(VecSet(v, 0.0));
5113     if (idx) {
5114       PetscInt i, m = mat->rmap->n;
5115       for (i = 0; i < m; i++) idx[i] = -1;
5116     }
5117   } else {
5118     MatCheckPreallocated(mat, 1);
5119     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5120     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5121   }
5122   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5123   PetscFunctionReturn(PETSC_SUCCESS);
5124 }
5125 
5126 /*@
5127   MatGetRowMax - Gets the maximum value (of the real part) of each
5128   row of the matrix
5129 
5130   Logically Collective
5131 
5132   Input Parameter:
5133 . mat - the matrix
5134 
5135   Output Parameters:
5136 + v   - the vector for storing the maximums
5137 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5138 
5139   Level: intermediate
5140 
5141   Notes:
5142   The result of this call are the same as if one converted the matrix to dense format
5143   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5144 
5145   This code is only implemented for a couple of matrix formats.
5146 
5147 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5148 @*/
5149 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5150 {
5151   PetscFunctionBegin;
5152   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5153   PetscValidType(mat, 1);
5154   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5155   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5156 
5157   if (!mat->cmap->N) {
5158     PetscCall(VecSet(v, PETSC_MIN_REAL));
5159     if (idx) {
5160       PetscInt i, m = mat->rmap->n;
5161       for (i = 0; i < m; i++) idx[i] = -1;
5162     }
5163   } else {
5164     MatCheckPreallocated(mat, 1);
5165     PetscUseTypeMethod(mat, getrowmax, v, idx);
5166   }
5167   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5168   PetscFunctionReturn(PETSC_SUCCESS);
5169 }
5170 
5171 /*@
5172   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5173   row of the matrix
5174 
5175   Logically Collective
5176 
5177   Input Parameter:
5178 . mat - the matrix
5179 
5180   Output Parameters:
5181 + v   - the vector for storing the maximums
5182 - idx - the indices of the column found for each row (or `NULL` if not needed)
5183 
5184   Level: intermediate
5185 
5186   Notes:
5187   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5188   row is 0 (the first column).
5189 
5190   This code is only implemented for a couple of matrix formats.
5191 
5192 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5193 @*/
5194 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5195 {
5196   PetscFunctionBegin;
5197   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5198   PetscValidType(mat, 1);
5199   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5200   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5201 
5202   if (!mat->cmap->N) {
5203     PetscCall(VecSet(v, 0.0));
5204     if (idx) {
5205       PetscInt i, m = mat->rmap->n;
5206       for (i = 0; i < m; i++) idx[i] = -1;
5207     }
5208   } else {
5209     MatCheckPreallocated(mat, 1);
5210     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5211     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5212   }
5213   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5214   PetscFunctionReturn(PETSC_SUCCESS);
5215 }
5216 
5217 /*@
5218   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5219 
5220   Logically Collective
5221 
5222   Input Parameter:
5223 . mat - the matrix
5224 
5225   Output Parameter:
5226 . v - the vector for storing the sum
5227 
5228   Level: intermediate
5229 
5230   This code is only implemented for a couple of matrix formats.
5231 
5232 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5233 @*/
5234 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5235 {
5236   PetscFunctionBegin;
5237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5238   PetscValidType(mat, 1);
5239   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5240   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5241 
5242   if (!mat->cmap->N) {
5243     PetscCall(VecSet(v, 0.0));
5244   } else {
5245     MatCheckPreallocated(mat, 1);
5246     PetscUseTypeMethod(mat, getrowsumabs, v);
5247   }
5248   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5249   PetscFunctionReturn(PETSC_SUCCESS);
5250 }
5251 
5252 /*@
5253   MatGetRowSum - Gets the sum of each row of the matrix
5254 
5255   Logically or Neighborhood Collective
5256 
5257   Input Parameter:
5258 . mat - the matrix
5259 
5260   Output Parameter:
5261 . v - the vector for storing the sum of rows
5262 
5263   Level: intermediate
5264 
5265   Note:
5266   This code is slow since it is not currently specialized for different formats
5267 
5268 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5269 @*/
5270 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5271 {
5272   Vec ones;
5273 
5274   PetscFunctionBegin;
5275   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5276   PetscValidType(mat, 1);
5277   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5278   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5279   MatCheckPreallocated(mat, 1);
5280   PetscCall(MatCreateVecs(mat, &ones, NULL));
5281   PetscCall(VecSet(ones, 1.));
5282   PetscCall(MatMult(mat, ones, v));
5283   PetscCall(VecDestroy(&ones));
5284   PetscFunctionReturn(PETSC_SUCCESS);
5285 }
5286 
5287 /*@
5288   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5289   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5290 
5291   Collective
5292 
5293   Input Parameter:
5294 . mat - the matrix to provide the transpose
5295 
5296   Output Parameter:
5297 . 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
5298 
5299   Level: advanced
5300 
5301   Note:
5302   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
5303   routine allows bypassing that call.
5304 
5305 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5306 @*/
5307 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5308 {
5309   MatParentState *rb = NULL;
5310 
5311   PetscFunctionBegin;
5312   PetscCall(PetscNew(&rb));
5313   rb->id    = ((PetscObject)mat)->id;
5314   rb->state = 0;
5315   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5316   PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault));
5317   PetscFunctionReturn(PETSC_SUCCESS);
5318 }
5319 
5320 /*@
5321   MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5322 
5323   Collective
5324 
5325   Input Parameters:
5326 + mat   - the matrix to transpose
5327 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5328 
5329   Output Parameter:
5330 . B - the transpose of the matrix
5331 
5332   Level: intermediate
5333 
5334   Notes:
5335   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5336 
5337   `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
5338   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5339 
5340   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.
5341 
5342   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5343   For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5344 
5345   If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5346 
5347   If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5348 
5349 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5350           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5351 @*/
5352 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5353 {
5354   PetscContainer  rB = NULL;
5355   MatParentState *rb = NULL;
5356 
5357   PetscFunctionBegin;
5358   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5359   PetscValidType(mat, 1);
5360   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5361   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5362   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5363   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5364   MatCheckPreallocated(mat, 1);
5365   if (reuse == MAT_REUSE_MATRIX) {
5366     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5367     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5368     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5369     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5370     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5371   }
5372 
5373   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5374   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5375     PetscUseTypeMethod(mat, transpose, reuse, B);
5376     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5377   }
5378   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5379 
5380   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5381   if (reuse != MAT_INPLACE_MATRIX) {
5382     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5383     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5384     rb->state        = ((PetscObject)mat)->state;
5385     rb->nonzerostate = mat->nonzerostate;
5386   }
5387   PetscFunctionReturn(PETSC_SUCCESS);
5388 }
5389 
5390 /*@
5391   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5392 
5393   Collective
5394 
5395   Input Parameter:
5396 . A - the matrix to transpose
5397 
5398   Output Parameter:
5399 . 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
5400       numerical portion.
5401 
5402   Level: intermediate
5403 
5404   Note:
5405   This is not supported for many matrix types, use `MatTranspose()` in those cases
5406 
5407 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5408 @*/
5409 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5410 {
5411   PetscFunctionBegin;
5412   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5413   PetscValidType(A, 1);
5414   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5415   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5416   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5417   PetscUseTypeMethod(A, transposesymbolic, B);
5418   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5419 
5420   PetscCall(MatTransposeSetPrecursor(A, *B));
5421   PetscFunctionReturn(PETSC_SUCCESS);
5422 }
5423 
5424 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5425 {
5426   PetscContainer  rB;
5427   MatParentState *rb;
5428 
5429   PetscFunctionBegin;
5430   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5431   PetscValidType(A, 1);
5432   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5433   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5434   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5435   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5436   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5437   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5438   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5439   PetscFunctionReturn(PETSC_SUCCESS);
5440 }
5441 
5442 /*@
5443   MatIsTranspose - Test whether a matrix is another one's transpose,
5444   or its own, in which case it tests symmetry.
5445 
5446   Collective
5447 
5448   Input Parameters:
5449 + A   - the matrix to test
5450 . B   - the matrix to test against, this can equal the first parameter
5451 - tol - tolerance, differences between entries smaller than this are counted as zero
5452 
5453   Output Parameter:
5454 . flg - the result
5455 
5456   Level: intermediate
5457 
5458   Notes:
5459   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5460   test involves parallel copies of the block off-diagonal parts of the matrix.
5461 
5462 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5463 @*/
5464 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5465 {
5466   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5467 
5468   PetscFunctionBegin;
5469   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5470   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5471   PetscAssertPointer(flg, 4);
5472   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5473   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5474   *flg = PETSC_FALSE;
5475   if (f && g) {
5476     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5477     PetscCall((*f)(A, B, tol, flg));
5478   } else {
5479     MatType mattype;
5480 
5481     PetscCall(MatGetType(f ? B : A, &mattype));
5482     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5483   }
5484   PetscFunctionReturn(PETSC_SUCCESS);
5485 }
5486 
5487 /*@
5488   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5489 
5490   Collective
5491 
5492   Input Parameters:
5493 + mat   - the matrix to transpose and complex conjugate
5494 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5495 
5496   Output Parameter:
5497 . B - the Hermitian transpose
5498 
5499   Level: intermediate
5500 
5501 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5502 @*/
5503 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5504 {
5505   PetscFunctionBegin;
5506   PetscCall(MatTranspose(mat, reuse, B));
5507 #if defined(PETSC_USE_COMPLEX)
5508   PetscCall(MatConjugate(*B));
5509 #endif
5510   PetscFunctionReturn(PETSC_SUCCESS);
5511 }
5512 
5513 /*@
5514   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5515 
5516   Collective
5517 
5518   Input Parameters:
5519 + A   - the matrix to test
5520 . B   - the matrix to test against, this can equal the first parameter
5521 - tol - tolerance, differences between entries smaller than this are counted as zero
5522 
5523   Output Parameter:
5524 . flg - the result
5525 
5526   Level: intermediate
5527 
5528   Notes:
5529   Only available for `MATAIJ` matrices.
5530 
5531   The sequential algorithm
5532   has a running time of the order of the number of nonzeros; the parallel
5533   test involves parallel copies of the block off-diagonal parts of the matrix.
5534 
5535 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5536 @*/
5537 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5538 {
5539   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5540 
5541   PetscFunctionBegin;
5542   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5543   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5544   PetscAssertPointer(flg, 4);
5545   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5546   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5547   if (f && g) {
5548     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5549     PetscCall((*f)(A, B, tol, flg));
5550   }
5551   PetscFunctionReturn(PETSC_SUCCESS);
5552 }
5553 
5554 /*@
5555   MatPermute - Creates a new matrix with rows and columns permuted from the
5556   original.
5557 
5558   Collective
5559 
5560   Input Parameters:
5561 + mat - the matrix to permute
5562 . row - row permutation, each processor supplies only the permutation for its rows
5563 - col - column permutation, each processor supplies only the permutation for its columns
5564 
5565   Output Parameter:
5566 . B - the permuted matrix
5567 
5568   Level: advanced
5569 
5570   Note:
5571   The index sets map from row/col of permuted matrix to row/col of original matrix.
5572   The index sets should be on the same communicator as mat and have the same local sizes.
5573 
5574   Developer Note:
5575   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5576   exploit the fact that row and col are permutations, consider implementing the
5577   more general `MatCreateSubMatrix()` instead.
5578 
5579 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5580 @*/
5581 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5582 {
5583   PetscFunctionBegin;
5584   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5585   PetscValidType(mat, 1);
5586   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5587   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5588   PetscAssertPointer(B, 4);
5589   PetscCheckSameComm(mat, 1, row, 2);
5590   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5591   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5592   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5593   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5594   MatCheckPreallocated(mat, 1);
5595 
5596   if (mat->ops->permute) {
5597     PetscUseTypeMethod(mat, permute, row, col, B);
5598     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5599   } else {
5600     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5601   }
5602   PetscFunctionReturn(PETSC_SUCCESS);
5603 }
5604 
5605 /*@
5606   MatEqual - Compares two matrices.
5607 
5608   Collective
5609 
5610   Input Parameters:
5611 + A - the first matrix
5612 - B - the second matrix
5613 
5614   Output Parameter:
5615 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5616 
5617   Level: intermediate
5618 
5619   Note:
5620   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
5621   using several randomly created vectors, see `MatMultEqual()`.
5622 
5623 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()`
5624 @*/
5625 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5626 {
5627   PetscFunctionBegin;
5628   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5629   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5630   PetscValidType(A, 1);
5631   PetscValidType(B, 2);
5632   PetscAssertPointer(flg, 3);
5633   PetscCheckSameComm(A, 1, B, 2);
5634   MatCheckPreallocated(A, 1);
5635   MatCheckPreallocated(B, 2);
5636   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5637   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5638   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,
5639              B->cmap->N);
5640   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5641     PetscUseTypeMethod(A, equal, B, flg);
5642   } else {
5643     PetscCall(MatMultEqual(A, B, 10, flg));
5644   }
5645   PetscFunctionReturn(PETSC_SUCCESS);
5646 }
5647 
5648 /*@
5649   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5650   matrices that are stored as vectors.  Either of the two scaling
5651   matrices can be `NULL`.
5652 
5653   Collective
5654 
5655   Input Parameters:
5656 + mat - the matrix to be scaled
5657 . l   - the left scaling vector (or `NULL`)
5658 - r   - the right scaling vector (or `NULL`)
5659 
5660   Level: intermediate
5661 
5662   Note:
5663   `MatDiagonalScale()` computes $A = LAR$, where
5664   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5665   The L scales the rows of the matrix, the R scales the columns of the matrix.
5666 
5667 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5668 @*/
5669 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5670 {
5671   PetscFunctionBegin;
5672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5673   PetscValidType(mat, 1);
5674   if (l) {
5675     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5676     PetscCheckSameComm(mat, 1, l, 2);
5677   }
5678   if (r) {
5679     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5680     PetscCheckSameComm(mat, 1, r, 3);
5681   }
5682   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5683   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5684   MatCheckPreallocated(mat, 1);
5685   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5686 
5687   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5688   PetscUseTypeMethod(mat, diagonalscale, l, r);
5689   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5690   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5691   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5692   PetscFunctionReturn(PETSC_SUCCESS);
5693 }
5694 
5695 /*@
5696   MatScale - Scales all elements of a matrix by a given number.
5697 
5698   Logically Collective
5699 
5700   Input Parameters:
5701 + mat - the matrix to be scaled
5702 - a   - the scaling value
5703 
5704   Level: intermediate
5705 
5706 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5707 @*/
5708 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5709 {
5710   PetscFunctionBegin;
5711   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5712   PetscValidType(mat, 1);
5713   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5714   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5715   PetscValidLogicalCollectiveScalar(mat, a, 2);
5716   MatCheckPreallocated(mat, 1);
5717 
5718   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5719   if (a != (PetscScalar)1.0) {
5720     PetscUseTypeMethod(mat, scale, a);
5721     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5722   }
5723   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5724   PetscFunctionReturn(PETSC_SUCCESS);
5725 }
5726 
5727 /*@
5728   MatNorm - Calculates various norms of a matrix.
5729 
5730   Collective
5731 
5732   Input Parameters:
5733 + mat  - the matrix
5734 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5735 
5736   Output Parameter:
5737 . nrm - the resulting norm
5738 
5739   Level: intermediate
5740 
5741 .seealso: [](ch_matrices), `Mat`
5742 @*/
5743 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5744 {
5745   PetscFunctionBegin;
5746   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5747   PetscValidType(mat, 1);
5748   PetscAssertPointer(nrm, 3);
5749 
5750   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5751   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5752   MatCheckPreallocated(mat, 1);
5753 
5754   PetscUseTypeMethod(mat, norm, type, nrm);
5755   PetscFunctionReturn(PETSC_SUCCESS);
5756 }
5757 
5758 /*
5759      This variable is used to prevent counting of MatAssemblyBegin() that
5760    are called from within a MatAssemblyEnd().
5761 */
5762 static PetscInt MatAssemblyEnd_InUse = 0;
5763 /*@
5764   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5765   be called after completing all calls to `MatSetValues()`.
5766 
5767   Collective
5768 
5769   Input Parameters:
5770 + mat  - the matrix
5771 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5772 
5773   Level: beginner
5774 
5775   Notes:
5776   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5777   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5778 
5779   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5780   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5781   using the matrix.
5782 
5783   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5784   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
5785   a global collective operation requiring all processes that share the matrix.
5786 
5787   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5788   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5789   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5790 
5791 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5792 @*/
5793 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5794 {
5795   PetscFunctionBegin;
5796   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5797   PetscValidType(mat, 1);
5798   MatCheckPreallocated(mat, 1);
5799   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5800   if (mat->assembled) {
5801     mat->was_assembled = PETSC_TRUE;
5802     mat->assembled     = PETSC_FALSE;
5803   }
5804 
5805   if (!MatAssemblyEnd_InUse) {
5806     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5807     PetscTryTypeMethod(mat, assemblybegin, type);
5808     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5809   } else PetscTryTypeMethod(mat, assemblybegin, type);
5810   PetscFunctionReturn(PETSC_SUCCESS);
5811 }
5812 
5813 /*@
5814   MatAssembled - Indicates if a matrix has been assembled and is ready for
5815   use; for example, in matrix-vector product.
5816 
5817   Not Collective
5818 
5819   Input Parameter:
5820 . mat - the matrix
5821 
5822   Output Parameter:
5823 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5824 
5825   Level: advanced
5826 
5827 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5828 @*/
5829 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5830 {
5831   PetscFunctionBegin;
5832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5833   PetscAssertPointer(assembled, 2);
5834   *assembled = mat->assembled;
5835   PetscFunctionReturn(PETSC_SUCCESS);
5836 }
5837 
5838 /*@
5839   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5840   be called after `MatAssemblyBegin()`.
5841 
5842   Collective
5843 
5844   Input Parameters:
5845 + mat  - the matrix
5846 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5847 
5848   Options Database Keys:
5849 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5850 . -mat_view ::ascii_info_detail      - Prints more detailed info
5851 . -mat_view                          - Prints matrix in ASCII format
5852 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5853 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5854 . -display <name>                    - Sets display name (default is host)
5855 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5856 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5857 . -viewer_socket_machine <machine>   - Machine to use for socket
5858 . -viewer_socket_port <port>         - Port number to use for socket
5859 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5860 
5861   Level: beginner
5862 
5863 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5864 @*/
5865 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5866 {
5867   static PetscInt inassm = 0;
5868   PetscBool       flg    = PETSC_FALSE;
5869 
5870   PetscFunctionBegin;
5871   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5872   PetscValidType(mat, 1);
5873 
5874   inassm++;
5875   MatAssemblyEnd_InUse++;
5876   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5877     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5878     PetscTryTypeMethod(mat, assemblyend, type);
5879     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5880   } else PetscTryTypeMethod(mat, assemblyend, type);
5881 
5882   /* Flush assembly is not a true assembly */
5883   if (type != MAT_FLUSH_ASSEMBLY) {
5884     if (mat->num_ass) {
5885       if (!mat->symmetry_eternal) {
5886         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5887         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5888       }
5889       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5890       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5891     }
5892     mat->num_ass++;
5893     mat->assembled        = PETSC_TRUE;
5894     mat->ass_nonzerostate = mat->nonzerostate;
5895   }
5896 
5897   mat->insertmode = NOT_SET_VALUES;
5898   MatAssemblyEnd_InUse--;
5899   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5900   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5901     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5902 
5903     if (mat->checksymmetryonassembly) {
5904       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5905       if (flg) {
5906         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5907       } else {
5908         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5909       }
5910     }
5911     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5912   }
5913   inassm--;
5914   PetscFunctionReturn(PETSC_SUCCESS);
5915 }
5916 
5917 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5918 /*@
5919   MatSetOption - Sets a parameter option for a matrix. Some options
5920   may be specific to certain storage formats.  Some options
5921   determine how values will be inserted (or added). Sorted,
5922   row-oriented input will generally assemble the fastest. The default
5923   is row-oriented.
5924 
5925   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5926 
5927   Input Parameters:
5928 + mat - the matrix
5929 . op  - the option, one of those listed below (and possibly others),
5930 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5931 
5932   Options Describing Matrix Structure:
5933 + `MAT_SPD`                         - symmetric positive definite
5934 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5935 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5936 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5937 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5938 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5939 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5940 
5941    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5942    do not need to be computed (usually at a high cost)
5943 
5944    Options For Use with `MatSetValues()`:
5945    Insert a logically dense subblock, which can be
5946 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5947 
5948    These options reflect the data you pass in with `MatSetValues()`; it has
5949    nothing to do with how the data is stored internally in the matrix
5950    data structure.
5951 
5952    When (re)assembling a matrix, we can restrict the input for
5953    efficiency/debugging purposes.  These options include
5954 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5955 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5956 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5957 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5958 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5959 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5960         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5961         performance for very large process counts.
5962 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5963         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5964         functions, instead sending only neighbor messages.
5965 
5966   Level: intermediate
5967 
5968   Notes:
5969   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5970 
5971   Some options are relevant only for particular matrix types and
5972   are thus ignored by others.  Other options are not supported by
5973   certain matrix types and will generate an error message if set.
5974 
5975   If using Fortran to compute a matrix, one may need to
5976   use the column-oriented option (or convert to the row-oriented
5977   format).
5978 
5979   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5980   that would generate a new entry in the nonzero structure is instead
5981   ignored.  Thus, if memory has not already been allocated for this particular
5982   data, then the insertion is ignored. For dense matrices, in which
5983   the entire array is allocated, no entries are ever ignored.
5984   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5985 
5986   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5987   that would generate a new entry in the nonzero structure instead produces
5988   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
5989 
5990   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5991   that would generate a new entry that has not been preallocated will
5992   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5993   only.) This is a useful flag when debugging matrix memory preallocation.
5994   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5995 
5996   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5997   other processors should be dropped, rather than stashed.
5998   This is useful if you know that the "owning" processor is also
5999   always generating the correct matrix entries, so that PETSc need
6000   not transfer duplicate entries generated on another processor.
6001 
6002   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6003   searches during matrix assembly. When this flag is set, the hash table
6004   is created during the first matrix assembly. This hash table is
6005   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6006   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6007   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6008   supported by `MATMPIBAIJ` format only.
6009 
6010   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6011   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6012 
6013   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6014   a zero location in the matrix
6015 
6016   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6017 
6018   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6019   zero row routines and thus improves performance for very large process counts.
6020 
6021   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6022   part of the matrix (since they should match the upper triangular part).
6023 
6024   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6025   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6026   with finite difference schemes with non-periodic boundary conditions.
6027 
6028   Developer Note:
6029   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6030   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6031   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6032   not changed.
6033 
6034 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6035 @*/
6036 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6037 {
6038   PetscFunctionBegin;
6039   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6040   if (op > 0) {
6041     PetscValidLogicalCollectiveEnum(mat, op, 2);
6042     PetscValidLogicalCollectiveBool(mat, flg, 3);
6043   }
6044 
6045   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);
6046 
6047   switch (op) {
6048   case MAT_FORCE_DIAGONAL_ENTRIES:
6049     mat->force_diagonals = flg;
6050     PetscFunctionReturn(PETSC_SUCCESS);
6051   case MAT_NO_OFF_PROC_ENTRIES:
6052     mat->nooffprocentries = flg;
6053     PetscFunctionReturn(PETSC_SUCCESS);
6054   case MAT_SUBSET_OFF_PROC_ENTRIES:
6055     mat->assembly_subset = flg;
6056     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6057 #if !defined(PETSC_HAVE_MPIUNI)
6058       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6059 #endif
6060       mat->stash.first_assembly_done = PETSC_FALSE;
6061     }
6062     PetscFunctionReturn(PETSC_SUCCESS);
6063   case MAT_NO_OFF_PROC_ZERO_ROWS:
6064     mat->nooffproczerorows = flg;
6065     PetscFunctionReturn(PETSC_SUCCESS);
6066   case MAT_SPD:
6067     if (flg) {
6068       mat->spd                    = PETSC_BOOL3_TRUE;
6069       mat->symmetric              = PETSC_BOOL3_TRUE;
6070       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6071     } else {
6072       mat->spd = PETSC_BOOL3_FALSE;
6073     }
6074     break;
6075   case MAT_SYMMETRIC:
6076     mat->symmetric = PetscBoolToBool3(flg);
6077     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6078 #if !defined(PETSC_USE_COMPLEX)
6079     mat->hermitian = PetscBoolToBool3(flg);
6080 #endif
6081     break;
6082   case MAT_HERMITIAN:
6083     mat->hermitian = PetscBoolToBool3(flg);
6084     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6085 #if !defined(PETSC_USE_COMPLEX)
6086     mat->symmetric = PetscBoolToBool3(flg);
6087 #endif
6088     break;
6089   case MAT_STRUCTURALLY_SYMMETRIC:
6090     mat->structurally_symmetric = PetscBoolToBool3(flg);
6091     break;
6092   case MAT_SYMMETRY_ETERNAL:
6093     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");
6094     mat->symmetry_eternal = flg;
6095     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6096     break;
6097   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6098     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");
6099     mat->structural_symmetry_eternal = flg;
6100     break;
6101   case MAT_SPD_ETERNAL:
6102     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");
6103     mat->spd_eternal = flg;
6104     if (flg) {
6105       mat->structural_symmetry_eternal = PETSC_TRUE;
6106       mat->symmetry_eternal            = PETSC_TRUE;
6107     }
6108     break;
6109   case MAT_STRUCTURE_ONLY:
6110     mat->structure_only = flg;
6111     break;
6112   case MAT_SORTED_FULL:
6113     mat->sortedfull = flg;
6114     break;
6115   default:
6116     break;
6117   }
6118   PetscTryTypeMethod(mat, setoption, op, flg);
6119   PetscFunctionReturn(PETSC_SUCCESS);
6120 }
6121 
6122 /*@
6123   MatGetOption - Gets a parameter option that has been set for a matrix.
6124 
6125   Logically Collective
6126 
6127   Input Parameters:
6128 + mat - the matrix
6129 - op  - the option, this only responds to certain options, check the code for which ones
6130 
6131   Output Parameter:
6132 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6133 
6134   Level: intermediate
6135 
6136   Notes:
6137   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6138 
6139   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6140   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6141 
6142 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6143     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6144 @*/
6145 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6146 {
6147   PetscFunctionBegin;
6148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6149   PetscValidType(mat, 1);
6150 
6151   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);
6152   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()");
6153 
6154   switch (op) {
6155   case MAT_NO_OFF_PROC_ENTRIES:
6156     *flg = mat->nooffprocentries;
6157     break;
6158   case MAT_NO_OFF_PROC_ZERO_ROWS:
6159     *flg = mat->nooffproczerorows;
6160     break;
6161   case MAT_SYMMETRIC:
6162     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6163     break;
6164   case MAT_HERMITIAN:
6165     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6166     break;
6167   case MAT_STRUCTURALLY_SYMMETRIC:
6168     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6169     break;
6170   case MAT_SPD:
6171     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6172     break;
6173   case MAT_SYMMETRY_ETERNAL:
6174     *flg = mat->symmetry_eternal;
6175     break;
6176   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6177     *flg = mat->symmetry_eternal;
6178     break;
6179   default:
6180     break;
6181   }
6182   PetscFunctionReturn(PETSC_SUCCESS);
6183 }
6184 
6185 /*@
6186   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6187   this routine retains the old nonzero structure.
6188 
6189   Logically Collective
6190 
6191   Input Parameter:
6192 . mat - the matrix
6193 
6194   Level: intermediate
6195 
6196   Note:
6197   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.
6198   See the Performance chapter of the users manual for information on preallocating matrices.
6199 
6200 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6201 @*/
6202 PetscErrorCode MatZeroEntries(Mat mat)
6203 {
6204   PetscFunctionBegin;
6205   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6206   PetscValidType(mat, 1);
6207   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6208   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");
6209   MatCheckPreallocated(mat, 1);
6210 
6211   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6212   PetscUseTypeMethod(mat, zeroentries);
6213   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6214   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6215   PetscFunctionReturn(PETSC_SUCCESS);
6216 }
6217 
6218 /*@
6219   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6220   of a set of rows and columns of a matrix.
6221 
6222   Collective
6223 
6224   Input Parameters:
6225 + mat     - the matrix
6226 . numRows - the number of rows/columns to zero
6227 . rows    - the global row indices
6228 . diag    - value put in the diagonal of the eliminated rows
6229 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6230 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6231 
6232   Level: intermediate
6233 
6234   Notes:
6235   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6236 
6237   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6238   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
6239 
6240   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6241   Krylov method to take advantage of the known solution on the zeroed rows.
6242 
6243   For the parallel case, all processes that share the matrix (i.e.,
6244   those in the communicator used for matrix creation) MUST call this
6245   routine, regardless of whether any rows being zeroed are owned by
6246   them.
6247 
6248   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6249   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
6250   missing.
6251 
6252   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6253   list only rows local to itself).
6254 
6255   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6256 
6257 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6258           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6259 @*/
6260 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6261 {
6262   PetscFunctionBegin;
6263   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6264   PetscValidType(mat, 1);
6265   if (numRows) PetscAssertPointer(rows, 3);
6266   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6268   MatCheckPreallocated(mat, 1);
6269 
6270   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6271   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6272   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6273   PetscFunctionReturn(PETSC_SUCCESS);
6274 }
6275 
6276 /*@
6277   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6278   of a set of rows and columns of a matrix.
6279 
6280   Collective
6281 
6282   Input Parameters:
6283 + mat  - the matrix
6284 . is   - the rows to zero
6285 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6286 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6287 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6288 
6289   Level: intermediate
6290 
6291   Note:
6292   See `MatZeroRowsColumns()` for details on how this routine operates.
6293 
6294 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6295           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6296 @*/
6297 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6298 {
6299   PetscInt        numRows;
6300   const PetscInt *rows;
6301 
6302   PetscFunctionBegin;
6303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6304   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6305   PetscValidType(mat, 1);
6306   PetscValidType(is, 2);
6307   PetscCall(ISGetLocalSize(is, &numRows));
6308   PetscCall(ISGetIndices(is, &rows));
6309   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6310   PetscCall(ISRestoreIndices(is, &rows));
6311   PetscFunctionReturn(PETSC_SUCCESS);
6312 }
6313 
6314 /*@
6315   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6316   of a set of rows of a matrix.
6317 
6318   Collective
6319 
6320   Input Parameters:
6321 + mat     - the matrix
6322 . numRows - the number of rows to zero
6323 . rows    - the global row indices
6324 . diag    - value put in the diagonal of the zeroed rows
6325 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6326 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6327 
6328   Level: intermediate
6329 
6330   Notes:
6331   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6332 
6333   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6334 
6335   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6336   Krylov method to take advantage of the known solution on the zeroed rows.
6337 
6338   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)
6339   from the matrix.
6340 
6341   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6342   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6343   formats this does not alter the nonzero structure.
6344 
6345   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6346   of the matrix is not changed the values are
6347   merely zeroed.
6348 
6349   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6350   formats can optionally remove the main diagonal entry from the
6351   nonzero structure as well, by passing 0.0 as the final argument).
6352 
6353   For the parallel case, all processes that share the matrix (i.e.,
6354   those in the communicator used for matrix creation) MUST call this
6355   routine, regardless of whether any rows being zeroed are owned by
6356   them.
6357 
6358   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6359   list only rows local to itself).
6360 
6361   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6362   owns that are to be zeroed. This saves a global synchronization in the implementation.
6363 
6364 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6365           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6366 @*/
6367 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6368 {
6369   PetscFunctionBegin;
6370   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6371   PetscValidType(mat, 1);
6372   if (numRows) PetscAssertPointer(rows, 3);
6373   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6374   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6375   MatCheckPreallocated(mat, 1);
6376 
6377   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6378   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6379   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6380   PetscFunctionReturn(PETSC_SUCCESS);
6381 }
6382 
6383 /*@
6384   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6385   of a set of rows of a matrix indicated by an `IS`
6386 
6387   Collective
6388 
6389   Input Parameters:
6390 + mat  - the matrix
6391 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6392 . diag - value put in all diagonals of eliminated rows
6393 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6394 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6395 
6396   Level: intermediate
6397 
6398   Note:
6399   See `MatZeroRows()` for details on how this routine operates.
6400 
6401 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6402           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6403 @*/
6404 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6405 {
6406   PetscInt        numRows = 0;
6407   const PetscInt *rows    = NULL;
6408 
6409   PetscFunctionBegin;
6410   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6411   PetscValidType(mat, 1);
6412   if (is) {
6413     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6414     PetscCall(ISGetLocalSize(is, &numRows));
6415     PetscCall(ISGetIndices(is, &rows));
6416   }
6417   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6418   if (is) PetscCall(ISRestoreIndices(is, &rows));
6419   PetscFunctionReturn(PETSC_SUCCESS);
6420 }
6421 
6422 /*@
6423   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6424   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6425 
6426   Collective
6427 
6428   Input Parameters:
6429 + mat     - the matrix
6430 . numRows - the number of rows to remove
6431 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6432 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6433 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6434 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6435 
6436   Level: intermediate
6437 
6438   Notes:
6439   See `MatZeroRows()` for details on how this routine operates.
6440 
6441   The grid coordinates are across the entire grid, not just the local portion
6442 
6443   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6444   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6445   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6446   `DM_BOUNDARY_PERIODIC` boundary type.
6447 
6448   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
6449   a single value per point) you can skip filling those indices.
6450 
6451   Fortran Note:
6452   `idxm` and `idxn` should be declared as
6453 .vb
6454     MatStencil idxm(4, m)
6455 .ve
6456   and the values inserted using
6457 .vb
6458     idxm(MatStencil_i, 1) = i
6459     idxm(MatStencil_j, 1) = j
6460     idxm(MatStencil_k, 1) = k
6461     idxm(MatStencil_c, 1) = c
6462    etc
6463 .ve
6464 
6465 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6466           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6467 @*/
6468 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6469 {
6470   PetscInt  dim    = mat->stencil.dim;
6471   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6472   PetscInt *dims   = mat->stencil.dims + 1;
6473   PetscInt *starts = mat->stencil.starts;
6474   PetscInt *dxm    = (PetscInt *)rows;
6475   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6476 
6477   PetscFunctionBegin;
6478   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6479   PetscValidType(mat, 1);
6480   if (numRows) PetscAssertPointer(rows, 3);
6481 
6482   PetscCall(PetscMalloc1(numRows, &jdxm));
6483   for (i = 0; i < numRows; ++i) {
6484     /* Skip unused dimensions (they are ordered k, j, i, c) */
6485     for (j = 0; j < 3 - sdim; ++j) dxm++;
6486     /* Local index in X dir */
6487     tmp = *dxm++ - starts[0];
6488     /* Loop over remaining dimensions */
6489     for (j = 0; j < dim - 1; ++j) {
6490       /* If nonlocal, set index to be negative */
6491       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6492       /* Update local index */
6493       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6494     }
6495     /* Skip component slot if necessary */
6496     if (mat->stencil.noc) dxm++;
6497     /* Local row number */
6498     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6499   }
6500   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6501   PetscCall(PetscFree(jdxm));
6502   PetscFunctionReturn(PETSC_SUCCESS);
6503 }
6504 
6505 /*@
6506   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6507   of a set of rows and columns of a matrix.
6508 
6509   Collective
6510 
6511   Input Parameters:
6512 + mat     - the matrix
6513 . numRows - the number of rows/columns to remove
6514 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6515 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6516 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6517 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6518 
6519   Level: intermediate
6520 
6521   Notes:
6522   See `MatZeroRowsColumns()` for details on how this routine operates.
6523 
6524   The grid coordinates are across the entire grid, not just the local portion
6525 
6526   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6527   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6528   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6529   `DM_BOUNDARY_PERIODIC` boundary type.
6530 
6531   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
6532   a single value per point) you can skip filling those indices.
6533 
6534   Fortran Note:
6535   `idxm` and `idxn` should be declared as
6536 .vb
6537     MatStencil idxm(4, m)
6538 .ve
6539   and the values inserted using
6540 .vb
6541     idxm(MatStencil_i, 1) = i
6542     idxm(MatStencil_j, 1) = j
6543     idxm(MatStencil_k, 1) = k
6544     idxm(MatStencil_c, 1) = c
6545     etc
6546 .ve
6547 
6548 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6549           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6550 @*/
6551 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6552 {
6553   PetscInt  dim    = mat->stencil.dim;
6554   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6555   PetscInt *dims   = mat->stencil.dims + 1;
6556   PetscInt *starts = mat->stencil.starts;
6557   PetscInt *dxm    = (PetscInt *)rows;
6558   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6559 
6560   PetscFunctionBegin;
6561   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6562   PetscValidType(mat, 1);
6563   if (numRows) PetscAssertPointer(rows, 3);
6564 
6565   PetscCall(PetscMalloc1(numRows, &jdxm));
6566   for (i = 0; i < numRows; ++i) {
6567     /* Skip unused dimensions (they are ordered k, j, i, c) */
6568     for (j = 0; j < 3 - sdim; ++j) dxm++;
6569     /* Local index in X dir */
6570     tmp = *dxm++ - starts[0];
6571     /* Loop over remaining dimensions */
6572     for (j = 0; j < dim - 1; ++j) {
6573       /* If nonlocal, set index to be negative */
6574       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6575       /* Update local index */
6576       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6577     }
6578     /* Skip component slot if necessary */
6579     if (mat->stencil.noc) dxm++;
6580     /* Local row number */
6581     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6582   }
6583   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6584   PetscCall(PetscFree(jdxm));
6585   PetscFunctionReturn(PETSC_SUCCESS);
6586 }
6587 
6588 /*@
6589   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6590   of a set of rows of a matrix; using local numbering of rows.
6591 
6592   Collective
6593 
6594   Input Parameters:
6595 + mat     - the matrix
6596 . numRows - the number of rows to remove
6597 . rows    - the local row indices
6598 . diag    - value put in all diagonals of eliminated rows
6599 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6600 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6601 
6602   Level: intermediate
6603 
6604   Notes:
6605   Before calling `MatZeroRowsLocal()`, the user must first set the
6606   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6607 
6608   See `MatZeroRows()` for details on how this routine operates.
6609 
6610 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6611           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6612 @*/
6613 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6614 {
6615   PetscFunctionBegin;
6616   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6617   PetscValidType(mat, 1);
6618   if (numRows) PetscAssertPointer(rows, 3);
6619   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6620   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6621   MatCheckPreallocated(mat, 1);
6622 
6623   if (mat->ops->zerorowslocal) {
6624     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6625   } else {
6626     IS              is, newis;
6627     const PetscInt *newRows;
6628 
6629     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6630     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6631     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6632     PetscCall(ISGetIndices(newis, &newRows));
6633     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6634     PetscCall(ISRestoreIndices(newis, &newRows));
6635     PetscCall(ISDestroy(&newis));
6636     PetscCall(ISDestroy(&is));
6637   }
6638   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6639   PetscFunctionReturn(PETSC_SUCCESS);
6640 }
6641 
6642 /*@
6643   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6644   of a set of rows of a matrix; using local numbering of rows.
6645 
6646   Collective
6647 
6648   Input Parameters:
6649 + mat  - the matrix
6650 . is   - index set of rows to remove
6651 . diag - value put in all diagonals of eliminated rows
6652 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6653 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6654 
6655   Level: intermediate
6656 
6657   Notes:
6658   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6659   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6660 
6661   See `MatZeroRows()` for details on how this routine operates.
6662 
6663 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6664           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6665 @*/
6666 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6667 {
6668   PetscInt        numRows;
6669   const PetscInt *rows;
6670 
6671   PetscFunctionBegin;
6672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6673   PetscValidType(mat, 1);
6674   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6675   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6676   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6677   MatCheckPreallocated(mat, 1);
6678 
6679   PetscCall(ISGetLocalSize(is, &numRows));
6680   PetscCall(ISGetIndices(is, &rows));
6681   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6682   PetscCall(ISRestoreIndices(is, &rows));
6683   PetscFunctionReturn(PETSC_SUCCESS);
6684 }
6685 
6686 /*@
6687   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6688   of a set of rows and columns of a matrix; using local numbering of rows.
6689 
6690   Collective
6691 
6692   Input Parameters:
6693 + mat     - the matrix
6694 . numRows - the number of rows to remove
6695 . rows    - the global row indices
6696 . diag    - value put in all diagonals of eliminated rows
6697 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6698 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6699 
6700   Level: intermediate
6701 
6702   Notes:
6703   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6704   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6705 
6706   See `MatZeroRowsColumns()` for details on how this routine operates.
6707 
6708 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6709           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6710 @*/
6711 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6712 {
6713   IS              is, newis;
6714   const PetscInt *newRows;
6715 
6716   PetscFunctionBegin;
6717   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6718   PetscValidType(mat, 1);
6719   if (numRows) PetscAssertPointer(rows, 3);
6720   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6721   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6722   MatCheckPreallocated(mat, 1);
6723 
6724   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6725   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6726   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6727   PetscCall(ISGetIndices(newis, &newRows));
6728   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6729   PetscCall(ISRestoreIndices(newis, &newRows));
6730   PetscCall(ISDestroy(&newis));
6731   PetscCall(ISDestroy(&is));
6732   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6733   PetscFunctionReturn(PETSC_SUCCESS);
6734 }
6735 
6736 /*@
6737   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6738   of a set of rows and columns of a matrix; using local numbering of rows.
6739 
6740   Collective
6741 
6742   Input Parameters:
6743 + mat  - the matrix
6744 . is   - index set of rows to remove
6745 . diag - value put in all diagonals of eliminated rows
6746 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6747 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6748 
6749   Level: intermediate
6750 
6751   Notes:
6752   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6753   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6754 
6755   See `MatZeroRowsColumns()` for details on how this routine operates.
6756 
6757 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6758           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6759 @*/
6760 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6761 {
6762   PetscInt        numRows;
6763   const PetscInt *rows;
6764 
6765   PetscFunctionBegin;
6766   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6767   PetscValidType(mat, 1);
6768   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6769   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6770   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6771   MatCheckPreallocated(mat, 1);
6772 
6773   PetscCall(ISGetLocalSize(is, &numRows));
6774   PetscCall(ISGetIndices(is, &rows));
6775   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6776   PetscCall(ISRestoreIndices(is, &rows));
6777   PetscFunctionReturn(PETSC_SUCCESS);
6778 }
6779 
6780 /*@
6781   MatGetSize - Returns the numbers of rows and columns in a matrix.
6782 
6783   Not Collective
6784 
6785   Input Parameter:
6786 . mat - the matrix
6787 
6788   Output Parameters:
6789 + m - the number of global rows
6790 - n - the number of global columns
6791 
6792   Level: beginner
6793 
6794   Note:
6795   Both output parameters can be `NULL` on input.
6796 
6797 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6798 @*/
6799 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6800 {
6801   PetscFunctionBegin;
6802   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6803   if (m) *m = mat->rmap->N;
6804   if (n) *n = mat->cmap->N;
6805   PetscFunctionReturn(PETSC_SUCCESS);
6806 }
6807 
6808 /*@
6809   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6810   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6811 
6812   Not Collective
6813 
6814   Input Parameter:
6815 . mat - the matrix
6816 
6817   Output Parameters:
6818 + m - the number of local rows, use `NULL` to not obtain this value
6819 - n - the number of local columns, use `NULL` to not obtain this value
6820 
6821   Level: beginner
6822 
6823 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6824 @*/
6825 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6826 {
6827   PetscFunctionBegin;
6828   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6829   if (m) PetscAssertPointer(m, 2);
6830   if (n) PetscAssertPointer(n, 3);
6831   if (m) *m = mat->rmap->n;
6832   if (n) *n = mat->cmap->n;
6833   PetscFunctionReturn(PETSC_SUCCESS);
6834 }
6835 
6836 /*@
6837   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6838   vector one multiplies this matrix by that are owned by this processor.
6839 
6840   Not Collective, unless matrix has not been allocated, then collective
6841 
6842   Input Parameter:
6843 . mat - the matrix
6844 
6845   Output Parameters:
6846 + m - the global index of the first local column, use `NULL` to not obtain this value
6847 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6848 
6849   Level: developer
6850 
6851   Notes:
6852   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6853 
6854   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6855   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6856 
6857   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6858   the local values in the matrix.
6859 
6860   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6861   Layouts](sec_matlayout) for details on matrix layouts.
6862 
6863 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6864           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6865 @*/
6866 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6867 {
6868   PetscFunctionBegin;
6869   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6870   PetscValidType(mat, 1);
6871   if (m) PetscAssertPointer(m, 2);
6872   if (n) PetscAssertPointer(n, 3);
6873   MatCheckPreallocated(mat, 1);
6874   if (m) *m = mat->cmap->rstart;
6875   if (n) *n = mat->cmap->rend;
6876   PetscFunctionReturn(PETSC_SUCCESS);
6877 }
6878 
6879 /*@
6880   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6881   this MPI process.
6882 
6883   Not Collective
6884 
6885   Input Parameter:
6886 . mat - the matrix
6887 
6888   Output Parameters:
6889 + m - the global index of the first local row, use `NULL` to not obtain this value
6890 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6891 
6892   Level: beginner
6893 
6894   Notes:
6895   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6896 
6897   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6898   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6899 
6900   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6901   the local values in the matrix.
6902 
6903   The high argument is one more than the last element stored locally.
6904 
6905   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6906   would contain the result of a matrix vector product with this matrix. See [Matrix
6907   Layouts](sec_matlayout) for details on matrix layouts.
6908 
6909 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6910           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6911 @*/
6912 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6913 {
6914   PetscFunctionBegin;
6915   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6916   PetscValidType(mat, 1);
6917   if (m) PetscAssertPointer(m, 2);
6918   if (n) PetscAssertPointer(n, 3);
6919   MatCheckPreallocated(mat, 1);
6920   if (m) *m = mat->rmap->rstart;
6921   if (n) *n = mat->rmap->rend;
6922   PetscFunctionReturn(PETSC_SUCCESS);
6923 }
6924 
6925 /*@C
6926   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6927   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6928 
6929   Not Collective, unless matrix has not been allocated
6930 
6931   Input Parameter:
6932 . mat - the matrix
6933 
6934   Output Parameter:
6935 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6936            where `size` is the number of MPI processes used by `mat`
6937 
6938   Level: beginner
6939 
6940   Notes:
6941   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6942 
6943   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6944   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6945 
6946   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6947   the local values in the matrix.
6948 
6949   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6950   would contain the result of a matrix vector product with this matrix. See [Matrix
6951   Layouts](sec_matlayout) for details on matrix layouts.
6952 
6953 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6954           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6955           `DMDAGetGhostCorners()`, `DM`
6956 @*/
6957 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6958 {
6959   PetscFunctionBegin;
6960   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6961   PetscValidType(mat, 1);
6962   MatCheckPreallocated(mat, 1);
6963   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6964   PetscFunctionReturn(PETSC_SUCCESS);
6965 }
6966 
6967 /*@C
6968   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6969   vector one multiplies this vector by that are owned by each processor.
6970 
6971   Not Collective, unless matrix has not been allocated
6972 
6973   Input Parameter:
6974 . mat - the matrix
6975 
6976   Output Parameter:
6977 . ranges - start of each processors portion plus one more than the total length at the end
6978 
6979   Level: beginner
6980 
6981   Notes:
6982   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6983 
6984   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6985   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6986 
6987   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6988   the local values in the matrix.
6989 
6990   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6991   Layouts](sec_matlayout) for details on matrix layouts.
6992 
6993 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
6994           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
6995           `DMDAGetGhostCorners()`, `DM`
6996 @*/
6997 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
6998 {
6999   PetscFunctionBegin;
7000   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7001   PetscValidType(mat, 1);
7002   MatCheckPreallocated(mat, 1);
7003   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7004   PetscFunctionReturn(PETSC_SUCCESS);
7005 }
7006 
7007 /*@
7008   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7009 
7010   Not Collective
7011 
7012   Input Parameter:
7013 . A - matrix
7014 
7015   Output Parameters:
7016 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7017 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7018 
7019   Level: intermediate
7020 
7021   Note:
7022   You should call `ISDestroy()` on the returned `IS`
7023 
7024   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7025   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7026   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7027   details on matrix layouts.
7028 
7029 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7030 @*/
7031 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7032 {
7033   PetscErrorCode (*f)(Mat, IS *, IS *);
7034 
7035   PetscFunctionBegin;
7036   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7037   PetscValidType(A, 1);
7038   MatCheckPreallocated(A, 1);
7039   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7040   if (f) {
7041     PetscCall((*f)(A, rows, cols));
7042   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7043     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7044     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7045   }
7046   PetscFunctionReturn(PETSC_SUCCESS);
7047 }
7048 
7049 /*@
7050   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7051   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7052   to complete the factorization.
7053 
7054   Collective
7055 
7056   Input Parameters:
7057 + fact - the factorized matrix obtained with `MatGetFactor()`
7058 . mat  - the matrix
7059 . row  - row permutation
7060 . col  - column permutation
7061 - info - structure containing
7062 .vb
7063       levels - number of levels of fill.
7064       expected fill - as ratio of original fill.
7065       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7066                 missing diagonal entries)
7067 .ve
7068 
7069   Level: developer
7070 
7071   Notes:
7072   See [Matrix Factorization](sec_matfactor) for additional information.
7073 
7074   Most users should employ the `KSP` interface for linear solvers
7075   instead of working directly with matrix algebra routines such as this.
7076   See, e.g., `KSPCreate()`.
7077 
7078   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7079 
7080   Fortran Note:
7081   A valid (non-null) `info` argument must be provided
7082 
7083 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7084           `MatGetOrdering()`, `MatFactorInfo`
7085 @*/
7086 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7087 {
7088   PetscFunctionBegin;
7089   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7090   PetscValidType(mat, 2);
7091   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7092   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7093   PetscAssertPointer(info, 5);
7094   PetscAssertPointer(fact, 1);
7095   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7096   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7097   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7098   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7099   MatCheckPreallocated(mat, 2);
7100 
7101   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7102   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7103   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7104   PetscFunctionReturn(PETSC_SUCCESS);
7105 }
7106 
7107 /*@
7108   MatICCFactorSymbolic - Performs symbolic incomplete
7109   Cholesky factorization for a symmetric matrix.  Use
7110   `MatCholeskyFactorNumeric()` to complete the factorization.
7111 
7112   Collective
7113 
7114   Input Parameters:
7115 + fact - the factorized matrix obtained with `MatGetFactor()`
7116 . mat  - the matrix to be factored
7117 . perm - row and column permutation
7118 - info - structure containing
7119 .vb
7120       levels - number of levels of fill.
7121       expected fill - as ratio of original fill.
7122 .ve
7123 
7124   Level: developer
7125 
7126   Notes:
7127   Most users should employ the `KSP` interface for linear solvers
7128   instead of working directly with matrix algebra routines such as this.
7129   See, e.g., `KSPCreate()`.
7130 
7131   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7132 
7133   Fortran Note:
7134   A valid (non-null) `info` argument must be provided
7135 
7136 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7137 @*/
7138 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7139 {
7140   PetscFunctionBegin;
7141   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7142   PetscValidType(mat, 2);
7143   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7144   PetscAssertPointer(info, 4);
7145   PetscAssertPointer(fact, 1);
7146   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7147   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7148   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7149   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7150   MatCheckPreallocated(mat, 2);
7151 
7152   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7153   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7154   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7155   PetscFunctionReturn(PETSC_SUCCESS);
7156 }
7157 
7158 /*@C
7159   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7160   points to an array of valid matrices, they may be reused to store the new
7161   submatrices.
7162 
7163   Collective
7164 
7165   Input Parameters:
7166 + mat   - the matrix
7167 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7168 . irow  - index set of rows to extract
7169 . icol  - index set of columns to extract
7170 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7171 
7172   Output Parameter:
7173 . submat - the array of submatrices
7174 
7175   Level: advanced
7176 
7177   Notes:
7178   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7179   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7180   to extract a parallel submatrix.
7181 
7182   Some matrix types place restrictions on the row and column
7183   indices, such as that they be sorted or that they be equal to each other.
7184 
7185   The index sets may not have duplicate entries.
7186 
7187   When extracting submatrices from a parallel matrix, each processor can
7188   form a different submatrix by setting the rows and columns of its
7189   individual index sets according to the local submatrix desired.
7190 
7191   When finished using the submatrices, the user should destroy
7192   them with `MatDestroySubMatrices()`.
7193 
7194   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7195   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7196 
7197   This routine creates the matrices in submat; you should NOT create them before
7198   calling it. It also allocates the array of matrix pointers submat.
7199 
7200   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7201   request one row/column in a block, they must request all rows/columns that are in
7202   that block. For example, if the block size is 2 you cannot request just row 0 and
7203   column 0.
7204 
7205   Fortran Note:
7206 .vb
7207   Mat, pointer :: submat(:)
7208 .ve
7209 
7210 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7211 @*/
7212 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7213 {
7214   PetscInt  i;
7215   PetscBool eq;
7216 
7217   PetscFunctionBegin;
7218   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7219   PetscValidType(mat, 1);
7220   if (n) {
7221     PetscAssertPointer(irow, 3);
7222     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7223     PetscAssertPointer(icol, 4);
7224     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7225   }
7226   PetscAssertPointer(submat, 6);
7227   if (n && scall == MAT_REUSE_MATRIX) {
7228     PetscAssertPointer(*submat, 6);
7229     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7230   }
7231   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7232   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7233   MatCheckPreallocated(mat, 1);
7234   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7235   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7236   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7237   for (i = 0; i < n; i++) {
7238     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7239     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7240     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7241 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7242     if (mat->boundtocpu && mat->bindingpropagates) {
7243       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7244       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7245     }
7246 #endif
7247   }
7248   PetscFunctionReturn(PETSC_SUCCESS);
7249 }
7250 
7251 /*@C
7252   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms).
7253 
7254   Collective
7255 
7256   Input Parameters:
7257 + mat   - the matrix
7258 . n     - the number of submatrixes to be extracted
7259 . irow  - index set of rows to extract
7260 . icol  - index set of columns to extract
7261 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7262 
7263   Output Parameter:
7264 . submat - the array of submatrices
7265 
7266   Level: advanced
7267 
7268   Note:
7269   This is used by `PCGASM`
7270 
7271 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7272 @*/
7273 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7274 {
7275   PetscInt  i;
7276   PetscBool eq;
7277 
7278   PetscFunctionBegin;
7279   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7280   PetscValidType(mat, 1);
7281   if (n) {
7282     PetscAssertPointer(irow, 3);
7283     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7284     PetscAssertPointer(icol, 4);
7285     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7286   }
7287   PetscAssertPointer(submat, 6);
7288   if (n && scall == MAT_REUSE_MATRIX) {
7289     PetscAssertPointer(*submat, 6);
7290     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7291   }
7292   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7293   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7294   MatCheckPreallocated(mat, 1);
7295 
7296   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7297   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7298   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7299   for (i = 0; i < n; i++) {
7300     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7301     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7302   }
7303   PetscFunctionReturn(PETSC_SUCCESS);
7304 }
7305 
7306 /*@C
7307   MatDestroyMatrices - Destroys an array of matrices
7308 
7309   Collective
7310 
7311   Input Parameters:
7312 + n   - the number of local matrices
7313 - mat - the matrices (this is a pointer to the array of matrices)
7314 
7315   Level: advanced
7316 
7317   Notes:
7318   Frees not only the matrices, but also the array that contains the matrices
7319 
7320   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7321 
7322 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7323 @*/
7324 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7325 {
7326   PetscInt i;
7327 
7328   PetscFunctionBegin;
7329   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7330   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7331   PetscAssertPointer(mat, 2);
7332 
7333   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7334 
7335   /* memory is allocated even if n = 0 */
7336   PetscCall(PetscFree(*mat));
7337   PetscFunctionReturn(PETSC_SUCCESS);
7338 }
7339 
7340 /*@C
7341   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7342 
7343   Collective
7344 
7345   Input Parameters:
7346 + n   - the number of local matrices
7347 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`)
7348 
7349   Level: advanced
7350 
7351   Note:
7352   Frees not only the matrices, but also the array that contains the matrices
7353 
7354 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7355 @*/
7356 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7357 {
7358   Mat mat0;
7359 
7360   PetscFunctionBegin;
7361   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7362   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7363   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7364   PetscAssertPointer(mat, 2);
7365 
7366   mat0 = (*mat)[0];
7367   if (mat0 && mat0->ops->destroysubmatrices) {
7368     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7369   } else {
7370     PetscCall(MatDestroyMatrices(n, mat));
7371   }
7372   PetscFunctionReturn(PETSC_SUCCESS);
7373 }
7374 
7375 /*@
7376   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7377 
7378   Collective
7379 
7380   Input Parameter:
7381 . mat - the matrix
7382 
7383   Output Parameter:
7384 . matstruct - the sequential matrix with the nonzero structure of `mat`
7385 
7386   Level: developer
7387 
7388 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7389 @*/
7390 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7391 {
7392   PetscFunctionBegin;
7393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7394   PetscAssertPointer(matstruct, 2);
7395 
7396   PetscValidType(mat, 1);
7397   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7398   MatCheckPreallocated(mat, 1);
7399 
7400   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7401   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7402   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7403   PetscFunctionReturn(PETSC_SUCCESS);
7404 }
7405 
7406 /*@C
7407   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7408 
7409   Collective
7410 
7411   Input Parameter:
7412 . mat - the matrix
7413 
7414   Level: advanced
7415 
7416   Note:
7417   This is not needed, one can just call `MatDestroy()`
7418 
7419 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7420 @*/
7421 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7422 {
7423   PetscFunctionBegin;
7424   PetscAssertPointer(mat, 1);
7425   PetscCall(MatDestroy(mat));
7426   PetscFunctionReturn(PETSC_SUCCESS);
7427 }
7428 
7429 /*@
7430   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7431   replaces the index sets by larger ones that represent submatrices with
7432   additional overlap.
7433 
7434   Collective
7435 
7436   Input Parameters:
7437 + mat - the matrix
7438 . n   - the number of index sets
7439 . is  - the array of index sets (these index sets will changed during the call)
7440 - ov  - the additional overlap requested
7441 
7442   Options Database Key:
7443 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7444 
7445   Level: developer
7446 
7447   Note:
7448   The computed overlap preserves the matrix block sizes when the blocks are square.
7449   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7450   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7451 
7452 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7453 @*/
7454 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7455 {
7456   PetscInt i, bs, cbs;
7457 
7458   PetscFunctionBegin;
7459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7460   PetscValidType(mat, 1);
7461   PetscValidLogicalCollectiveInt(mat, n, 2);
7462   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7463   if (n) {
7464     PetscAssertPointer(is, 3);
7465     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7466   }
7467   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7468   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7469   MatCheckPreallocated(mat, 1);
7470 
7471   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7472   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7473   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7474   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7475   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7476   if (bs == cbs) {
7477     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7478   }
7479   PetscFunctionReturn(PETSC_SUCCESS);
7480 }
7481 
7482 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7483 
7484 /*@
7485   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7486   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7487   additional overlap.
7488 
7489   Collective
7490 
7491   Input Parameters:
7492 + mat - the matrix
7493 . n   - the number of index sets
7494 . is  - the array of index sets (these index sets will changed during the call)
7495 - ov  - the additional overlap requested
7496 
7497   `   Options Database Key:
7498 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7499 
7500   Level: developer
7501 
7502 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7503 @*/
7504 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7505 {
7506   PetscInt i;
7507 
7508   PetscFunctionBegin;
7509   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7510   PetscValidType(mat, 1);
7511   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7512   if (n) {
7513     PetscAssertPointer(is, 3);
7514     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7515   }
7516   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7517   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7518   MatCheckPreallocated(mat, 1);
7519   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7520   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7521   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7522   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7523   PetscFunctionReturn(PETSC_SUCCESS);
7524 }
7525 
7526 /*@
7527   MatGetBlockSize - Returns the matrix block size.
7528 
7529   Not Collective
7530 
7531   Input Parameter:
7532 . mat - the matrix
7533 
7534   Output Parameter:
7535 . bs - block size
7536 
7537   Level: intermediate
7538 
7539   Notes:
7540   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7541 
7542   If the block size has not been set yet this routine returns 1.
7543 
7544 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7545 @*/
7546 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7547 {
7548   PetscFunctionBegin;
7549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7550   PetscAssertPointer(bs, 2);
7551   *bs = mat->rmap->bs;
7552   PetscFunctionReturn(PETSC_SUCCESS);
7553 }
7554 
7555 /*@
7556   MatGetBlockSizes - Returns the matrix block row and column sizes.
7557 
7558   Not Collective
7559 
7560   Input Parameter:
7561 . mat - the matrix
7562 
7563   Output Parameters:
7564 + rbs - row block size
7565 - cbs - column block size
7566 
7567   Level: intermediate
7568 
7569   Notes:
7570   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7571   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7572 
7573   If a block size has not been set yet this routine returns 1.
7574 
7575 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7576 @*/
7577 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7578 {
7579   PetscFunctionBegin;
7580   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7581   if (rbs) PetscAssertPointer(rbs, 2);
7582   if (cbs) PetscAssertPointer(cbs, 3);
7583   if (rbs) *rbs = mat->rmap->bs;
7584   if (cbs) *cbs = mat->cmap->bs;
7585   PetscFunctionReturn(PETSC_SUCCESS);
7586 }
7587 
7588 /*@
7589   MatSetBlockSize - Sets the matrix block size.
7590 
7591   Logically Collective
7592 
7593   Input Parameters:
7594 + mat - the matrix
7595 - bs  - block size
7596 
7597   Level: intermediate
7598 
7599   Notes:
7600   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7601   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7602 
7603   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7604   is compatible with the matrix local sizes.
7605 
7606 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7607 @*/
7608 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7609 {
7610   PetscFunctionBegin;
7611   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7612   PetscValidLogicalCollectiveInt(mat, bs, 2);
7613   PetscCall(MatSetBlockSizes(mat, bs, bs));
7614   PetscFunctionReturn(PETSC_SUCCESS);
7615 }
7616 
7617 typedef struct {
7618   PetscInt         n;
7619   IS              *is;
7620   Mat             *mat;
7621   PetscObjectState nonzerostate;
7622   Mat              C;
7623 } EnvelopeData;
7624 
7625 static PetscErrorCode EnvelopeDataDestroy(void **ptr)
7626 {
7627   EnvelopeData *edata = (EnvelopeData *)*ptr;
7628 
7629   PetscFunctionBegin;
7630   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7631   PetscCall(PetscFree(edata->is));
7632   PetscCall(PetscFree(edata));
7633   PetscFunctionReturn(PETSC_SUCCESS);
7634 }
7635 
7636 /*@
7637   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7638   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7639 
7640   Collective
7641 
7642   Input Parameter:
7643 . mat - the matrix
7644 
7645   Level: intermediate
7646 
7647   Notes:
7648   There can be zeros within the blocks
7649 
7650   The blocks can overlap between processes, including laying on more than two processes
7651 
7652 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7653 @*/
7654 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7655 {
7656   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7657   PetscInt          *diag, *odiag, sc;
7658   VecScatter         scatter;
7659   PetscScalar       *seqv;
7660   const PetscScalar *parv;
7661   const PetscInt    *ia, *ja;
7662   PetscBool          set, flag, done;
7663   Mat                AA = mat, A;
7664   MPI_Comm           comm;
7665   PetscMPIInt        rank, size, tag;
7666   MPI_Status         status;
7667   PetscContainer     container;
7668   EnvelopeData      *edata;
7669   Vec                seq, par;
7670   IS                 isglobal;
7671 
7672   PetscFunctionBegin;
7673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7674   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7675   if (!set || !flag) {
7676     /* TODO: only needs nonzero structure of transpose */
7677     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7678     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7679   }
7680   PetscCall(MatAIJGetLocalMat(AA, &A));
7681   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7682   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7683 
7684   PetscCall(MatGetLocalSize(mat, &n, NULL));
7685   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7686   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7687   PetscCallMPI(MPI_Comm_size(comm, &size));
7688   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7689 
7690   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7691 
7692   if (rank > 0) {
7693     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7694     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7695   }
7696   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7697   for (i = 0; i < n; i++) {
7698     env = PetscMax(env, ja[ia[i + 1] - 1]);
7699     II  = rstart + i;
7700     if (env == II) {
7701       starts[lblocks]  = tbs;
7702       sizes[lblocks++] = 1 + II - tbs;
7703       tbs              = 1 + II;
7704     }
7705   }
7706   if (rank < size - 1) {
7707     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7708     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7709   }
7710 
7711   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7712   if (!set || !flag) PetscCall(MatDestroy(&AA));
7713   PetscCall(MatDestroy(&A));
7714 
7715   PetscCall(PetscNew(&edata));
7716   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7717   edata->n = lblocks;
7718   /* create IS needed for extracting blocks from the original matrix */
7719   PetscCall(PetscMalloc1(lblocks, &edata->is));
7720   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7721 
7722   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7723   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7724   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7725   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7726   PetscCall(MatSetType(edata->C, MATAIJ));
7727 
7728   /* Communicate the start and end of each row, from each block to the correct rank */
7729   /* TODO: Use PetscSF instead of VecScatter */
7730   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7731   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7732   PetscCall(VecGetArrayWrite(seq, &seqv));
7733   for (PetscInt i = 0; i < lblocks; i++) {
7734     for (PetscInt j = 0; j < sizes[i]; j++) {
7735       seqv[cnt]     = starts[i];
7736       seqv[cnt + 1] = starts[i] + sizes[i];
7737       cnt += 2;
7738     }
7739   }
7740   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7741   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7742   sc -= cnt;
7743   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7744   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7745   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7746   PetscCall(ISDestroy(&isglobal));
7747   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7748   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7749   PetscCall(VecScatterDestroy(&scatter));
7750   PetscCall(VecDestroy(&seq));
7751   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7752   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7753   PetscCall(VecGetArrayRead(par, &parv));
7754   cnt = 0;
7755   PetscCall(MatGetSize(mat, NULL, &n));
7756   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7757     PetscInt start, end, d = 0, od = 0;
7758 
7759     start = (PetscInt)PetscRealPart(parv[cnt]);
7760     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7761     cnt += 2;
7762 
7763     if (start < cstart) {
7764       od += cstart - start + n - cend;
7765       d += cend - cstart;
7766     } else if (start < cend) {
7767       od += n - cend;
7768       d += cend - start;
7769     } else od += n - start;
7770     if (end <= cstart) {
7771       od -= cstart - end + n - cend;
7772       d -= cend - cstart;
7773     } else if (end < cend) {
7774       od -= n - cend;
7775       d -= cend - end;
7776     } else od -= n - end;
7777 
7778     odiag[i] = od;
7779     diag[i]  = d;
7780   }
7781   PetscCall(VecRestoreArrayRead(par, &parv));
7782   PetscCall(VecDestroy(&par));
7783   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7784   PetscCall(PetscFree2(diag, odiag));
7785   PetscCall(PetscFree2(sizes, starts));
7786 
7787   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7788   PetscCall(PetscContainerSetPointer(container, edata));
7789   PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy));
7790   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7791   PetscCall(PetscObjectDereference((PetscObject)container));
7792   PetscFunctionReturn(PETSC_SUCCESS);
7793 }
7794 
7795 /*@
7796   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7797 
7798   Collective
7799 
7800   Input Parameters:
7801 + A     - the matrix
7802 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7803 
7804   Output Parameter:
7805 . C - matrix with inverted block diagonal of `A`
7806 
7807   Level: advanced
7808 
7809   Note:
7810   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7811 
7812 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7813 @*/
7814 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7815 {
7816   PetscContainer   container;
7817   EnvelopeData    *edata;
7818   PetscObjectState nonzerostate;
7819 
7820   PetscFunctionBegin;
7821   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7822   if (!container) {
7823     PetscCall(MatComputeVariableBlockEnvelope(A));
7824     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7825   }
7826   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7827   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7828   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7829   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7830 
7831   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7832   *C = edata->C;
7833 
7834   for (PetscInt i = 0; i < edata->n; i++) {
7835     Mat          D;
7836     PetscScalar *dvalues;
7837 
7838     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7839     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7840     PetscCall(MatSeqDenseInvert(D));
7841     PetscCall(MatDenseGetArray(D, &dvalues));
7842     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7843     PetscCall(MatDestroy(&D));
7844   }
7845   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7846   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7847   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7848   PetscFunctionReturn(PETSC_SUCCESS);
7849 }
7850 
7851 /*@
7852   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7853 
7854   Not Collective
7855 
7856   Input Parameters:
7857 + mat     - the matrix
7858 . nblocks - the number of blocks on this process, each block can only exist on a single process
7859 - bsizes  - the block sizes
7860 
7861   Level: intermediate
7862 
7863   Notes:
7864   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7865 
7866   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.
7867 
7868 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7869           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7870 @*/
7871 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7872 {
7873   PetscInt ncnt = 0, nlocal;
7874 
7875   PetscFunctionBegin;
7876   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7877   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7878   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);
7879   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7880   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);
7881   PetscCall(PetscFree(mat->bsizes));
7882   mat->nblocks = nblocks;
7883   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7884   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7885   PetscFunctionReturn(PETSC_SUCCESS);
7886 }
7887 
7888 /*@C
7889   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7890 
7891   Not Collective; No Fortran Support
7892 
7893   Input Parameter:
7894 . mat - the matrix
7895 
7896   Output Parameters:
7897 + nblocks - the number of blocks on this process
7898 - bsizes  - the block sizes
7899 
7900   Level: intermediate
7901 
7902 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7903 @*/
7904 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7905 {
7906   PetscFunctionBegin;
7907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7908   if (nblocks) *nblocks = mat->nblocks;
7909   if (bsizes) *bsizes = mat->bsizes;
7910   PetscFunctionReturn(PETSC_SUCCESS);
7911 }
7912 
7913 /*@
7914   MatSetBlockSizes - Sets the matrix block row and column sizes.
7915 
7916   Logically Collective
7917 
7918   Input Parameters:
7919 + mat - the matrix
7920 . rbs - row block size
7921 - cbs - column block size
7922 
7923   Level: intermediate
7924 
7925   Notes:
7926   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7927   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7928   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7929 
7930   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7931   are compatible with the matrix local sizes.
7932 
7933   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7934 
7935 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7936 @*/
7937 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7938 {
7939   PetscFunctionBegin;
7940   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7941   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7942   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7943   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7944   if (mat->rmap->refcnt) {
7945     ISLocalToGlobalMapping l2g  = NULL;
7946     PetscLayout            nmap = NULL;
7947 
7948     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7949     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7950     PetscCall(PetscLayoutDestroy(&mat->rmap));
7951     mat->rmap          = nmap;
7952     mat->rmap->mapping = l2g;
7953   }
7954   if (mat->cmap->refcnt) {
7955     ISLocalToGlobalMapping l2g  = NULL;
7956     PetscLayout            nmap = NULL;
7957 
7958     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7959     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7960     PetscCall(PetscLayoutDestroy(&mat->cmap));
7961     mat->cmap          = nmap;
7962     mat->cmap->mapping = l2g;
7963   }
7964   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7965   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7966   PetscFunctionReturn(PETSC_SUCCESS);
7967 }
7968 
7969 /*@
7970   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7971 
7972   Logically Collective
7973 
7974   Input Parameters:
7975 + mat     - the matrix
7976 . fromRow - matrix from which to copy row block size
7977 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7978 
7979   Level: developer
7980 
7981 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7982 @*/
7983 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7984 {
7985   PetscFunctionBegin;
7986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7987   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7988   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7989   PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7990   PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7991   PetscFunctionReturn(PETSC_SUCCESS);
7992 }
7993 
7994 /*@
7995   MatResidual - Default routine to calculate the residual r = b - Ax
7996 
7997   Collective
7998 
7999   Input Parameters:
8000 + mat - the matrix
8001 . b   - the right-hand-side
8002 - x   - the approximate solution
8003 
8004   Output Parameter:
8005 . r - location to store the residual
8006 
8007   Level: developer
8008 
8009 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8010 @*/
8011 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8012 {
8013   PetscFunctionBegin;
8014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8015   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8016   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8017   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8018   PetscValidType(mat, 1);
8019   MatCheckPreallocated(mat, 1);
8020   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8021   if (!mat->ops->residual) {
8022     PetscCall(MatMult(mat, x, r));
8023     PetscCall(VecAYPX(r, -1.0, b));
8024   } else {
8025     PetscUseTypeMethod(mat, residual, b, x, r);
8026   }
8027   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8028   PetscFunctionReturn(PETSC_SUCCESS);
8029 }
8030 
8031 /*@C
8032   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8033 
8034   Collective
8035 
8036   Input Parameters:
8037 + mat             - the matrix
8038 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8039 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8040 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8041                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8042                  always used.
8043 
8044   Output Parameters:
8045 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8046 . 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
8047 . ja   - the column indices, use `NULL` if not needed
8048 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8049            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8050 
8051   Level: developer
8052 
8053   Notes:
8054   You CANNOT change any of the ia[] or ja[] values.
8055 
8056   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8057 
8058   Fortran Notes:
8059   Use
8060 .vb
8061     PetscInt, pointer :: ia(:),ja(:)
8062     call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8063     ! Access the ith and jth entries via ia(i) and ja(j)
8064 .ve
8065 
8066 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8067 @*/
8068 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8069 {
8070   PetscFunctionBegin;
8071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8072   PetscValidType(mat, 1);
8073   if (n) PetscAssertPointer(n, 5);
8074   if (ia) PetscAssertPointer(ia, 6);
8075   if (ja) PetscAssertPointer(ja, 7);
8076   if (done) PetscAssertPointer(done, 8);
8077   MatCheckPreallocated(mat, 1);
8078   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8079   else {
8080     if (done) *done = PETSC_TRUE;
8081     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8082     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8083     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8084   }
8085   PetscFunctionReturn(PETSC_SUCCESS);
8086 }
8087 
8088 /*@C
8089   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8090 
8091   Collective
8092 
8093   Input Parameters:
8094 + mat             - the matrix
8095 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8096 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8097                 symmetrized
8098 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8099                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8100                  always used.
8101 . n               - number of columns in the (possibly compressed) matrix
8102 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8103 - ja              - the row indices
8104 
8105   Output Parameter:
8106 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8107 
8108   Level: developer
8109 
8110 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8111 @*/
8112 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8113 {
8114   PetscFunctionBegin;
8115   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8116   PetscValidType(mat, 1);
8117   PetscAssertPointer(n, 5);
8118   if (ia) PetscAssertPointer(ia, 6);
8119   if (ja) PetscAssertPointer(ja, 7);
8120   PetscAssertPointer(done, 8);
8121   MatCheckPreallocated(mat, 1);
8122   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8123   else {
8124     *done = PETSC_TRUE;
8125     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8126   }
8127   PetscFunctionReturn(PETSC_SUCCESS);
8128 }
8129 
8130 /*@C
8131   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8132 
8133   Collective
8134 
8135   Input Parameters:
8136 + mat             - the matrix
8137 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8138 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8139 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8140                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8141                     always used.
8142 . n               - size of (possibly compressed) matrix
8143 . ia              - the row pointers
8144 - ja              - the column indices
8145 
8146   Output Parameter:
8147 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8148 
8149   Level: developer
8150 
8151   Note:
8152   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8153   us of the array after it has been restored. If you pass `NULL`, it will
8154   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8155 
8156 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8157 @*/
8158 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8159 {
8160   PetscFunctionBegin;
8161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8162   PetscValidType(mat, 1);
8163   if (ia) PetscAssertPointer(ia, 6);
8164   if (ja) PetscAssertPointer(ja, 7);
8165   if (done) PetscAssertPointer(done, 8);
8166   MatCheckPreallocated(mat, 1);
8167 
8168   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8169   else {
8170     if (done) *done = PETSC_TRUE;
8171     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8172     if (n) *n = 0;
8173     if (ia) *ia = NULL;
8174     if (ja) *ja = NULL;
8175   }
8176   PetscFunctionReturn(PETSC_SUCCESS);
8177 }
8178 
8179 /*@C
8180   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8181 
8182   Collective
8183 
8184   Input Parameters:
8185 + mat             - the matrix
8186 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8187 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8188 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8189                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8190                     always used.
8191 
8192   Output Parameters:
8193 + n    - size of (possibly compressed) matrix
8194 . ia   - the column pointers
8195 . ja   - the row indices
8196 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8197 
8198   Level: developer
8199 
8200 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8201 @*/
8202 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8203 {
8204   PetscFunctionBegin;
8205   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8206   PetscValidType(mat, 1);
8207   if (ia) PetscAssertPointer(ia, 6);
8208   if (ja) PetscAssertPointer(ja, 7);
8209   PetscAssertPointer(done, 8);
8210   MatCheckPreallocated(mat, 1);
8211 
8212   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8213   else {
8214     *done = PETSC_TRUE;
8215     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8216     if (n) *n = 0;
8217     if (ia) *ia = NULL;
8218     if (ja) *ja = NULL;
8219   }
8220   PetscFunctionReturn(PETSC_SUCCESS);
8221 }
8222 
8223 /*@
8224   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8225   `MatGetColumnIJ()`.
8226 
8227   Collective
8228 
8229   Input Parameters:
8230 + mat        - the matrix
8231 . ncolors    - maximum color value
8232 . n          - number of entries in colorarray
8233 - colorarray - array indicating color for each column
8234 
8235   Output Parameter:
8236 . iscoloring - coloring generated using colorarray information
8237 
8238   Level: developer
8239 
8240 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8241 @*/
8242 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8243 {
8244   PetscFunctionBegin;
8245   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8246   PetscValidType(mat, 1);
8247   PetscAssertPointer(colorarray, 4);
8248   PetscAssertPointer(iscoloring, 5);
8249   MatCheckPreallocated(mat, 1);
8250 
8251   if (!mat->ops->coloringpatch) {
8252     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8253   } else {
8254     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8255   }
8256   PetscFunctionReturn(PETSC_SUCCESS);
8257 }
8258 
8259 /*@
8260   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8261 
8262   Logically Collective
8263 
8264   Input Parameter:
8265 . mat - the factored matrix to be reset
8266 
8267   Level: developer
8268 
8269   Notes:
8270   This routine should be used only with factored matrices formed by in-place
8271   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8272   format).  This option can save memory, for example, when solving nonlinear
8273   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8274   ILU(0) preconditioner.
8275 
8276   One can specify in-place ILU(0) factorization by calling
8277 .vb
8278      PCType(pc,PCILU);
8279      PCFactorSeUseInPlace(pc);
8280 .ve
8281   or by using the options -pc_type ilu -pc_factor_in_place
8282 
8283   In-place factorization ILU(0) can also be used as a local
8284   solver for the blocks within the block Jacobi or additive Schwarz
8285   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8286   for details on setting local solver options.
8287 
8288   Most users should employ the `KSP` interface for linear solvers
8289   instead of working directly with matrix algebra routines such as this.
8290   See, e.g., `KSPCreate()`.
8291 
8292 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8293 @*/
8294 PetscErrorCode MatSetUnfactored(Mat mat)
8295 {
8296   PetscFunctionBegin;
8297   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8298   PetscValidType(mat, 1);
8299   MatCheckPreallocated(mat, 1);
8300   mat->factortype = MAT_FACTOR_NONE;
8301   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8302   PetscUseTypeMethod(mat, setunfactored);
8303   PetscFunctionReturn(PETSC_SUCCESS);
8304 }
8305 
8306 /*@
8307   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8308   as the original matrix.
8309 
8310   Collective
8311 
8312   Input Parameters:
8313 + mat   - the original matrix
8314 . isrow - parallel `IS` containing the rows this processor should obtain
8315 . 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.
8316 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8317 
8318   Output Parameter:
8319 . newmat - the new submatrix, of the same type as the original matrix
8320 
8321   Level: advanced
8322 
8323   Notes:
8324   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8325 
8326   Some matrix types place restrictions on the row and column indices, such
8327   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;
8328   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8329 
8330   The index sets may not have duplicate entries.
8331 
8332   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8333   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8334   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8335   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8336   you are finished using it.
8337 
8338   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8339   the input matrix.
8340 
8341   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8342 
8343   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8344   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8345 
8346   Example usage:
8347   Consider the following 8x8 matrix with 34 non-zero values, that is
8348   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8349   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8350   as follows
8351 .vb
8352             1  2  0  |  0  3  0  |  0  4
8353     Proc0   0  5  6  |  7  0  0  |  8  0
8354             9  0 10  | 11  0  0  | 12  0
8355     -------------------------------------
8356            13  0 14  | 15 16 17  |  0  0
8357     Proc1   0 18  0  | 19 20 21  |  0  0
8358             0  0  0  | 22 23  0  | 24  0
8359     -------------------------------------
8360     Proc2  25 26 27  |  0  0 28  | 29  0
8361            30  0  0  | 31 32 33  |  0 34
8362 .ve
8363 
8364   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8365 
8366 .vb
8367             2  0  |  0  3  0  |  0
8368     Proc0   5  6  |  7  0  0  |  8
8369     -------------------------------
8370     Proc1  18  0  | 19 20 21  |  0
8371     -------------------------------
8372     Proc2  26 27  |  0  0 28  | 29
8373             0  0  | 31 32 33  |  0
8374 .ve
8375 
8376 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8377 @*/
8378 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8379 {
8380   PetscMPIInt size;
8381   Mat        *local;
8382   IS          iscoltmp;
8383   PetscBool   flg;
8384 
8385   PetscFunctionBegin;
8386   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8387   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8388   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8389   PetscAssertPointer(newmat, 5);
8390   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8391   PetscValidType(mat, 1);
8392   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8393   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8394 
8395   MatCheckPreallocated(mat, 1);
8396   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8397 
8398   if (!iscol || isrow == iscol) {
8399     PetscBool   stride;
8400     PetscMPIInt grabentirematrix = 0, grab;
8401     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8402     if (stride) {
8403       PetscInt first, step, n, rstart, rend;
8404       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8405       if (step == 1) {
8406         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8407         if (rstart == first) {
8408           PetscCall(ISGetLocalSize(isrow, &n));
8409           if (n == rend - rstart) grabentirematrix = 1;
8410         }
8411       }
8412     }
8413     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8414     if (grab) {
8415       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8416       if (cll == MAT_INITIAL_MATRIX) {
8417         *newmat = mat;
8418         PetscCall(PetscObjectReference((PetscObject)mat));
8419       }
8420       PetscFunctionReturn(PETSC_SUCCESS);
8421     }
8422   }
8423 
8424   if (!iscol) {
8425     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8426   } else {
8427     iscoltmp = iscol;
8428   }
8429 
8430   /* if original matrix is on just one processor then use submatrix generated */
8431   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8432     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8433     goto setproperties;
8434   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8435     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8436     *newmat = *local;
8437     PetscCall(PetscFree(local));
8438     goto setproperties;
8439   } else if (!mat->ops->createsubmatrix) {
8440     /* Create a new matrix type that implements the operation using the full matrix */
8441     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8442     switch (cll) {
8443     case MAT_INITIAL_MATRIX:
8444       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8445       break;
8446     case MAT_REUSE_MATRIX:
8447       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8448       break;
8449     default:
8450       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8451     }
8452     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8453     goto setproperties;
8454   }
8455 
8456   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8457   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8458   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8459 
8460 setproperties:
8461   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8462     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8463     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8464   }
8465   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8466   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8467   PetscFunctionReturn(PETSC_SUCCESS);
8468 }
8469 
8470 /*@
8471   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8472 
8473   Not Collective
8474 
8475   Input Parameters:
8476 + A - the matrix we wish to propagate options from
8477 - B - the matrix we wish to propagate options to
8478 
8479   Level: beginner
8480 
8481   Note:
8482   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8483 
8484 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8485 @*/
8486 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8487 {
8488   PetscFunctionBegin;
8489   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8490   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8491   B->symmetry_eternal            = A->symmetry_eternal;
8492   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8493   B->symmetric                   = A->symmetric;
8494   B->structurally_symmetric      = A->structurally_symmetric;
8495   B->spd                         = A->spd;
8496   B->hermitian                   = A->hermitian;
8497   PetscFunctionReturn(PETSC_SUCCESS);
8498 }
8499 
8500 /*@
8501   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8502   used during the assembly process to store values that belong to
8503   other processors.
8504 
8505   Not Collective
8506 
8507   Input Parameters:
8508 + mat   - the matrix
8509 . size  - the initial size of the stash.
8510 - bsize - the initial size of the block-stash(if used).
8511 
8512   Options Database Keys:
8513 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8514 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8515 
8516   Level: intermediate
8517 
8518   Notes:
8519   The block-stash is used for values set with `MatSetValuesBlocked()` while
8520   the stash is used for values set with `MatSetValues()`
8521 
8522   Run with the option -info and look for output of the form
8523   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8524   to determine the appropriate value, MM, to use for size and
8525   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8526   to determine the value, BMM to use for bsize
8527 
8528 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8529 @*/
8530 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8531 {
8532   PetscFunctionBegin;
8533   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8534   PetscValidType(mat, 1);
8535   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8536   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8537   PetscFunctionReturn(PETSC_SUCCESS);
8538 }
8539 
8540 /*@
8541   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8542   the matrix
8543 
8544   Neighbor-wise Collective
8545 
8546   Input Parameters:
8547 + A - the matrix
8548 . x - the vector to be multiplied by the interpolation operator
8549 - y - the vector to be added to the result
8550 
8551   Output Parameter:
8552 . w - the resulting vector
8553 
8554   Level: intermediate
8555 
8556   Notes:
8557   `w` may be the same vector as `y`.
8558 
8559   This allows one to use either the restriction or interpolation (its transpose)
8560   matrix to do the interpolation
8561 
8562 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8563 @*/
8564 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8565 {
8566   PetscInt M, N, Ny;
8567 
8568   PetscFunctionBegin;
8569   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8570   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8571   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8572   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8573   PetscCall(MatGetSize(A, &M, &N));
8574   PetscCall(VecGetSize(y, &Ny));
8575   if (M == Ny) {
8576     PetscCall(MatMultAdd(A, x, y, w));
8577   } else {
8578     PetscCall(MatMultTransposeAdd(A, x, y, w));
8579   }
8580   PetscFunctionReturn(PETSC_SUCCESS);
8581 }
8582 
8583 /*@
8584   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8585   the matrix
8586 
8587   Neighbor-wise Collective
8588 
8589   Input Parameters:
8590 + A - the matrix
8591 - x - the vector to be interpolated
8592 
8593   Output Parameter:
8594 . y - the resulting vector
8595 
8596   Level: intermediate
8597 
8598   Note:
8599   This allows one to use either the restriction or interpolation (its transpose)
8600   matrix to do the interpolation
8601 
8602 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8603 @*/
8604 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8605 {
8606   PetscInt M, N, Ny;
8607 
8608   PetscFunctionBegin;
8609   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8610   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8611   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8612   PetscCall(MatGetSize(A, &M, &N));
8613   PetscCall(VecGetSize(y, &Ny));
8614   if (M == Ny) {
8615     PetscCall(MatMult(A, x, y));
8616   } else {
8617     PetscCall(MatMultTranspose(A, x, y));
8618   }
8619   PetscFunctionReturn(PETSC_SUCCESS);
8620 }
8621 
8622 /*@
8623   MatRestrict - $y = A*x$ or $A^T*x$
8624 
8625   Neighbor-wise Collective
8626 
8627   Input Parameters:
8628 + A - the matrix
8629 - x - the vector to be restricted
8630 
8631   Output Parameter:
8632 . y - the resulting vector
8633 
8634   Level: intermediate
8635 
8636   Note:
8637   This allows one to use either the restriction or interpolation (its transpose)
8638   matrix to do the restriction
8639 
8640 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8641 @*/
8642 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8643 {
8644   PetscInt M, N, Nx;
8645 
8646   PetscFunctionBegin;
8647   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8648   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8649   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8650   PetscCall(MatGetSize(A, &M, &N));
8651   PetscCall(VecGetSize(x, &Nx));
8652   if (M == Nx) {
8653     PetscCall(MatMultTranspose(A, x, y));
8654   } else {
8655     PetscCall(MatMult(A, x, y));
8656   }
8657   PetscFunctionReturn(PETSC_SUCCESS);
8658 }
8659 
8660 /*@
8661   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8662 
8663   Neighbor-wise Collective
8664 
8665   Input Parameters:
8666 + A - the matrix
8667 . x - the input dense matrix to be multiplied
8668 - w - the input dense matrix to be added to the result
8669 
8670   Output Parameter:
8671 . y - the output dense matrix
8672 
8673   Level: intermediate
8674 
8675   Note:
8676   This allows one to use either the restriction or interpolation (its transpose)
8677   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8678   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8679 
8680 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8681 @*/
8682 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8683 {
8684   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8685   PetscBool trans = PETSC_TRUE;
8686   MatReuse  reuse = MAT_INITIAL_MATRIX;
8687 
8688   PetscFunctionBegin;
8689   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8690   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8691   PetscValidType(x, 2);
8692   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8693   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8694   PetscCall(MatGetSize(A, &M, &N));
8695   PetscCall(MatGetSize(x, &Mx, &Nx));
8696   if (N == Mx) trans = PETSC_FALSE;
8697   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);
8698   Mo = trans ? N : M;
8699   if (*y) {
8700     PetscCall(MatGetSize(*y, &My, &Ny));
8701     if (Mo == My && Nx == Ny) {
8702       reuse = MAT_REUSE_MATRIX;
8703     } else {
8704       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);
8705       PetscCall(MatDestroy(y));
8706     }
8707   }
8708 
8709   if (w && *y == w) { /* this is to minimize changes in PCMG */
8710     PetscBool flg;
8711 
8712     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8713     if (w) {
8714       PetscInt My, Ny, Mw, Nw;
8715 
8716       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8717       PetscCall(MatGetSize(*y, &My, &Ny));
8718       PetscCall(MatGetSize(w, &Mw, &Nw));
8719       if (!flg || My != Mw || Ny != Nw) w = NULL;
8720     }
8721     if (!w) {
8722       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8723       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8724       PetscCall(PetscObjectDereference((PetscObject)w));
8725     } else {
8726       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8727     }
8728   }
8729   if (!trans) {
8730     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8731   } else {
8732     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8733   }
8734   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8735   PetscFunctionReturn(PETSC_SUCCESS);
8736 }
8737 
8738 /*@
8739   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8740 
8741   Neighbor-wise Collective
8742 
8743   Input Parameters:
8744 + A - the matrix
8745 - x - the input dense matrix
8746 
8747   Output Parameter:
8748 . y - the output dense matrix
8749 
8750   Level: intermediate
8751 
8752   Note:
8753   This allows one to use either the restriction or interpolation (its transpose)
8754   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8755   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8756 
8757 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8758 @*/
8759 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8760 {
8761   PetscFunctionBegin;
8762   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8763   PetscFunctionReturn(PETSC_SUCCESS);
8764 }
8765 
8766 /*@
8767   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8768 
8769   Neighbor-wise Collective
8770 
8771   Input Parameters:
8772 + A - the matrix
8773 - x - the input dense matrix
8774 
8775   Output Parameter:
8776 . y - the output dense matrix
8777 
8778   Level: intermediate
8779 
8780   Note:
8781   This allows one to use either the restriction or interpolation (its transpose)
8782   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8783   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8784 
8785 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8786 @*/
8787 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8788 {
8789   PetscFunctionBegin;
8790   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8791   PetscFunctionReturn(PETSC_SUCCESS);
8792 }
8793 
8794 /*@
8795   MatGetNullSpace - retrieves the null space of a matrix.
8796 
8797   Logically Collective
8798 
8799   Input Parameters:
8800 + mat    - the matrix
8801 - nullsp - the null space object
8802 
8803   Level: developer
8804 
8805 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8806 @*/
8807 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8808 {
8809   PetscFunctionBegin;
8810   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8811   PetscAssertPointer(nullsp, 2);
8812   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8813   PetscFunctionReturn(PETSC_SUCCESS);
8814 }
8815 
8816 /*@C
8817   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8818 
8819   Logically Collective
8820 
8821   Input Parameters:
8822 + n   - the number of matrices
8823 - mat - the array of matrices
8824 
8825   Output Parameters:
8826 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
8827 
8828   Level: developer
8829 
8830   Note:
8831   Call `MatRestoreNullspaces()` to provide these to another array of matrices
8832 
8833 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8834           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8835 @*/
8836 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8837 {
8838   PetscFunctionBegin;
8839   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8840   PetscAssertPointer(mat, 2);
8841   PetscAssertPointer(nullsp, 3);
8842 
8843   PetscCall(PetscCalloc1(3 * n, nullsp));
8844   for (PetscInt i = 0; i < n; i++) {
8845     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8846     (*nullsp)[i] = mat[i]->nullsp;
8847     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
8848     (*nullsp)[n + i] = mat[i]->nearnullsp;
8849     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
8850     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
8851     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
8852   }
8853   PetscFunctionReturn(PETSC_SUCCESS);
8854 }
8855 
8856 /*@C
8857   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
8858 
8859   Logically Collective
8860 
8861   Input Parameters:
8862 + n      - the number of matrices
8863 . mat    - the array of matrices
8864 - nullsp - an array of null spaces
8865 
8866   Level: developer
8867 
8868   Note:
8869   Call `MatGetNullSpaces()` to create `nullsp`
8870 
8871 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8872           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
8873 @*/
8874 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8875 {
8876   PetscFunctionBegin;
8877   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8878   PetscAssertPointer(mat, 2);
8879   PetscAssertPointer(nullsp, 3);
8880   PetscAssertPointer(*nullsp, 3);
8881 
8882   for (PetscInt i = 0; i < n; i++) {
8883     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8884     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
8885     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
8886     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
8887     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
8888     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
8889     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
8890   }
8891   PetscCall(PetscFree(*nullsp));
8892   PetscFunctionReturn(PETSC_SUCCESS);
8893 }
8894 
8895 /*@
8896   MatSetNullSpace - attaches a null space to a matrix.
8897 
8898   Logically Collective
8899 
8900   Input Parameters:
8901 + mat    - the matrix
8902 - nullsp - the null space object
8903 
8904   Level: advanced
8905 
8906   Notes:
8907   This null space is used by the `KSP` linear solvers to solve singular systems.
8908 
8909   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`
8910 
8911   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
8912   to zero but the linear system will still be solved in a least squares sense.
8913 
8914   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8915   the domain of a matrix $A$ (from $R^n$ to $R^m$ ($m$ rows, $n$ columns) $R^n$ = the direct sum of the null space of $A$, $n(A)$, plus the range of $A^T$, $R(A^T)$.
8916   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
8917   $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
8918   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)$.
8919   This  $\hat{b}$ can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8920 
8921   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one has called
8922   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8923   routine also automatically calls `MatSetTransposeNullSpace()`.
8924 
8925   The user should call `MatNullSpaceDestroy()`.
8926 
8927 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8928           `KSPSetPCSide()`
8929 @*/
8930 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8931 {
8932   PetscFunctionBegin;
8933   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8934   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8935   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8936   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8937   mat->nullsp = nullsp;
8938   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8939   PetscFunctionReturn(PETSC_SUCCESS);
8940 }
8941 
8942 /*@
8943   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8944 
8945   Logically Collective
8946 
8947   Input Parameters:
8948 + mat    - the matrix
8949 - nullsp - the null space object
8950 
8951   Level: developer
8952 
8953 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8954 @*/
8955 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8956 {
8957   PetscFunctionBegin;
8958   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8959   PetscValidType(mat, 1);
8960   PetscAssertPointer(nullsp, 2);
8961   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8962   PetscFunctionReturn(PETSC_SUCCESS);
8963 }
8964 
8965 /*@
8966   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8967 
8968   Logically Collective
8969 
8970   Input Parameters:
8971 + mat    - the matrix
8972 - nullsp - the null space object
8973 
8974   Level: advanced
8975 
8976   Notes:
8977   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8978 
8979   See `MatSetNullSpace()`
8980 
8981 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8982 @*/
8983 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8984 {
8985   PetscFunctionBegin;
8986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8987   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8988   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8989   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8990   mat->transnullsp = nullsp;
8991   PetscFunctionReturn(PETSC_SUCCESS);
8992 }
8993 
8994 /*@
8995   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8996   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8997 
8998   Logically Collective
8999 
9000   Input Parameters:
9001 + mat    - the matrix
9002 - nullsp - the null space object
9003 
9004   Level: advanced
9005 
9006   Notes:
9007   Overwrites any previous near null space that may have been attached
9008 
9009   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9010 
9011 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9012 @*/
9013 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9014 {
9015   PetscFunctionBegin;
9016   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9017   PetscValidType(mat, 1);
9018   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9019   MatCheckPreallocated(mat, 1);
9020   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9021   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9022   mat->nearnullsp = nullsp;
9023   PetscFunctionReturn(PETSC_SUCCESS);
9024 }
9025 
9026 /*@
9027   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9028 
9029   Not Collective
9030 
9031   Input Parameter:
9032 . mat - the matrix
9033 
9034   Output Parameter:
9035 . nullsp - the null space object, `NULL` if not set
9036 
9037   Level: advanced
9038 
9039 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9040 @*/
9041 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9042 {
9043   PetscFunctionBegin;
9044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9045   PetscValidType(mat, 1);
9046   PetscAssertPointer(nullsp, 2);
9047   MatCheckPreallocated(mat, 1);
9048   *nullsp = mat->nearnullsp;
9049   PetscFunctionReturn(PETSC_SUCCESS);
9050 }
9051 
9052 /*@
9053   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9054 
9055   Collective
9056 
9057   Input Parameters:
9058 + mat  - the matrix
9059 . row  - row/column permutation
9060 - info - information on desired factorization process
9061 
9062   Level: developer
9063 
9064   Notes:
9065   Probably really in-place only when level of fill is zero, otherwise allocates
9066   new space to store factored matrix and deletes previous memory.
9067 
9068   Most users should employ the `KSP` interface for linear solvers
9069   instead of working directly with matrix algebra routines such as this.
9070   See, e.g., `KSPCreate()`.
9071 
9072   Fortran Note:
9073   A valid (non-null) `info` argument must be provided
9074 
9075 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9076 @*/
9077 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9078 {
9079   PetscFunctionBegin;
9080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9081   PetscValidType(mat, 1);
9082   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9083   PetscAssertPointer(info, 3);
9084   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9085   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9086   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9087   MatCheckPreallocated(mat, 1);
9088   PetscUseTypeMethod(mat, iccfactor, row, info);
9089   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9090   PetscFunctionReturn(PETSC_SUCCESS);
9091 }
9092 
9093 /*@
9094   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9095   ghosted ones.
9096 
9097   Not Collective
9098 
9099   Input Parameters:
9100 + mat  - the matrix
9101 - diag - the diagonal values, including ghost ones
9102 
9103   Level: developer
9104 
9105   Notes:
9106   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9107 
9108   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9109 
9110 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9111 @*/
9112 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9113 {
9114   PetscMPIInt size;
9115 
9116   PetscFunctionBegin;
9117   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9118   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9119   PetscValidType(mat, 1);
9120 
9121   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9122   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9123   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9124   if (size == 1) {
9125     PetscInt n, m;
9126     PetscCall(VecGetSize(diag, &n));
9127     PetscCall(MatGetSize(mat, NULL, &m));
9128     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9129     PetscCall(MatDiagonalScale(mat, NULL, diag));
9130   } else {
9131     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9132   }
9133   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9134   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9135   PetscFunctionReturn(PETSC_SUCCESS);
9136 }
9137 
9138 /*@
9139   MatGetInertia - Gets the inertia from a factored matrix
9140 
9141   Collective
9142 
9143   Input Parameter:
9144 . mat - the matrix
9145 
9146   Output Parameters:
9147 + nneg  - number of negative eigenvalues
9148 . nzero - number of zero eigenvalues
9149 - npos  - number of positive eigenvalues
9150 
9151   Level: advanced
9152 
9153   Note:
9154   Matrix must have been factored by `MatCholeskyFactor()`
9155 
9156 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9157 @*/
9158 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9159 {
9160   PetscFunctionBegin;
9161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9162   PetscValidType(mat, 1);
9163   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9164   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9165   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9166   PetscFunctionReturn(PETSC_SUCCESS);
9167 }
9168 
9169 /*@C
9170   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9171 
9172   Neighbor-wise Collective
9173 
9174   Input Parameters:
9175 + mat - the factored matrix obtained with `MatGetFactor()`
9176 - b   - the right-hand-side vectors
9177 
9178   Output Parameter:
9179 . x - the result vectors
9180 
9181   Level: developer
9182 
9183   Note:
9184   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9185   call `MatSolves`(A,x,x).
9186 
9187 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9188 @*/
9189 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9190 {
9191   PetscFunctionBegin;
9192   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9193   PetscValidType(mat, 1);
9194   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9195   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9196   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9197 
9198   MatCheckPreallocated(mat, 1);
9199   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9200   PetscUseTypeMethod(mat, solves, b, x);
9201   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9202   PetscFunctionReturn(PETSC_SUCCESS);
9203 }
9204 
9205 /*@
9206   MatIsSymmetric - Test whether a matrix is symmetric
9207 
9208   Collective
9209 
9210   Input Parameters:
9211 + A   - the matrix to test
9212 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9213 
9214   Output Parameter:
9215 . flg - the result
9216 
9217   Level: intermediate
9218 
9219   Notes:
9220   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9221 
9222   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9223 
9224   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9225   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9226 
9227 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9228           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9229 @*/
9230 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9231 {
9232   PetscFunctionBegin;
9233   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9234   PetscAssertPointer(flg, 3);
9235   if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9236   else {
9237     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9238     else PetscCall(MatIsTranspose(A, A, tol, flg));
9239     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9240   }
9241   PetscFunctionReturn(PETSC_SUCCESS);
9242 }
9243 
9244 /*@
9245   MatIsHermitian - Test whether a matrix is Hermitian
9246 
9247   Collective
9248 
9249   Input Parameters:
9250 + A   - the matrix to test
9251 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9252 
9253   Output Parameter:
9254 . flg - the result
9255 
9256   Level: intermediate
9257 
9258   Notes:
9259   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9260 
9261   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9262 
9263   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9264   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9265 
9266 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9267           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9268 @*/
9269 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9270 {
9271   PetscFunctionBegin;
9272   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9273   PetscAssertPointer(flg, 3);
9274   if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9275   else {
9276     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9277     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9278     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9279   }
9280   PetscFunctionReturn(PETSC_SUCCESS);
9281 }
9282 
9283 /*@
9284   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9285 
9286   Not Collective
9287 
9288   Input Parameter:
9289 . A - the matrix to check
9290 
9291   Output Parameters:
9292 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9293 - flg - the result (only valid if set is `PETSC_TRUE`)
9294 
9295   Level: advanced
9296 
9297   Notes:
9298   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9299   if you want it explicitly checked
9300 
9301   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9302   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9303 
9304 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9305 @*/
9306 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9307 {
9308   PetscFunctionBegin;
9309   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9310   PetscAssertPointer(set, 2);
9311   PetscAssertPointer(flg, 3);
9312   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9313     *set = PETSC_TRUE;
9314     *flg = PetscBool3ToBool(A->symmetric);
9315   } else {
9316     *set = PETSC_FALSE;
9317   }
9318   PetscFunctionReturn(PETSC_SUCCESS);
9319 }
9320 
9321 /*@
9322   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9323 
9324   Not Collective
9325 
9326   Input Parameter:
9327 . A - the matrix to check
9328 
9329   Output Parameters:
9330 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9331 - flg - the result (only valid if set is `PETSC_TRUE`)
9332 
9333   Level: advanced
9334 
9335   Notes:
9336   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9337 
9338   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9339   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9340 
9341 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9342 @*/
9343 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9344 {
9345   PetscFunctionBegin;
9346   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9347   PetscAssertPointer(set, 2);
9348   PetscAssertPointer(flg, 3);
9349   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9350     *set = PETSC_TRUE;
9351     *flg = PetscBool3ToBool(A->spd);
9352   } else {
9353     *set = PETSC_FALSE;
9354   }
9355   PetscFunctionReturn(PETSC_SUCCESS);
9356 }
9357 
9358 /*@
9359   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9360 
9361   Not Collective
9362 
9363   Input Parameter:
9364 . A - the matrix to check
9365 
9366   Output Parameters:
9367 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9368 - flg - the result (only valid if set is `PETSC_TRUE`)
9369 
9370   Level: advanced
9371 
9372   Notes:
9373   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9374   if you want it explicitly checked
9375 
9376   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9377   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9378 
9379 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9380 @*/
9381 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9382 {
9383   PetscFunctionBegin;
9384   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9385   PetscAssertPointer(set, 2);
9386   PetscAssertPointer(flg, 3);
9387   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9388     *set = PETSC_TRUE;
9389     *flg = PetscBool3ToBool(A->hermitian);
9390   } else {
9391     *set = PETSC_FALSE;
9392   }
9393   PetscFunctionReturn(PETSC_SUCCESS);
9394 }
9395 
9396 /*@
9397   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9398 
9399   Collective
9400 
9401   Input Parameter:
9402 . A - the matrix to test
9403 
9404   Output Parameter:
9405 . flg - the result
9406 
9407   Level: intermediate
9408 
9409   Notes:
9410   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9411 
9412   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
9413   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9414 
9415 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9416 @*/
9417 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9418 {
9419   PetscFunctionBegin;
9420   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9421   PetscAssertPointer(flg, 2);
9422   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9423     *flg = PetscBool3ToBool(A->structurally_symmetric);
9424   } else {
9425     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9426     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9427   }
9428   PetscFunctionReturn(PETSC_SUCCESS);
9429 }
9430 
9431 /*@
9432   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9433 
9434   Not Collective
9435 
9436   Input Parameter:
9437 . A - the matrix to check
9438 
9439   Output Parameters:
9440 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9441 - flg - the result (only valid if set is PETSC_TRUE)
9442 
9443   Level: advanced
9444 
9445   Notes:
9446   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
9447   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9448 
9449   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9450 
9451 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9452 @*/
9453 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9454 {
9455   PetscFunctionBegin;
9456   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9457   PetscAssertPointer(set, 2);
9458   PetscAssertPointer(flg, 3);
9459   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9460     *set = PETSC_TRUE;
9461     *flg = PetscBool3ToBool(A->structurally_symmetric);
9462   } else {
9463     *set = PETSC_FALSE;
9464   }
9465   PetscFunctionReturn(PETSC_SUCCESS);
9466 }
9467 
9468 /*@
9469   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9470   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9471 
9472   Not Collective
9473 
9474   Input Parameter:
9475 . mat - the matrix
9476 
9477   Output Parameters:
9478 + nstash    - the size of the stash
9479 . reallocs  - the number of additional mallocs incurred.
9480 . bnstash   - the size of the block stash
9481 - breallocs - the number of additional mallocs incurred.in the block stash
9482 
9483   Level: advanced
9484 
9485 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9486 @*/
9487 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9488 {
9489   PetscFunctionBegin;
9490   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9491   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9492   PetscFunctionReturn(PETSC_SUCCESS);
9493 }
9494 
9495 /*@
9496   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9497   parallel layout, `PetscLayout` for rows and columns
9498 
9499   Collective
9500 
9501   Input Parameter:
9502 . mat - the matrix
9503 
9504   Output Parameters:
9505 + right - (optional) vector that the matrix can be multiplied against
9506 - left  - (optional) vector that the matrix vector product can be stored in
9507 
9508   Level: advanced
9509 
9510   Notes:
9511   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()`.
9512 
9513   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9514 
9515 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9516 @*/
9517 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9518 {
9519   PetscFunctionBegin;
9520   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9521   PetscValidType(mat, 1);
9522   if (mat->ops->getvecs) {
9523     PetscUseTypeMethod(mat, getvecs, right, left);
9524   } else {
9525     if (right) {
9526       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9527       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9528       PetscCall(VecSetType(*right, mat->defaultvectype));
9529 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9530       if (mat->boundtocpu && mat->bindingpropagates) {
9531         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9532         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9533       }
9534 #endif
9535     }
9536     if (left) {
9537       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9538       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9539       PetscCall(VecSetType(*left, mat->defaultvectype));
9540 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9541       if (mat->boundtocpu && mat->bindingpropagates) {
9542         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9543         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9544       }
9545 #endif
9546     }
9547   }
9548   PetscFunctionReturn(PETSC_SUCCESS);
9549 }
9550 
9551 /*@
9552   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9553   with default values.
9554 
9555   Not Collective
9556 
9557   Input Parameter:
9558 . info - the `MatFactorInfo` data structure
9559 
9560   Level: developer
9561 
9562   Notes:
9563   The solvers are generally used through the `KSP` and `PC` objects, for example
9564   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9565 
9566   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9567 
9568 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9569 @*/
9570 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9571 {
9572   PetscFunctionBegin;
9573   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9574   PetscFunctionReturn(PETSC_SUCCESS);
9575 }
9576 
9577 /*@
9578   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9579 
9580   Collective
9581 
9582   Input Parameters:
9583 + mat - the factored matrix
9584 - is  - the index set defining the Schur indices (0-based)
9585 
9586   Level: advanced
9587 
9588   Notes:
9589   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9590 
9591   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9592 
9593   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9594 
9595 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9596           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9597 @*/
9598 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9599 {
9600   PetscErrorCode (*f)(Mat, IS);
9601 
9602   PetscFunctionBegin;
9603   PetscValidType(mat, 1);
9604   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9605   PetscValidType(is, 2);
9606   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9607   PetscCheckSameComm(mat, 1, is, 2);
9608   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9609   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9610   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9611   PetscCall(MatDestroy(&mat->schur));
9612   PetscCall((*f)(mat, is));
9613   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9614   PetscFunctionReturn(PETSC_SUCCESS);
9615 }
9616 
9617 /*@
9618   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9619 
9620   Logically Collective
9621 
9622   Input Parameters:
9623 + F      - the factored matrix obtained by calling `MatGetFactor()`
9624 . S      - location where to return the Schur complement, can be `NULL`
9625 - status - the status of the Schur complement matrix, can be `NULL`
9626 
9627   Level: advanced
9628 
9629   Notes:
9630   You must call `MatFactorSetSchurIS()` before calling this routine.
9631 
9632   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9633 
9634   The routine provides a copy of the Schur matrix stored within the solver data structures.
9635   The caller must destroy the object when it is no longer needed.
9636   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9637 
9638   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)
9639 
9640   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9641 
9642   Developer Note:
9643   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9644   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9645 
9646 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9647 @*/
9648 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9649 {
9650   PetscFunctionBegin;
9651   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9652   if (S) PetscAssertPointer(S, 2);
9653   if (status) PetscAssertPointer(status, 3);
9654   if (S) {
9655     PetscErrorCode (*f)(Mat, Mat *);
9656 
9657     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9658     if (f) {
9659       PetscCall((*f)(F, S));
9660     } else {
9661       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9662     }
9663   }
9664   if (status) *status = F->schur_status;
9665   PetscFunctionReturn(PETSC_SUCCESS);
9666 }
9667 
9668 /*@
9669   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9670 
9671   Logically Collective
9672 
9673   Input Parameters:
9674 + F      - the factored matrix obtained by calling `MatGetFactor()`
9675 . S      - location where to return the Schur complement, can be `NULL`
9676 - status - the status of the Schur complement matrix, can be `NULL`
9677 
9678   Level: advanced
9679 
9680   Notes:
9681   You must call `MatFactorSetSchurIS()` before calling this routine.
9682 
9683   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9684 
9685   The routine returns a the Schur Complement stored within the data structures of the solver.
9686 
9687   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9688 
9689   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9690 
9691   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9692 
9693   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9694 
9695 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9696 @*/
9697 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9698 {
9699   PetscFunctionBegin;
9700   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9701   if (S) {
9702     PetscAssertPointer(S, 2);
9703     *S = F->schur;
9704   }
9705   if (status) {
9706     PetscAssertPointer(status, 3);
9707     *status = F->schur_status;
9708   }
9709   PetscFunctionReturn(PETSC_SUCCESS);
9710 }
9711 
9712 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9713 {
9714   Mat S = F->schur;
9715 
9716   PetscFunctionBegin;
9717   switch (F->schur_status) {
9718   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9719   case MAT_FACTOR_SCHUR_INVERTED:
9720     if (S) {
9721       S->ops->solve             = NULL;
9722       S->ops->matsolve          = NULL;
9723       S->ops->solvetranspose    = NULL;
9724       S->ops->matsolvetranspose = NULL;
9725       S->ops->solveadd          = NULL;
9726       S->ops->solvetransposeadd = NULL;
9727       S->factortype             = MAT_FACTOR_NONE;
9728       PetscCall(PetscFree(S->solvertype));
9729     }
9730   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9731     break;
9732   default:
9733     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9734   }
9735   PetscFunctionReturn(PETSC_SUCCESS);
9736 }
9737 
9738 /*@
9739   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9740 
9741   Logically Collective
9742 
9743   Input Parameters:
9744 + F      - the factored matrix obtained by calling `MatGetFactor()`
9745 . S      - location where the Schur complement is stored
9746 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9747 
9748   Level: advanced
9749 
9750 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9751 @*/
9752 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9753 {
9754   PetscFunctionBegin;
9755   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9756   if (S) {
9757     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9758     *S = NULL;
9759   }
9760   F->schur_status = status;
9761   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9762   PetscFunctionReturn(PETSC_SUCCESS);
9763 }
9764 
9765 /*@
9766   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9767 
9768   Logically Collective
9769 
9770   Input Parameters:
9771 + F   - the factored matrix obtained by calling `MatGetFactor()`
9772 . rhs - location where the right-hand side of the Schur complement system is stored
9773 - sol - location where the solution of the Schur complement system has to be returned
9774 
9775   Level: advanced
9776 
9777   Notes:
9778   The sizes of the vectors should match the size of the Schur complement
9779 
9780   Must be called after `MatFactorSetSchurIS()`
9781 
9782 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9783 @*/
9784 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9785 {
9786   PetscFunctionBegin;
9787   PetscValidType(F, 1);
9788   PetscValidType(rhs, 2);
9789   PetscValidType(sol, 3);
9790   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9791   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9792   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9793   PetscCheckSameComm(F, 1, rhs, 2);
9794   PetscCheckSameComm(F, 1, sol, 3);
9795   PetscCall(MatFactorFactorizeSchurComplement(F));
9796   switch (F->schur_status) {
9797   case MAT_FACTOR_SCHUR_FACTORED:
9798     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9799     break;
9800   case MAT_FACTOR_SCHUR_INVERTED:
9801     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9802     break;
9803   default:
9804     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9805   }
9806   PetscFunctionReturn(PETSC_SUCCESS);
9807 }
9808 
9809 /*@
9810   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9811 
9812   Logically Collective
9813 
9814   Input Parameters:
9815 + F   - the factored matrix obtained by calling `MatGetFactor()`
9816 . rhs - location where the right-hand side of the Schur complement system is stored
9817 - sol - location where the solution of the Schur complement system has to be returned
9818 
9819   Level: advanced
9820 
9821   Notes:
9822   The sizes of the vectors should match the size of the Schur complement
9823 
9824   Must be called after `MatFactorSetSchurIS()`
9825 
9826 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9827 @*/
9828 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9829 {
9830   PetscFunctionBegin;
9831   PetscValidType(F, 1);
9832   PetscValidType(rhs, 2);
9833   PetscValidType(sol, 3);
9834   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9835   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9836   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9837   PetscCheckSameComm(F, 1, rhs, 2);
9838   PetscCheckSameComm(F, 1, sol, 3);
9839   PetscCall(MatFactorFactorizeSchurComplement(F));
9840   switch (F->schur_status) {
9841   case MAT_FACTOR_SCHUR_FACTORED:
9842     PetscCall(MatSolve(F->schur, rhs, sol));
9843     break;
9844   case MAT_FACTOR_SCHUR_INVERTED:
9845     PetscCall(MatMult(F->schur, rhs, sol));
9846     break;
9847   default:
9848     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9849   }
9850   PetscFunctionReturn(PETSC_SUCCESS);
9851 }
9852 
9853 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9854 #if PetscDefined(HAVE_CUDA)
9855 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9856 #endif
9857 
9858 /* Schur status updated in the interface */
9859 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9860 {
9861   Mat S = F->schur;
9862 
9863   PetscFunctionBegin;
9864   if (S) {
9865     PetscMPIInt size;
9866     PetscBool   isdense, isdensecuda;
9867 
9868     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9869     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9870     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9871     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9872     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9873     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9874     if (isdense) {
9875       PetscCall(MatSeqDenseInvertFactors_Private(S));
9876     } else if (isdensecuda) {
9877 #if defined(PETSC_HAVE_CUDA)
9878       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9879 #endif
9880     }
9881     // HIP??????????????
9882     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9883   }
9884   PetscFunctionReturn(PETSC_SUCCESS);
9885 }
9886 
9887 /*@
9888   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9889 
9890   Logically Collective
9891 
9892   Input Parameter:
9893 . F - the factored matrix obtained by calling `MatGetFactor()`
9894 
9895   Level: advanced
9896 
9897   Notes:
9898   Must be called after `MatFactorSetSchurIS()`.
9899 
9900   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9901 
9902 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9903 @*/
9904 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9905 {
9906   PetscFunctionBegin;
9907   PetscValidType(F, 1);
9908   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9909   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9910   PetscCall(MatFactorFactorizeSchurComplement(F));
9911   PetscCall(MatFactorInvertSchurComplement_Private(F));
9912   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9913   PetscFunctionReturn(PETSC_SUCCESS);
9914 }
9915 
9916 /*@
9917   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9918 
9919   Logically Collective
9920 
9921   Input Parameter:
9922 . F - the factored matrix obtained by calling `MatGetFactor()`
9923 
9924   Level: advanced
9925 
9926   Note:
9927   Must be called after `MatFactorSetSchurIS()`
9928 
9929 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9930 @*/
9931 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9932 {
9933   MatFactorInfo info;
9934 
9935   PetscFunctionBegin;
9936   PetscValidType(F, 1);
9937   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9938   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9939   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9940   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9941   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9942     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9943   } else {
9944     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9945   }
9946   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9947   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9948   PetscFunctionReturn(PETSC_SUCCESS);
9949 }
9950 
9951 /*@
9952   MatPtAP - Creates the matrix product $C = P^T * A * P$
9953 
9954   Neighbor-wise Collective
9955 
9956   Input Parameters:
9957 + A     - the matrix
9958 . P     - the projection matrix
9959 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9960 - 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
9961           if the result is a dense matrix this is irrelevant
9962 
9963   Output Parameter:
9964 . C - the product matrix
9965 
9966   Level: intermediate
9967 
9968   Notes:
9969   C will be created and must be destroyed by the user with `MatDestroy()`.
9970 
9971   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9972 
9973   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
9974 
9975   Developer Note:
9976   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9977 
9978 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9979 @*/
9980 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9981 {
9982   PetscFunctionBegin;
9983   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9984   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9985 
9986   if (scall == MAT_INITIAL_MATRIX) {
9987     PetscCall(MatProductCreate(A, P, NULL, C));
9988     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9989     PetscCall(MatProductSetAlgorithm(*C, "default"));
9990     PetscCall(MatProductSetFill(*C, fill));
9991 
9992     (*C)->product->api_user = PETSC_TRUE;
9993     PetscCall(MatProductSetFromOptions(*C));
9994     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);
9995     PetscCall(MatProductSymbolic(*C));
9996   } else { /* scall == MAT_REUSE_MATRIX */
9997     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9998   }
9999 
10000   PetscCall(MatProductNumeric(*C));
10001   (*C)->symmetric = A->symmetric;
10002   (*C)->spd       = A->spd;
10003   PetscFunctionReturn(PETSC_SUCCESS);
10004 }
10005 
10006 /*@
10007   MatRARt - Creates the matrix product $C = R * A * R^T$
10008 
10009   Neighbor-wise Collective
10010 
10011   Input Parameters:
10012 + A     - the matrix
10013 . R     - the projection matrix
10014 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10015 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10016           if the result is a dense matrix this is irrelevant
10017 
10018   Output Parameter:
10019 . C - the product matrix
10020 
10021   Level: intermediate
10022 
10023   Notes:
10024   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10025 
10026   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10027 
10028   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10029   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10030   the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10031   We recommend using `MatPtAP()` when possible.
10032 
10033   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10034 
10035 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10036 @*/
10037 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10038 {
10039   PetscFunctionBegin;
10040   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10041   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10042 
10043   if (scall == MAT_INITIAL_MATRIX) {
10044     PetscCall(MatProductCreate(A, R, NULL, C));
10045     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10046     PetscCall(MatProductSetAlgorithm(*C, "default"));
10047     PetscCall(MatProductSetFill(*C, fill));
10048 
10049     (*C)->product->api_user = PETSC_TRUE;
10050     PetscCall(MatProductSetFromOptions(*C));
10051     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);
10052     PetscCall(MatProductSymbolic(*C));
10053   } else { /* scall == MAT_REUSE_MATRIX */
10054     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10055   }
10056 
10057   PetscCall(MatProductNumeric(*C));
10058   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10059   PetscFunctionReturn(PETSC_SUCCESS);
10060 }
10061 
10062 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10063 {
10064   PetscBool flg = PETSC_TRUE;
10065 
10066   PetscFunctionBegin;
10067   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10068   if (scall == MAT_INITIAL_MATRIX) {
10069     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10070     PetscCall(MatProductCreate(A, B, NULL, C));
10071     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10072     PetscCall(MatProductSetFill(*C, fill));
10073   } else { /* scall == MAT_REUSE_MATRIX */
10074     Mat_Product *product = (*C)->product;
10075 
10076     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10077     if (flg && product && product->type != ptype) {
10078       PetscCall(MatProductClear(*C));
10079       product = NULL;
10080     }
10081     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10082     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10083       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10084       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10085       product        = (*C)->product;
10086       product->fill  = fill;
10087       product->clear = PETSC_TRUE;
10088     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10089       flg = PETSC_FALSE;
10090       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10091     }
10092   }
10093   if (flg) {
10094     (*C)->product->api_user = PETSC_TRUE;
10095     PetscCall(MatProductSetType(*C, ptype));
10096     PetscCall(MatProductSetFromOptions(*C));
10097     PetscCall(MatProductSymbolic(*C));
10098   }
10099   PetscCall(MatProductNumeric(*C));
10100   PetscFunctionReturn(PETSC_SUCCESS);
10101 }
10102 
10103 /*@
10104   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10105 
10106   Neighbor-wise Collective
10107 
10108   Input Parameters:
10109 + A     - the left matrix
10110 . B     - the right matrix
10111 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10112 - 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
10113           if the result is a dense matrix this is irrelevant
10114 
10115   Output Parameter:
10116 . C - the product matrix
10117 
10118   Notes:
10119   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10120 
10121   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call and C was obtained from a previous
10122   call to this function with `MAT_INITIAL_MATRIX`.
10123 
10124   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10125 
10126   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`,
10127   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10128 
10129   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10130 
10131   Example of Usage:
10132 .vb
10133      MatProductCreate(A,B,NULL,&C);
10134      MatProductSetType(C,MATPRODUCT_AB);
10135      MatProductSymbolic(C);
10136      MatProductNumeric(C); // compute C=A * B
10137      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10138      MatProductNumeric(C);
10139      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10140      MatProductNumeric(C);
10141 .ve
10142 
10143   Level: intermediate
10144 
10145 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10146 @*/
10147 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10148 {
10149   PetscFunctionBegin;
10150   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10151   PetscFunctionReturn(PETSC_SUCCESS);
10152 }
10153 
10154 /*@
10155   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10156 
10157   Neighbor-wise Collective
10158 
10159   Input Parameters:
10160 + A     - the left matrix
10161 . B     - the right matrix
10162 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10163 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10164 
10165   Output Parameter:
10166 . C - the product matrix
10167 
10168   Options Database Key:
10169 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10170               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10171               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10172 
10173   Level: intermediate
10174 
10175   Notes:
10176   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10177 
10178   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10179 
10180   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10181   actually needed.
10182 
10183   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10184   and for pairs of `MATMPIDENSE` matrices.
10185 
10186   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10187 
10188   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10189 
10190 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10191 @*/
10192 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10193 {
10194   PetscFunctionBegin;
10195   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10196   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10197   PetscFunctionReturn(PETSC_SUCCESS);
10198 }
10199 
10200 /*@
10201   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10202 
10203   Neighbor-wise Collective
10204 
10205   Input Parameters:
10206 + A     - the left matrix
10207 . B     - the right matrix
10208 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10209 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10210 
10211   Output Parameter:
10212 . C - the product matrix
10213 
10214   Level: intermediate
10215 
10216   Notes:
10217   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10218 
10219   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10220 
10221   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10222 
10223   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10224   actually needed.
10225 
10226   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10227   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10228 
10229   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10230 
10231 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10232 @*/
10233 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10234 {
10235   PetscFunctionBegin;
10236   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10237   PetscFunctionReturn(PETSC_SUCCESS);
10238 }
10239 
10240 /*@
10241   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10242 
10243   Neighbor-wise Collective
10244 
10245   Input Parameters:
10246 + A     - the left matrix
10247 . B     - the middle matrix
10248 . C     - the right matrix
10249 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10250 - 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
10251           if the result is a dense matrix this is irrelevant
10252 
10253   Output Parameter:
10254 . D - the product matrix
10255 
10256   Level: intermediate
10257 
10258   Notes:
10259   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10260 
10261   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10262 
10263   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10264 
10265   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10266   actually needed.
10267 
10268   If you have many matrices with the same non-zero structure to multiply, you
10269   should use `MAT_REUSE_MATRIX` in all calls but the first
10270 
10271   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10272 
10273 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10274 @*/
10275 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10276 {
10277   PetscFunctionBegin;
10278   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10279   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10280 
10281   if (scall == MAT_INITIAL_MATRIX) {
10282     PetscCall(MatProductCreate(A, B, C, D));
10283     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10284     PetscCall(MatProductSetAlgorithm(*D, "default"));
10285     PetscCall(MatProductSetFill(*D, fill));
10286 
10287     (*D)->product->api_user = PETSC_TRUE;
10288     PetscCall(MatProductSetFromOptions(*D));
10289     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,
10290                ((PetscObject)C)->type_name);
10291     PetscCall(MatProductSymbolic(*D));
10292   } else { /* user may change input matrices when REUSE */
10293     PetscCall(MatProductReplaceMats(A, B, C, *D));
10294   }
10295   PetscCall(MatProductNumeric(*D));
10296   PetscFunctionReturn(PETSC_SUCCESS);
10297 }
10298 
10299 /*@
10300   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10301 
10302   Collective
10303 
10304   Input Parameters:
10305 + mat      - the matrix
10306 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10307 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10308 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10309 
10310   Output Parameter:
10311 . matredundant - redundant matrix
10312 
10313   Level: advanced
10314 
10315   Notes:
10316   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10317   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10318 
10319   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10320   calling it.
10321 
10322   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10323 
10324 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10325 @*/
10326 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10327 {
10328   MPI_Comm       comm;
10329   PetscMPIInt    size;
10330   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10331   Mat_Redundant *redund     = NULL;
10332   PetscSubcomm   psubcomm   = NULL;
10333   MPI_Comm       subcomm_in = subcomm;
10334   Mat           *matseq;
10335   IS             isrow, iscol;
10336   PetscBool      newsubcomm = PETSC_FALSE;
10337 
10338   PetscFunctionBegin;
10339   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10340   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10341     PetscAssertPointer(*matredundant, 5);
10342     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10343   }
10344 
10345   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10346   if (size == 1 || nsubcomm == 1) {
10347     if (reuse == MAT_INITIAL_MATRIX) {
10348       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10349     } else {
10350       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");
10351       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10352     }
10353     PetscFunctionReturn(PETSC_SUCCESS);
10354   }
10355 
10356   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10357   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10358   MatCheckPreallocated(mat, 1);
10359 
10360   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10361   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10362     /* create psubcomm, then get subcomm */
10363     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10364     PetscCallMPI(MPI_Comm_size(comm, &size));
10365     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10366 
10367     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10368     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10369     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10370     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10371     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10372     newsubcomm = PETSC_TRUE;
10373     PetscCall(PetscSubcommDestroy(&psubcomm));
10374   }
10375 
10376   /* get isrow, iscol and a local sequential matrix matseq[0] */
10377   if (reuse == MAT_INITIAL_MATRIX) {
10378     mloc_sub = PETSC_DECIDE;
10379     nloc_sub = PETSC_DECIDE;
10380     if (bs < 1) {
10381       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10382       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10383     } else {
10384       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10385       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10386     }
10387     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10388     rstart = rend - mloc_sub;
10389     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10390     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10391     PetscCall(ISSetIdentity(iscol));
10392   } else { /* reuse == MAT_REUSE_MATRIX */
10393     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");
10394     /* retrieve subcomm */
10395     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10396     redund = (*matredundant)->redundant;
10397     isrow  = redund->isrow;
10398     iscol  = redund->iscol;
10399     matseq = redund->matseq;
10400   }
10401   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10402 
10403   /* get matredundant over subcomm */
10404   if (reuse == MAT_INITIAL_MATRIX) {
10405     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10406 
10407     /* create a supporting struct and attach it to C for reuse */
10408     PetscCall(PetscNew(&redund));
10409     (*matredundant)->redundant = redund;
10410     redund->isrow              = isrow;
10411     redund->iscol              = iscol;
10412     redund->matseq             = matseq;
10413     if (newsubcomm) {
10414       redund->subcomm = subcomm;
10415     } else {
10416       redund->subcomm = MPI_COMM_NULL;
10417     }
10418   } else {
10419     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10420   }
10421 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10422   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10423     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10424     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10425   }
10426 #endif
10427   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10428   PetscFunctionReturn(PETSC_SUCCESS);
10429 }
10430 
10431 /*@C
10432   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10433   a given `Mat`. Each submatrix can span multiple procs.
10434 
10435   Collective
10436 
10437   Input Parameters:
10438 + mat     - the matrix
10439 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10440 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10441 
10442   Output Parameter:
10443 . subMat - parallel sub-matrices each spanning a given `subcomm`
10444 
10445   Level: advanced
10446 
10447   Notes:
10448   The submatrix partition across processors is dictated by `subComm` a
10449   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10450   is not restricted to be grouped with consecutive original MPI processes.
10451 
10452   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10453   map directly to the layout of the original matrix [wrt the local
10454   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10455   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10456   the `subMat`. However the offDiagMat looses some columns - and this is
10457   reconstructed with `MatSetValues()`
10458 
10459   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10460 
10461 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10462 @*/
10463 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10464 {
10465   PetscMPIInt commsize, subCommSize;
10466 
10467   PetscFunctionBegin;
10468   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10469   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10470   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10471 
10472   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");
10473   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10474   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10475   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10476   PetscFunctionReturn(PETSC_SUCCESS);
10477 }
10478 
10479 /*@
10480   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10481 
10482   Not Collective
10483 
10484   Input Parameters:
10485 + mat   - matrix to extract local submatrix from
10486 . isrow - local row indices for submatrix
10487 - iscol - local column indices for submatrix
10488 
10489   Output Parameter:
10490 . submat - the submatrix
10491 
10492   Level: intermediate
10493 
10494   Notes:
10495   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10496 
10497   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10498   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10499 
10500   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10501   `MatSetValuesBlockedLocal()` will also be implemented.
10502 
10503   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10504   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10505 
10506 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10507 @*/
10508 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10509 {
10510   PetscFunctionBegin;
10511   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10512   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10513   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10514   PetscCheckSameComm(isrow, 2, iscol, 3);
10515   PetscAssertPointer(submat, 4);
10516   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10517 
10518   if (mat->ops->getlocalsubmatrix) {
10519     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10520   } else {
10521     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10522   }
10523   PetscFunctionReturn(PETSC_SUCCESS);
10524 }
10525 
10526 /*@
10527   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10528 
10529   Not Collective
10530 
10531   Input Parameters:
10532 + mat    - matrix to extract local submatrix from
10533 . isrow  - local row indices for submatrix
10534 . iscol  - local column indices for submatrix
10535 - submat - the submatrix
10536 
10537   Level: intermediate
10538 
10539 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10540 @*/
10541 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10542 {
10543   PetscFunctionBegin;
10544   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10545   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10546   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10547   PetscCheckSameComm(isrow, 2, iscol, 3);
10548   PetscAssertPointer(submat, 4);
10549   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10550 
10551   if (mat->ops->restorelocalsubmatrix) {
10552     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10553   } else {
10554     PetscCall(MatDestroy(submat));
10555   }
10556   *submat = NULL;
10557   PetscFunctionReturn(PETSC_SUCCESS);
10558 }
10559 
10560 /*@
10561   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10562 
10563   Collective
10564 
10565   Input Parameter:
10566 . mat - the matrix
10567 
10568   Output Parameter:
10569 . is - if any rows have zero diagonals this contains the list of them
10570 
10571   Level: developer
10572 
10573 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10574 @*/
10575 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10576 {
10577   PetscFunctionBegin;
10578   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10579   PetscValidType(mat, 1);
10580   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10581   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10582 
10583   if (!mat->ops->findzerodiagonals) {
10584     Vec                diag;
10585     const PetscScalar *a;
10586     PetscInt          *rows;
10587     PetscInt           rStart, rEnd, r, nrow = 0;
10588 
10589     PetscCall(MatCreateVecs(mat, &diag, NULL));
10590     PetscCall(MatGetDiagonal(mat, diag));
10591     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10592     PetscCall(VecGetArrayRead(diag, &a));
10593     for (r = 0; r < rEnd - rStart; ++r)
10594       if (a[r] == 0.0) ++nrow;
10595     PetscCall(PetscMalloc1(nrow, &rows));
10596     nrow = 0;
10597     for (r = 0; r < rEnd - rStart; ++r)
10598       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10599     PetscCall(VecRestoreArrayRead(diag, &a));
10600     PetscCall(VecDestroy(&diag));
10601     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10602   } else {
10603     PetscUseTypeMethod(mat, findzerodiagonals, is);
10604   }
10605   PetscFunctionReturn(PETSC_SUCCESS);
10606 }
10607 
10608 /*@
10609   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10610 
10611   Collective
10612 
10613   Input Parameter:
10614 . mat - the matrix
10615 
10616   Output Parameter:
10617 . is - contains the list of rows with off block diagonal entries
10618 
10619   Level: developer
10620 
10621 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10622 @*/
10623 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10624 {
10625   PetscFunctionBegin;
10626   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10627   PetscValidType(mat, 1);
10628   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10629   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10630 
10631   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10632   PetscFunctionReturn(PETSC_SUCCESS);
10633 }
10634 
10635 /*@C
10636   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10637 
10638   Collective; No Fortran Support
10639 
10640   Input Parameter:
10641 . mat - the matrix
10642 
10643   Output Parameter:
10644 . values - the block inverses in column major order (FORTRAN-like)
10645 
10646   Level: advanced
10647 
10648   Notes:
10649   The size of the blocks is determined by the block size of the matrix.
10650 
10651   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10652 
10653   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10654 
10655 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10656 @*/
10657 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10658 {
10659   PetscFunctionBegin;
10660   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10661   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10662   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10663   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10664   PetscFunctionReturn(PETSC_SUCCESS);
10665 }
10666 
10667 /*@
10668   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10669 
10670   Collective; No Fortran Support
10671 
10672   Input Parameters:
10673 + mat     - the matrix
10674 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10675 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10676 
10677   Output Parameter:
10678 . values - the block inverses in column major order (FORTRAN-like)
10679 
10680   Level: advanced
10681 
10682   Notes:
10683   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10684 
10685   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10686 
10687 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10688 @*/
10689 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10690 {
10691   PetscFunctionBegin;
10692   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10693   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10694   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10695   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10696   PetscFunctionReturn(PETSC_SUCCESS);
10697 }
10698 
10699 /*@
10700   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10701 
10702   Collective
10703 
10704   Input Parameters:
10705 + A - the matrix
10706 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10707 
10708   Level: advanced
10709 
10710   Note:
10711   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10712 
10713 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10714 @*/
10715 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10716 {
10717   const PetscScalar *vals;
10718   PetscInt          *dnnz;
10719   PetscInt           m, rstart, rend, bs, i, j;
10720 
10721   PetscFunctionBegin;
10722   PetscCall(MatInvertBlockDiagonal(A, &vals));
10723   PetscCall(MatGetBlockSize(A, &bs));
10724   PetscCall(MatGetLocalSize(A, &m, NULL));
10725   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10726   PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs));
10727   PetscCall(PetscMalloc1(m / bs, &dnnz));
10728   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10729   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10730   PetscCall(PetscFree(dnnz));
10731   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10732   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10733   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10734   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10735   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10736   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10737   PetscFunctionReturn(PETSC_SUCCESS);
10738 }
10739 
10740 /*@
10741   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10742   via `MatTransposeColoringCreate()`.
10743 
10744   Collective
10745 
10746   Input Parameter:
10747 . c - coloring context
10748 
10749   Level: intermediate
10750 
10751 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10752 @*/
10753 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10754 {
10755   MatTransposeColoring matcolor = *c;
10756 
10757   PetscFunctionBegin;
10758   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10759   if (--((PetscObject)matcolor)->refct > 0) {
10760     matcolor = NULL;
10761     PetscFunctionReturn(PETSC_SUCCESS);
10762   }
10763 
10764   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10765   PetscCall(PetscFree(matcolor->rows));
10766   PetscCall(PetscFree(matcolor->den2sp));
10767   PetscCall(PetscFree(matcolor->colorforcol));
10768   PetscCall(PetscFree(matcolor->columns));
10769   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10770   PetscCall(PetscHeaderDestroy(c));
10771   PetscFunctionReturn(PETSC_SUCCESS);
10772 }
10773 
10774 /*@
10775   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10776   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10777   `MatTransposeColoring` to sparse `B`.
10778 
10779   Collective
10780 
10781   Input Parameters:
10782 + coloring - coloring context created with `MatTransposeColoringCreate()`
10783 - B        - sparse matrix
10784 
10785   Output Parameter:
10786 . Btdense - dense matrix $B^T$
10787 
10788   Level: developer
10789 
10790   Note:
10791   These are used internally for some implementations of `MatRARt()`
10792 
10793 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10794 @*/
10795 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10796 {
10797   PetscFunctionBegin;
10798   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10799   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10800   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10801 
10802   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10803   PetscFunctionReturn(PETSC_SUCCESS);
10804 }
10805 
10806 /*@
10807   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10808   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10809   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10810   $C_{sp}$ from $C_{den}$.
10811 
10812   Collective
10813 
10814   Input Parameters:
10815 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10816 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10817 
10818   Output Parameter:
10819 . Csp - sparse matrix
10820 
10821   Level: developer
10822 
10823   Note:
10824   These are used internally for some implementations of `MatRARt()`
10825 
10826 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10827 @*/
10828 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10829 {
10830   PetscFunctionBegin;
10831   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10832   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10833   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10834 
10835   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10836   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10837   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10838   PetscFunctionReturn(PETSC_SUCCESS);
10839 }
10840 
10841 /*@
10842   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10843 
10844   Collective
10845 
10846   Input Parameters:
10847 + mat        - the matrix product C
10848 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10849 
10850   Output Parameter:
10851 . color - the new coloring context
10852 
10853   Level: intermediate
10854 
10855 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10856           `MatTransColoringApplyDenToSp()`
10857 @*/
10858 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10859 {
10860   MatTransposeColoring c;
10861   MPI_Comm             comm;
10862 
10863   PetscFunctionBegin;
10864   PetscAssertPointer(color, 3);
10865 
10866   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10867   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10868   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10869   c->ctype = iscoloring->ctype;
10870   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10871   *color = c;
10872   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10873   PetscFunctionReturn(PETSC_SUCCESS);
10874 }
10875 
10876 /*@
10877   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10878   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
10879 
10880   Not Collective
10881 
10882   Input Parameter:
10883 . mat - the matrix
10884 
10885   Output Parameter:
10886 . state - the current state
10887 
10888   Level: intermediate
10889 
10890   Notes:
10891   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10892   different matrices
10893 
10894   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10895 
10896   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10897 
10898 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10899 @*/
10900 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10901 {
10902   PetscFunctionBegin;
10903   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10904   *state = mat->nonzerostate;
10905   PetscFunctionReturn(PETSC_SUCCESS);
10906 }
10907 
10908 /*@
10909   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10910   matrices from each processor
10911 
10912   Collective
10913 
10914   Input Parameters:
10915 + comm   - the communicators the parallel matrix will live on
10916 . seqmat - the input sequential matrices
10917 . n      - number of local columns (or `PETSC_DECIDE`)
10918 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10919 
10920   Output Parameter:
10921 . mpimat - the parallel matrix generated
10922 
10923   Level: developer
10924 
10925   Note:
10926   The number of columns of the matrix in EACH processor MUST be the same.
10927 
10928 .seealso: [](ch_matrices), `Mat`
10929 @*/
10930 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10931 {
10932   PetscMPIInt size;
10933 
10934   PetscFunctionBegin;
10935   PetscCallMPI(MPI_Comm_size(comm, &size));
10936   if (size == 1) {
10937     if (reuse == MAT_INITIAL_MATRIX) {
10938       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10939     } else {
10940       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10941     }
10942     PetscFunctionReturn(PETSC_SUCCESS);
10943   }
10944 
10945   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");
10946 
10947   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10948   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10949   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10950   PetscFunctionReturn(PETSC_SUCCESS);
10951 }
10952 
10953 /*@
10954   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10955 
10956   Collective
10957 
10958   Input Parameters:
10959 + A - the matrix to create subdomains from
10960 - N - requested number of subdomains
10961 
10962   Output Parameters:
10963 + n   - number of subdomains resulting on this MPI process
10964 - iss - `IS` list with indices of subdomains on this MPI process
10965 
10966   Level: advanced
10967 
10968   Note:
10969   The number of subdomains must be smaller than the communicator size
10970 
10971 .seealso: [](ch_matrices), `Mat`, `IS`
10972 @*/
10973 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10974 {
10975   MPI_Comm    comm, subcomm;
10976   PetscMPIInt size, rank, color;
10977   PetscInt    rstart, rend, k;
10978 
10979   PetscFunctionBegin;
10980   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10981   PetscCallMPI(MPI_Comm_size(comm, &size));
10982   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10983   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);
10984   *n    = 1;
10985   k     = size / N + (size % N > 0); /* There are up to k ranks to a color */
10986   color = rank / k;
10987   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10988   PetscCall(PetscMalloc1(1, iss));
10989   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10990   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10991   PetscCallMPI(MPI_Comm_free(&subcomm));
10992   PetscFunctionReturn(PETSC_SUCCESS);
10993 }
10994 
10995 /*@
10996   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10997 
10998   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10999   If they are not the same, uses `MatMatMatMult()`.
11000 
11001   Once the coarse grid problem is constructed, correct for interpolation operators
11002   that are not of full rank, which can legitimately happen in the case of non-nested
11003   geometric multigrid.
11004 
11005   Input Parameters:
11006 + restrct     - restriction operator
11007 . dA          - fine grid matrix
11008 . interpolate - interpolation operator
11009 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11010 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11011 
11012   Output Parameter:
11013 . A - the Galerkin coarse matrix
11014 
11015   Options Database Key:
11016 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11017 
11018   Level: developer
11019 
11020   Note:
11021   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11022 
11023 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11024 @*/
11025 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11026 {
11027   IS  zerorows;
11028   Vec diag;
11029 
11030   PetscFunctionBegin;
11031   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11032   /* Construct the coarse grid matrix */
11033   if (interpolate == restrct) {
11034     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11035   } else {
11036     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11037   }
11038 
11039   /* If the interpolation matrix is not of full rank, A will have zero rows.
11040      This can legitimately happen in the case of non-nested geometric multigrid.
11041      In that event, we set the rows of the matrix to the rows of the identity,
11042      ignoring the equations (as the RHS will also be zero). */
11043 
11044   PetscCall(MatFindZeroRows(*A, &zerorows));
11045 
11046   if (zerorows != NULL) { /* if there are any zero rows */
11047     PetscCall(MatCreateVecs(*A, &diag, NULL));
11048     PetscCall(MatGetDiagonal(*A, diag));
11049     PetscCall(VecISSet(diag, zerorows, 1.0));
11050     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11051     PetscCall(VecDestroy(&diag));
11052     PetscCall(ISDestroy(&zerorows));
11053   }
11054   PetscFunctionReturn(PETSC_SUCCESS);
11055 }
11056 
11057 /*@C
11058   MatSetOperation - Allows user to set a matrix operation for any matrix type
11059 
11060   Logically Collective
11061 
11062   Input Parameters:
11063 + mat - the matrix
11064 . op  - the name of the operation
11065 - f   - the function that provides the operation
11066 
11067   Level: developer
11068 
11069   Example Usage:
11070 .vb
11071   extern PetscErrorCode usermult(Mat, Vec, Vec);
11072 
11073   PetscCall(MatCreateXXX(comm, ..., &A));
11074   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11075 .ve
11076 
11077   Notes:
11078   See the file `include/petscmat.h` for a complete list of matrix
11079   operations, which all have the form MATOP_<OPERATION>, where
11080   <OPERATION> is the name (in all capital letters) of the
11081   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11082 
11083   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11084   sequence as the usual matrix interface routines, since they
11085   are intended to be accessed via the usual matrix interface
11086   routines, e.g.,
11087 .vb
11088   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11089 .ve
11090 
11091   In particular each function MUST return `PETSC_SUCCESS` on success and
11092   nonzero on failure.
11093 
11094   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11095 
11096 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11097 @*/
11098 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11099 {
11100   PetscFunctionBegin;
11101   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11102   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11103   (((void (**)(void))mat->ops)[op]) = f;
11104   PetscFunctionReturn(PETSC_SUCCESS);
11105 }
11106 
11107 /*@C
11108   MatGetOperation - Gets a matrix operation for any matrix type.
11109 
11110   Not Collective
11111 
11112   Input Parameters:
11113 + mat - the matrix
11114 - op  - the name of the operation
11115 
11116   Output Parameter:
11117 . f - the function that provides the operation
11118 
11119   Level: developer
11120 
11121   Example Usage:
11122 .vb
11123   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11124 
11125   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11126 .ve
11127 
11128   Notes:
11129   See the file include/petscmat.h for a complete list of matrix
11130   operations, which all have the form MATOP_<OPERATION>, where
11131   <OPERATION> is the name (in all capital letters) of the
11132   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11133 
11134   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11135 
11136 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11137 @*/
11138 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11139 {
11140   PetscFunctionBegin;
11141   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11142   *f = (((void (**)(void))mat->ops)[op]);
11143   PetscFunctionReturn(PETSC_SUCCESS);
11144 }
11145 
11146 /*@
11147   MatHasOperation - Determines whether the given matrix supports the particular operation.
11148 
11149   Not Collective
11150 
11151   Input Parameters:
11152 + mat - the matrix
11153 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11154 
11155   Output Parameter:
11156 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11157 
11158   Level: advanced
11159 
11160   Note:
11161   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11162 
11163 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11164 @*/
11165 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11166 {
11167   PetscFunctionBegin;
11168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11169   PetscAssertPointer(has, 3);
11170   if (mat->ops->hasoperation) {
11171     PetscUseTypeMethod(mat, hasoperation, op, has);
11172   } else {
11173     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11174     else {
11175       *has = PETSC_FALSE;
11176       if (op == MATOP_CREATE_SUBMATRIX) {
11177         PetscMPIInt size;
11178 
11179         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11180         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11181       }
11182     }
11183   }
11184   PetscFunctionReturn(PETSC_SUCCESS);
11185 }
11186 
11187 /*@
11188   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11189 
11190   Collective
11191 
11192   Input Parameter:
11193 . mat - the matrix
11194 
11195   Output Parameter:
11196 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11197 
11198   Level: beginner
11199 
11200 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11201 @*/
11202 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11203 {
11204   PetscFunctionBegin;
11205   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11206   PetscValidType(mat, 1);
11207   PetscAssertPointer(cong, 2);
11208   if (!mat->rmap || !mat->cmap) {
11209     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11210     PetscFunctionReturn(PETSC_SUCCESS);
11211   }
11212   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11213     PetscCall(PetscLayoutSetUp(mat->rmap));
11214     PetscCall(PetscLayoutSetUp(mat->cmap));
11215     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11216     if (*cong) mat->congruentlayouts = 1;
11217     else mat->congruentlayouts = 0;
11218   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11219   PetscFunctionReturn(PETSC_SUCCESS);
11220 }
11221 
11222 PetscErrorCode MatSetInf(Mat A)
11223 {
11224   PetscFunctionBegin;
11225   PetscUseTypeMethod(A, setinf);
11226   PetscFunctionReturn(PETSC_SUCCESS);
11227 }
11228 
11229 /*@
11230   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
11231   and possibly removes small values from the graph structure.
11232 
11233   Collective
11234 
11235   Input Parameters:
11236 + A       - the matrix
11237 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11238 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11239 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11240 . num_idx - size of 'index' array
11241 - index   - array of block indices to use for graph strength of connection weight
11242 
11243   Output Parameter:
11244 . graph - the resulting graph
11245 
11246   Level: advanced
11247 
11248 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11249 @*/
11250 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11251 {
11252   PetscFunctionBegin;
11253   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11254   PetscValidType(A, 1);
11255   PetscValidLogicalCollectiveBool(A, scale, 3);
11256   PetscAssertPointer(graph, 7);
11257   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11258   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11259   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11260   PetscFunctionReturn(PETSC_SUCCESS);
11261 }
11262 
11263 /*@
11264   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11265   meaning the same memory is used for the matrix, and no new memory is allocated.
11266 
11267   Collective
11268 
11269   Input Parameters:
11270 + A    - the matrix
11271 - 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
11272 
11273   Level: intermediate
11274 
11275   Developer Note:
11276   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11277   of the arrays in the data structure are unneeded.
11278 
11279 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11280 @*/
11281 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11282 {
11283   PetscFunctionBegin;
11284   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11285   PetscUseTypeMethod(A, eliminatezeros, keep);
11286   PetscFunctionReturn(PETSC_SUCCESS);
11287 }
11288