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