xref: /petsc/src/mat/interface/matrix.c (revision 04346f8ccbfaa9fb73fb7dce6ecc10b18d1c2572)
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   PetscCheck(x->ops->setrandom,PetscObjectComm((PetscObject)x),PETSC_ERR_SUP,"Mat type %s",((PetscObject)x)->type_name);
83 
84   if (!rctx) {
85     MPI_Comm comm;
86     PetscCall(PetscObjectGetComm((PetscObject)x,&comm));
87     PetscCall(PetscRandomCreate(comm,&randObj));
88     PetscCall(PetscRandomSetFromOptions(randObj));
89     rctx = randObj;
90   }
91   PetscCall(PetscLogEventBegin(MAT_SetRandom,x,rctx,0,0));
92   PetscCall((*x->ops->setrandom)(x,rctx));
93   PetscCall(PetscLogEventEnd(MAT_SetRandom,x,rctx,0,0));
94 
95   PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY));
96   PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY));
97   PetscCall(PetscRandomDestroy(&randObj));
98   PetscFunctionReturn(0);
99 }
100 
101 /*@
102    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
103 
104    Logically Collective on Mat
105 
106    Input Parameter:
107 .  mat - the factored matrix
108 
109    Output Parameters:
110 +  pivot - the pivot value computed
111 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
112          the share the matrix
113 
114    Level: advanced
115 
116    Notes:
117     This routine does not work for factorizations done with external packages.
118 
119     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
120 
121     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
122 
123 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`
124 @*/
125 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat,PetscReal *pivot,PetscInt *row)
126 {
127   PetscFunctionBegin;
128   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
129   PetscValidRealPointer(pivot,2);
130   PetscValidIntPointer(row,3);
131   *pivot = mat->factorerror_zeropivot_value;
132   *row   = mat->factorerror_zeropivot_row;
133   PetscFunctionReturn(0);
134 }
135 
136 /*@
137    MatFactorGetError - gets the error code from a factorization
138 
139    Logically Collective on Mat
140 
141    Input Parameters:
142 .  mat - the factored matrix
143 
144    Output Parameter:
145 .  err  - the error code
146 
147    Level: advanced
148 
149    Notes:
150     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
151 
152 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
153           `MatErrorCode`
154 @*/
155 PetscErrorCode MatFactorGetError(Mat mat,MatFactorError *err)
156 {
157   PetscFunctionBegin;
158   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
159   PetscValidPointer(err,2);
160   *err = mat->factorerrortype;
161   PetscFunctionReturn(0);
162 }
163 
164 /*@
165    MatFactorClearError - clears the error code in a factorization
166 
167    Logically Collective on Mat
168 
169    Input Parameter:
170 .  mat - the factored matrix
171 
172    Level: developer
173 
174    Notes:
175     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
176 
177 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
178           `MatGetErrorCode()`, `MatErrorCode`
179 @*/
180 PetscErrorCode MatFactorClearError(Mat mat)
181 {
182   PetscFunctionBegin;
183   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
184   mat->factorerrortype             = MAT_FACTOR_NOERROR;
185   mat->factorerror_zeropivot_value = 0.0;
186   mat->factorerror_zeropivot_row   = 0;
187   PetscFunctionReturn(0);
188 }
189 
190 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat,PetscBool cols,PetscReal tol,IS *nonzero)
191 {
192   Vec               r,l;
193   const PetscScalar *al;
194   PetscInt          i,nz,gnz,N,n;
195 
196   PetscFunctionBegin;
197   PetscCall(MatCreateVecs(mat,&r,&l));
198   if (!cols) { /* nonzero rows */
199     PetscCall(MatGetSize(mat,&N,NULL));
200     PetscCall(MatGetLocalSize(mat,&n,NULL));
201     PetscCall(VecSet(l,0.0));
202     PetscCall(VecSetRandom(r,NULL));
203     PetscCall(MatMult(mat,r,l));
204     PetscCall(VecGetArrayRead(l,&al));
205   } else { /* nonzero columns */
206     PetscCall(MatGetSize(mat,NULL,&N));
207     PetscCall(MatGetLocalSize(mat,NULL,&n));
208     PetscCall(VecSet(r,0.0));
209     PetscCall(VecSetRandom(l,NULL));
210     PetscCall(MatMultTranspose(mat,l,r));
211     PetscCall(VecGetArrayRead(r,&al));
212   }
213   if (tol <= 0.0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nz++; }
214   else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nz++; }
215   PetscCall(MPIU_Allreduce(&nz,&gnz,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
216   if (gnz != N) {
217     PetscInt *nzr;
218     PetscCall(PetscMalloc1(nz,&nzr));
219     if (nz) {
220       if (tol < 0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nzr[nz++] = i; }
221       else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; }
222     }
223     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat),nz,nzr,PETSC_OWN_POINTER,nonzero));
224   } else *nonzero = NULL;
225   if (!cols) { /* nonzero rows */
226     PetscCall(VecRestoreArrayRead(l,&al));
227   } else {
228     PetscCall(VecRestoreArrayRead(r,&al));
229   }
230   PetscCall(VecDestroy(&l));
231   PetscCall(VecDestroy(&r));
232   PetscFunctionReturn(0);
233 }
234 
235 /*@
236       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
237 
238   Input Parameter:
239 .    A  - the matrix
240 
241   Output Parameter:
242 .    keptrows - the rows that are not completely zero
243 
244   Notes:
245     keptrows is set to NULL if all rows are nonzero.
246 
247   Level: intermediate
248 
249  @*/
250 PetscErrorCode MatFindNonzeroRows(Mat mat,IS *keptrows)
251 {
252   PetscFunctionBegin;
253   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
254   PetscValidType(mat,1);
255   PetscValidPointer(keptrows,2);
256   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
257   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
258   if (mat->ops->findnonzerorows) {
259     PetscCall((*mat->ops->findnonzerorows)(mat,keptrows));
260   } else {
261     PetscCall(MatFindNonzeroRowsOrCols_Basic(mat,PETSC_FALSE,0.0,keptrows));
262   }
263   PetscFunctionReturn(0);
264 }
265 
266 /*@
267       MatFindZeroRows - Locate all rows that are completely zero in the matrix
268 
269   Input Parameter:
270 .    A  - the matrix
271 
272   Output Parameter:
273 .    zerorows - the rows that are completely zero
274 
275   Notes:
276     zerorows is set to NULL if no rows are zero.
277 
278   Level: intermediate
279 
280  @*/
281 PetscErrorCode MatFindZeroRows(Mat mat,IS *zerorows)
282 {
283   IS       keptrows;
284   PetscInt m, n;
285 
286   PetscFunctionBegin;
287   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
288   PetscValidType(mat,1);
289   PetscValidPointer(zerorows,2);
290   PetscCall(MatFindNonzeroRows(mat, &keptrows));
291   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
292      In keeping with this convention, we set zerorows to NULL if there are no zero
293      rows. */
294   if (keptrows == NULL) {
295     *zerorows = NULL;
296   } else {
297     PetscCall(MatGetOwnershipRange(mat,&m,&n));
298     PetscCall(ISComplement(keptrows,m,n,zerorows));
299     PetscCall(ISDestroy(&keptrows));
300   }
301   PetscFunctionReturn(0);
302 }
303 
304 /*@
305    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
306 
307    Not Collective
308 
309    Input Parameters:
310 .   A - the matrix
311 
312    Output Parameters:
313 .   a - the diagonal part (which is a SEQUENTIAL matrix)
314 
315    Notes:
316    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
317 
318    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.
319 
320    Level: advanced
321 
322 .seelaso: `MatCreateAIJ()`
323 @*/
324 PetscErrorCode MatGetDiagonalBlock(Mat A,Mat *a)
325 {
326   PetscFunctionBegin;
327   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
328   PetscValidType(A,1);
329   PetscValidPointer(a,2);
330   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
331   if (A->ops->getdiagonalblock) {
332     PetscCall((*A->ops->getdiagonalblock)(A,a));
333   } else {
334     PetscMPIInt size;
335 
336     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
337     PetscCheck(size == 1,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not for parallel matrix type %s",((PetscObject)A)->type_name);
338     *a = A;
339   }
340   PetscFunctionReturn(0);
341 }
342 
343 /*@
344    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
345 
346    Collective on Mat
347 
348    Input Parameters:
349 .  mat - the matrix
350 
351    Output Parameter:
352 .   trace - the sum of the diagonal entries
353 
354    Level: advanced
355 
356 @*/
357 PetscErrorCode MatGetTrace(Mat mat,PetscScalar *trace)
358 {
359   Vec diag;
360 
361   PetscFunctionBegin;
362   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
363   PetscValidScalarPointer(trace,2);
364   PetscCall(MatCreateVecs(mat,&diag,NULL));
365   PetscCall(MatGetDiagonal(mat,diag));
366   PetscCall(VecSum(diag,trace));
367   PetscCall(VecDestroy(&diag));
368   PetscFunctionReturn(0);
369 }
370 
371 /*@
372    MatRealPart - Zeros out the imaginary part of the matrix
373 
374    Logically Collective on Mat
375 
376    Input Parameters:
377 .  mat - the matrix
378 
379    Level: advanced
380 
381 .seealso: `MatImaginaryPart()`
382 @*/
383 PetscErrorCode MatRealPart(Mat mat)
384 {
385   PetscFunctionBegin;
386   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
387   PetscValidType(mat,1);
388   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
389   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
390   PetscCheck(mat->ops->realpart,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
391   MatCheckPreallocated(mat,1);
392   PetscCall((*mat->ops->realpart)(mat));
393   PetscFunctionReturn(0);
394 }
395 
396 /*@C
397    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
398 
399    Collective on Mat
400 
401    Input Parameter:
402 .  mat - the matrix
403 
404    Output Parameters:
405 +   nghosts - number of ghosts (note for BAIJ matrices there is one ghost for each block)
406 -   ghosts - the global indices of the ghost points
407 
408    Notes:
409     the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
410 
411    Level: advanced
412 
413 @*/
414 PetscErrorCode MatGetGhosts(Mat mat,PetscInt *nghosts,const PetscInt *ghosts[])
415 {
416   PetscFunctionBegin;
417   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
418   PetscValidType(mat,1);
419   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
420   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
421   if (mat->ops->getghosts) {
422     PetscCall((*mat->ops->getghosts)(mat,nghosts,ghosts));
423   } else {
424     if (nghosts) *nghosts = 0;
425     if (ghosts)  *ghosts  = NULL;
426   }
427   PetscFunctionReturn(0);
428 }
429 
430 /*@
431    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
432 
433    Logically Collective on Mat
434 
435    Input Parameters:
436 .  mat - the matrix
437 
438    Level: advanced
439 
440 .seealso: `MatRealPart()`
441 @*/
442 PetscErrorCode MatImaginaryPart(Mat mat)
443 {
444   PetscFunctionBegin;
445   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
446   PetscValidType(mat,1);
447   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
448   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
449   PetscCheck(mat->ops->imaginarypart,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
450   MatCheckPreallocated(mat,1);
451   PetscCall((*mat->ops->imaginarypart)(mat));
452   PetscFunctionReturn(0);
453 }
454 
455 /*@
456    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for BAIJ matrices)
457 
458    Not Collective
459 
460    Input Parameter:
461 .  mat - the matrix
462 
463    Output Parameters:
464 +  missing - is any diagonal missing
465 -  dd - first diagonal entry that is missing (optional) on this process
466 
467    Level: advanced
468 
469 .seealso: `MatRealPart()`
470 @*/
471 PetscErrorCode MatMissingDiagonal(Mat mat,PetscBool *missing,PetscInt *dd)
472 {
473   PetscFunctionBegin;
474   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
475   PetscValidType(mat,1);
476   PetscValidBoolPointer(missing,2);
477   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix %s",((PetscObject)mat)->type_name);
478   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
479   PetscCheck(mat->ops->missingdiagonal,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
480   PetscCall((*mat->ops->missingdiagonal)(mat,missing,dd));
481   PetscFunctionReturn(0);
482 }
483 
484 /*@C
485    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
486    for each row that you get to ensure that your application does
487    not bleed memory.
488 
489    Not Collective
490 
491    Input Parameters:
492 +  mat - the matrix
493 -  row - the row to get
494 
495    Output Parameters:
496 +  ncols -  if not NULL, the number of nonzeros in the row
497 .  cols - if not NULL, the column numbers
498 -  vals - if not NULL, the values
499 
500    Notes:
501    This routine is provided for people who need to have direct access
502    to the structure of a matrix.  We hope that we provide enough
503    high-level matrix routines that few users will need it.
504 
505    `MatGetRow()` always returns 0-based column indices, regardless of
506    whether the internal representation is 0-based (default) or 1-based.
507 
508    For better efficiency, set cols and/or vals to NULL if you do
509    not wish to extract these quantities.
510 
511    The user can only examine the values extracted with `MatGetRow()`;
512    the values cannot be altered.  To change the matrix entries, one
513    must use `MatSetValues()`.
514 
515    You can only have one call to `MatGetRow()` outstanding for a particular
516    matrix at a time, per processor. `MatGetRow()` can only obtain rows
517    associated with the given processor, it cannot get rows from the
518    other processors; for that we suggest using `MatCreateSubMatrices()`, then
519    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
520    is in the global number of rows.
521 
522    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
523 
524    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
525 
526    Fortran Notes:
527    The calling sequence from Fortran is
528 .vb
529    MatGetRow(matrix,row,ncols,cols,values,ierr)
530          Mat     matrix (input)
531          integer row    (input)
532          integer ncols  (output)
533          integer cols(maxcols) (output)
534          double precision (or double complex) values(maxcols) output
535 .ve
536    where maxcols >= maximum nonzeros in any row of the matrix.
537 
538    Caution:
539    Do not try to change the contents of the output arrays (cols and vals).
540    In some cases, this may corrupt the matrix.
541 
542    Level: advanced
543 
544 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
545 @*/
546 PetscErrorCode MatGetRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
547 {
548   PetscInt incols;
549 
550   PetscFunctionBegin;
551   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
552   PetscValidType(mat,1);
553   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
554   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
555   PetscCheck(mat->ops->getrow,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
556   MatCheckPreallocated(mat,1);
557   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);
558   PetscCall(PetscLogEventBegin(MAT_GetRow,mat,0,0,0));
559   PetscCall((*mat->ops->getrow)(mat,row,&incols,(PetscInt**)cols,(PetscScalar**)vals));
560   if (ncols) *ncols = incols;
561   PetscCall(PetscLogEventEnd(MAT_GetRow,mat,0,0,0));
562   PetscFunctionReturn(0);
563 }
564 
565 /*@
566    MatConjugate - replaces the matrix values with their complex conjugates
567 
568    Logically Collective on Mat
569 
570    Input Parameters:
571 .  mat - the matrix
572 
573    Level: advanced
574 
575 .seealso: `VecConjugate()`, `MatTranspose()`
576 @*/
577 PetscErrorCode MatConjugate(Mat mat)
578 {
579   PetscFunctionBegin;
580   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
581   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
582   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
583     PetscCheck(mat->ops->conjugate,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not provided for matrix type %s, send email to petsc-maint@mcs.anl.gov",((PetscObject)mat)->type_name);
584     PetscCall((*mat->ops->conjugate)(mat));
585     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
586   }
587   PetscFunctionReturn(0);
588 }
589 
590 /*@C
591    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
592 
593    Not Collective
594 
595    Input Parameters:
596 +  mat - the matrix
597 .  row - the row to get
598 .  ncols, cols - the number of nonzeros and their columns
599 -  vals - if nonzero the column values
600 
601    Notes:
602    This routine should be called after you have finished examining the entries.
603 
604    This routine zeros out ncols, cols, and vals. This is to prevent accidental
605    us of the array after it has been restored. If you pass NULL, it will
606    not zero the pointers.  Use of cols or vals after `MatRestoreRow()` is invalid.
607 
608    Fortran Notes:
609    The calling sequence from Fortran is
610 .vb
611    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
612       Mat     matrix (input)
613       integer row    (input)
614       integer ncols  (output)
615       integer cols(maxcols) (output)
616       double precision (or double complex) values(maxcols) output
617 .ve
618    Where maxcols >= maximum nonzeros in any row of the matrix.
619 
620    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
621    before another call to `MatGetRow()` can be made.
622 
623    Level: advanced
624 
625 .seealso: `MatGetRow()`
626 @*/
627 PetscErrorCode MatRestoreRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
628 {
629   PetscFunctionBegin;
630   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
631   if (ncols) PetscValidIntPointer(ncols,3);
632   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
633   if (!mat->ops->restorerow) PetscFunctionReturn(0);
634   PetscCall((*mat->ops->restorerow)(mat,row,ncols,(PetscInt **)cols,(PetscScalar **)vals));
635   if (ncols) *ncols = 0;
636   if (cols)  *cols = NULL;
637   if (vals)  *vals = NULL;
638   PetscFunctionReturn(0);
639 }
640 
641 /*@
642    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
643    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
644 
645    Not Collective
646 
647    Input Parameters:
648 .  mat - the matrix
649 
650    Notes:
651    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.
652 
653    Level: advanced
654 
655 .seealso: `MatRestoreRowUpperTriangular()`
656 @*/
657 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
658 {
659   PetscFunctionBegin;
660   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
661   PetscValidType(mat,1);
662   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
663   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
664   MatCheckPreallocated(mat,1);
665   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
666   PetscCall((*mat->ops->getrowuppertriangular)(mat));
667   PetscFunctionReturn(0);
668 }
669 
670 /*@
671    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
672 
673    Not Collective
674 
675    Input Parameters:
676 .  mat - the matrix
677 
678    Notes:
679    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
680 
681    Level: advanced
682 
683 .seealso: `MatGetRowUpperTriangular()`
684 @*/
685 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
686 {
687   PetscFunctionBegin;
688   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
689   PetscValidType(mat,1);
690   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
691   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
692   MatCheckPreallocated(mat,1);
693   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
694   PetscCall((*mat->ops->restorerowuppertriangular)(mat));
695   PetscFunctionReturn(0);
696 }
697 
698 /*@C
699    MatSetOptionsPrefix - Sets the prefix used for searching for all
700    Mat options in the database.
701 
702    Logically Collective on Mat
703 
704    Input Parameters:
705 +  A - the Mat context
706 -  prefix - the prefix to prepend to all option names
707 
708    Notes:
709    A hyphen (-) must NOT be given at the beginning of the prefix name.
710    The first character of all runtime options is AUTOMATICALLY the hyphen.
711 
712    This is NOT used for options for the factorization of the matrix. Normally the
713    prefix is automatically passed in from the PC calling the factorization. To set
714    it directly use  `MatSetOptionsPrefixFactor()`
715 
716    Level: advanced
717 
718 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
719 @*/
720 PetscErrorCode MatSetOptionsPrefix(Mat A,const char prefix[])
721 {
722   PetscFunctionBegin;
723   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
724   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A,prefix));
725   PetscFunctionReturn(0);
726 }
727 
728 /*@C
729    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all Mat factor options in the database for
730    for matrices created with `MatGetFactor()`
731 
732    Logically Collective on Mat
733 
734    Input Parameters:
735 +  A - the Mat context
736 -  prefix - the prefix to prepend to all option names for the factored matrix
737 
738    Notes:
739    A hyphen (-) must NOT be given at the beginning of the prefix name.
740    The first character of all runtime options is AUTOMATICALLY the hyphen.
741 
742    Normally the prefix is automatically passed in from the PC calling the factorization. To set
743    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
744 
745    Level: developer
746 
747 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
748 @*/
749 PetscErrorCode MatSetOptionsPrefixFactor(Mat A,const char prefix[])
750 {
751   PetscFunctionBegin;
752   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
753   if (prefix) {
754     PetscValidCharPointer(prefix,2);
755     PetscCheck(prefix[0] != '-',PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
756     if (prefix != A->factorprefix) {
757       PetscCall(PetscFree(A->factorprefix));
758       PetscCall(PetscStrallocpy(prefix,&A->factorprefix));
759     }
760   } else PetscCall(PetscFree(A->factorprefix));
761   PetscFunctionReturn(0);
762 }
763 
764 /*@C
765    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all Mat factor options in the database for
766    for matrices created with `MatGetFactor()`
767 
768    Logically Collective on Mat
769 
770    Input Parameters:
771 +  A - the Mat context
772 -  prefix - the prefix to prepend to all option names for the factored matrix
773 
774    Notes:
775    A hyphen (-) must NOT be given at the beginning of the prefix name.
776    The first character of all runtime options is AUTOMATICALLY the hyphen.
777 
778    Normally the prefix is automatically passed in from the PC calling the factorization. To set
779    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
780 
781    Level: developer
782    .seealso: `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
783              `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
784              `MatSetOptionsPrefix()`
785 @*/
786 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A,const char prefix[])
787 {
788   char           *buf = A->factorprefix;
789   size_t         len1,len2;
790 
791   PetscFunctionBegin;
792   PetscValidHeader(A,1);
793   if (!prefix) PetscFunctionReturn(0);
794   if (!buf) {
795     PetscCall(MatSetOptionsPrefixFactor(A,prefix));
796     PetscFunctionReturn(0);
797   }
798   PetscCheck(prefix[0] != '-',PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
799 
800   PetscCall(PetscStrlen(prefix,&len1));
801   PetscCall(PetscStrlen(buf,&len2));
802   PetscCall(PetscMalloc1(1+len1+len2,&A->factorprefix));
803   PetscCall(PetscStrcpy(A->factorprefix,buf));
804   PetscCall(PetscStrcat(A->factorprefix,prefix));
805   PetscCall(PetscFree(buf));
806   PetscFunctionReturn(0);
807 }
808 
809 /*@C
810    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
811    Mat options in the database.
812 
813    Logically Collective on Mat
814 
815    Input Parameters:
816 +  A - the Mat context
817 -  prefix - the prefix to prepend to all option names
818 
819    Notes:
820    A hyphen (-) must NOT be given at the beginning of the prefix name.
821    The first character of all runtime options is AUTOMATICALLY the hyphen.
822 
823    Level: advanced
824 
825 .seealso: `MatGetOptionsPrefix()`
826 @*/
827 PetscErrorCode MatAppendOptionsPrefix(Mat A,const char prefix[])
828 {
829   PetscFunctionBegin;
830   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
831   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A,prefix));
832   PetscFunctionReturn(0);
833 }
834 
835 /*@C
836    MatGetOptionsPrefix - Gets the prefix used for searching for all
837    Mat options in the database.
838 
839    Not Collective
840 
841    Input Parameter:
842 .  A - the Mat context
843 
844    Output Parameter:
845 .  prefix - pointer to the prefix string used
846 
847    Notes:
848     On the fortran side, the user should pass in a string 'prefix' of
849    sufficient length to hold the prefix.
850 
851    Level: advanced
852 
853 .seealso: `MatAppendOptionsPrefix()`
854 @*/
855 PetscErrorCode MatGetOptionsPrefix(Mat A,const char *prefix[])
856 {
857   PetscFunctionBegin;
858   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
859   PetscValidPointer(prefix,2);
860   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A,prefix));
861   PetscFunctionReturn(0);
862 }
863 
864 /*@
865    MatResetPreallocation - Reset mat to use the original nonzero pattern provided by users.
866 
867    Collective on Mat
868 
869    Input Parameters:
870 .  A - the Mat context
871 
872    Notes:
873    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
874 
875    Users can reset the preallocation to access the original memory.
876 
877    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.
878 
879    Level: beginner
880 
881 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
882 @*/
883 PetscErrorCode MatResetPreallocation(Mat A)
884 {
885   PetscFunctionBegin;
886   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
887   PetscValidType(A,1);
888   PetscUseMethod(A,"MatResetPreallocation_C",(Mat),(A));
889   PetscFunctionReturn(0);
890 }
891 
892 /*@
893    MatSetUp - Sets up the internal matrix data structures for later use.
894 
895    Collective on Mat
896 
897    Input Parameters:
898 .  A - the Mat context
899 
900    Notes:
901    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
902 
903    If a suitable preallocation routine is used, this function does not need to be called.
904 
905    See the Performance chapter of the PETSc users manual for how to preallocate matrices
906 
907    Level: beginner
908 
909 .seealso: `MatCreate()`, `MatDestroy()`
910 @*/
911 PetscErrorCode MatSetUp(Mat A)
912 {
913   PetscFunctionBegin;
914   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
915   if (!((PetscObject)A)->type_name) {
916     PetscMPIInt size;
917 
918     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
919     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
920   }
921   if (!A->preallocated && A->ops->setup) {
922     PetscCall(PetscInfo(A,"Warning not preallocating matrix storage\n"));
923     PetscCall((*A->ops->setup)(A));
924   }
925   PetscCall(PetscLayoutSetUp(A->rmap));
926   PetscCall(PetscLayoutSetUp(A->cmap));
927   A->preallocated = PETSC_TRUE;
928   PetscFunctionReturn(0);
929 }
930 
931 #if defined(PETSC_HAVE_SAWS)
932 #include <petscviewersaws.h>
933 #endif
934 
935 /*@C
936    MatViewFromOptions - View from Options
937 
938    Collective on Mat
939 
940    Input Parameters:
941 +  A - the Mat context
942 .  obj - Optional object
943 -  name - command line option
944 
945    Level: intermediate
946 .seealso: `Mat`, `MatView`, `PetscObjectViewFromOptions()`, `MatCreate()`
947 @*/
948 PetscErrorCode  MatViewFromOptions(Mat A,PetscObject obj,const char name[])
949 {
950   PetscFunctionBegin;
951   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
952   PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name));
953   PetscFunctionReturn(0);
954 }
955 
956 /*@C
957    MatView - Visualizes a matrix object.
958 
959    Collective on Mat
960 
961    Input Parameters:
962 +  mat - the matrix
963 -  viewer - visualization context
964 
965   Notes:
966   The available visualization contexts include
967 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
968 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
969 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
970 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
971 
972    The user can open alternative visualization contexts with
973 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
974 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
975          specified file; corresponding input uses MatLoad()
976 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
977          an X window display
978 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
979          Currently only the sequential dense and AIJ
980          matrix types support the Socket viewer.
981 
982    The user can call `PetscViewerPushFormat()` to specify the output
983    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
984    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
985 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
986 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
987 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
988 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
989          format common among all matrix types
990 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
991          format (which is in many cases the same as the default)
992 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
993          size and structure (not the matrix entries)
994 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
995          the matrix structure
996 
997    Options Database Keys:
998 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
999 .  -mat_view ::ascii_info_detail - Prints more detailed info
1000 .  -mat_view - Prints matrix in ASCII format
1001 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1002 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1003 .  -display <name> - Sets display name (default is host)
1004 .  -draw_pause <sec> - Sets number of seconds to pause after display
1005 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1006 .  -viewer_socket_machine <machine> -
1007 .  -viewer_socket_port <port> -
1008 .  -mat_view binary - save matrix to file in binary format
1009 -  -viewer_binary_filename <name> -
1010 
1011    Level: beginner
1012 
1013    Notes:
1014     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1015     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1016 
1017     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1018 
1019     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1020       viewer is used.
1021 
1022       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1023       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1024 
1025       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1026       and then use the following mouse functions.
1027 .vb
1028   left mouse: zoom in
1029   middle mouse: zoom out
1030   right mouse: continue with the simulation
1031 .ve
1032 
1033 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`,
1034           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`
1035 @*/
1036 PetscErrorCode MatView(Mat mat,PetscViewer viewer)
1037 {
1038   PetscInt          rows,cols,rbs,cbs;
1039   PetscBool         isascii,isstring,issaws;
1040   PetscViewerFormat format;
1041   PetscMPIInt       size;
1042 
1043   PetscFunctionBegin;
1044   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1045   PetscValidType(mat,1);
1046   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat),&viewer));
1047   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1048   PetscCheckSameComm(mat,1,viewer,2);
1049   MatCheckPreallocated(mat,1);
1050 
1051   PetscCall(PetscViewerGetFormat(viewer,&format));
1052   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
1053   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1054 
1055   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring));
1056   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
1057   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws));
1058   if ((!isascii || (format != PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) && mat->factortype) {
1059     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"No viewers for factored matrix except ASCII info or info_detail");
1060   }
1061 
1062   PetscCall(PetscLogEventBegin(MAT_View,mat,viewer,0,0));
1063   if (isascii) {
1064     PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Must call MatAssemblyBegin/End() before viewing matrix");
1065     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat,viewer));
1066     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1067       MatNullSpace nullsp,transnullsp;
1068 
1069       PetscCall(PetscViewerASCIIPushTab(viewer));
1070       PetscCall(MatGetSize(mat,&rows,&cols));
1071       PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
1072       if (rbs != 1 || cbs != 1) {
1073         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n",rows,cols,rbs,cbs));
1074         else            PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n",rows,cols,rbs));
1075       } else PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n",rows,cols));
1076       if (mat->factortype) {
1077         MatSolverType solver;
1078         PetscCall(MatFactorGetSolverType(mat,&solver));
1079         PetscCall(PetscViewerASCIIPrintf(viewer,"package used to perform factorization: %s\n",solver));
1080       }
1081       if (mat->ops->getinfo) {
1082         MatInfo info;
1083         PetscCall(MatGetInfo(mat,MAT_GLOBAL_SUM,&info));
1084         PetscCall(PetscViewerASCIIPrintf(viewer,"total: nonzeros=%.f, allocated nonzeros=%.f\n",info.nz_used,info.nz_allocated));
1085         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer,"total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n",(PetscInt)info.mallocs));
1086       }
1087       PetscCall(MatGetNullSpace(mat,&nullsp));
1088       PetscCall(MatGetTransposeNullSpace(mat,&transnullsp));
1089       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached null space\n"));
1090       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached transposed null space\n"));
1091       PetscCall(MatGetNearNullSpace(mat,&nullsp));
1092       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached near null space\n"));
1093       PetscCall(PetscViewerASCIIPushTab(viewer));
1094       PetscCall(MatProductView(mat,viewer));
1095       PetscCall(PetscViewerASCIIPopTab(viewer));
1096     }
1097   } else if (issaws) {
1098 #if defined(PETSC_HAVE_SAWS)
1099     PetscMPIInt rank;
1100 
1101     PetscCall(PetscObjectName((PetscObject)mat));
1102     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
1103     if (!((PetscObject)mat)->amsmem && rank == 0) {
1104       PetscCall(PetscObjectViewSAWs((PetscObject)mat,viewer));
1105     }
1106 #endif
1107   } else if (isstring) {
1108     const char *type;
1109     PetscCall(MatGetType(mat,&type));
1110     PetscCall(PetscViewerStringSPrintf(viewer," MatType: %-7.7s",type));
1111     if (mat->ops->view) PetscCall((*mat->ops->view)(mat,viewer));
1112   }
1113   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1114     PetscCall(PetscViewerASCIIPushTab(viewer));
1115     PetscCall((*mat->ops->viewnative)(mat,viewer));
1116     PetscCall(PetscViewerASCIIPopTab(viewer));
1117   } else if (mat->ops->view) {
1118     PetscCall(PetscViewerASCIIPushTab(viewer));
1119     PetscCall((*mat->ops->view)(mat,viewer));
1120     PetscCall(PetscViewerASCIIPopTab(viewer));
1121   }
1122   if (isascii) {
1123     PetscCall(PetscViewerGetFormat(viewer,&format));
1124     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1125       PetscCall(PetscViewerASCIIPopTab(viewer));
1126     }
1127   }
1128   PetscCall(PetscLogEventEnd(MAT_View,mat,viewer,0,0));
1129   PetscFunctionReturn(0);
1130 }
1131 
1132 #if defined(PETSC_USE_DEBUG)
1133 #include <../src/sys/totalview/tv_data_display.h>
1134 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1135 {
1136   TV_add_row("Local rows", "int", &mat->rmap->n);
1137   TV_add_row("Local columns", "int", &mat->cmap->n);
1138   TV_add_row("Global rows", "int", &mat->rmap->N);
1139   TV_add_row("Global columns", "int", &mat->cmap->N);
1140   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1141   return TV_format_OK;
1142 }
1143 #endif
1144 
1145 /*@C
1146    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1147    with `MatView()`.  The matrix format is determined from the options database.
1148    Generates a parallel MPI matrix if the communicator has more than one
1149    processor.  The default matrix type is AIJ.
1150 
1151    Collective on PetscViewer
1152 
1153    Input Parameters:
1154 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1155             or some related function before a call to `MatLoad()`
1156 -  viewer - binary/HDF5 file viewer
1157 
1158    Options Database Keys:
1159    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1160    block size
1161 .    -matload_block_size <bs> - set block size
1162 
1163    Level: beginner
1164 
1165    Notes:
1166    If the Mat type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1167    Mat before calling this routine if you wish to set it from the options database.
1168 
1169    `MatLoad()` automatically loads into the options database any options
1170    given in the file filename.info where filename is the name of the file
1171    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1172    file will be ignored if you use the -viewer_binary_skip_info option.
1173 
1174    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1175    sets the default matrix type AIJ and sets the local and global sizes.
1176    If type and/or size is already set, then the same are used.
1177 
1178    In parallel, each processor can load a subset of rows (or the
1179    entire matrix).  This routine is especially useful when a large
1180    matrix is stored on disk and only part of it is desired on each
1181    processor.  For example, a parallel solver may access only some of
1182    the rows from each processor.  The algorithm used here reads
1183    relatively small blocks of data rather than reading the entire
1184    matrix and then subsetting it.
1185 
1186    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1187    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1188    or the sequence like
1189 .vb
1190     `PetscViewer` v;
1191     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1192     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1193     `PetscViewerSetFromOptions`(v);
1194     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1195     `PetscViewerFileSetName`(v,"datafile");
1196 .ve
1197    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1198 $ -viewer_type {binary,hdf5}
1199 
1200    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1201    and src/mat/tutorials/ex10.c with the second approach.
1202 
1203    Notes about the PETSc binary format:
1204    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1205    is read onto rank 0 and then shipped to its destination rank, one after another.
1206    Multiple objects, both matrices and vectors, can be stored within the same file.
1207    Their PetscObject name is ignored; they are loaded in the order of their storage.
1208 
1209    Most users should not need to know the details of the binary storage
1210    format, since `MatLoad()` and `MatView()` completely hide these details.
1211    But for anyone who's interested, the standard binary matrix storage
1212    format is
1213 
1214 $    PetscInt    MAT_FILE_CLASSID
1215 $    PetscInt    number of rows
1216 $    PetscInt    number of columns
1217 $    PetscInt    total number of nonzeros
1218 $    PetscInt    *number nonzeros in each row
1219 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1220 $    PetscScalar *values of all nonzeros
1221 
1222    PETSc automatically does the byte swapping for
1223 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1224 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1225 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1226 and `PetscBinaryWrite()` to see how this may be done.
1227 
1228    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1229    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1230    Each processor's chunk is loaded independently by its owning rank.
1231    Multiple objects, both matrices and vectors, can be stored within the same file.
1232    They are looked up by their PetscObject name.
1233 
1234    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1235    by default the same structure and naming of the AIJ arrays and column count
1236    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1237 $    save example.mat A b -v7.3
1238    can be directly read by this routine (see Reference 1 for details).
1239    Note that depending on your MATLAB version, this format might be a default,
1240    otherwise you can set it as default in Preferences.
1241 
1242    Unless -nocompression flag is used to save the file in MATLAB,
1243    PETSc must be configured with ZLIB package.
1244 
1245    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1246 
1247    Current HDF5 (MAT-File) limitations:
1248    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1249 
1250    Corresponding `MatView()` is not yet implemented.
1251 
1252    The loaded matrix is actually a transpose of the original one in MATLAB,
1253    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1254    With this format, matrix is automatically transposed by PETSc,
1255    unless the matrix is marked as SPD or symmetric
1256    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1257 
1258    References:
1259 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1260 
1261 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1262 
1263  @*/
1264 PetscErrorCode MatLoad(Mat mat,PetscViewer viewer)
1265 {
1266   PetscBool flg;
1267 
1268   PetscFunctionBegin;
1269   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1270   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1271 
1272   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat,MATAIJ));
1273 
1274   flg  = PETSC_FALSE;
1275   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matload_symmetric",&flg,NULL));
1276   if (flg) {
1277     PetscCall(MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE));
1278     PetscCall(MatSetOption(mat,MAT_SYMMETRY_ETERNAL,PETSC_TRUE));
1279   }
1280   flg  = PETSC_FALSE;
1281   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matload_spd",&flg,NULL));
1282   if (flg) PetscCall(MatSetOption(mat,MAT_SPD,PETSC_TRUE));
1283 
1284   PetscCheck(mat->ops->load,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatLoad is not supported for type %s",((PetscObject)mat)->type_name);
1285   PetscCall(PetscLogEventBegin(MAT_Load,mat,viewer,0,0));
1286   PetscCall((*mat->ops->load)(mat,viewer));
1287   PetscCall(PetscLogEventEnd(MAT_Load,mat,viewer,0,0));
1288   PetscFunctionReturn(0);
1289 }
1290 
1291 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1292 {
1293   Mat_Redundant *redund = *redundant;
1294 
1295   PetscFunctionBegin;
1296   if (redund) {
1297     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1298       PetscCall(ISDestroy(&redund->isrow));
1299       PetscCall(ISDestroy(&redund->iscol));
1300       PetscCall(MatDestroySubMatrices(1,&redund->matseq));
1301     } else {
1302       PetscCall(PetscFree2(redund->send_rank,redund->recv_rank));
1303       PetscCall(PetscFree(redund->sbuf_j));
1304       PetscCall(PetscFree(redund->sbuf_a));
1305       for (PetscInt i=0; i<redund->nrecvs; i++) {
1306         PetscCall(PetscFree(redund->rbuf_j[i]));
1307         PetscCall(PetscFree(redund->rbuf_a[i]));
1308       }
1309       PetscCall(PetscFree4(redund->sbuf_nz,redund->rbuf_nz,redund->rbuf_j,redund->rbuf_a));
1310     }
1311 
1312     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1313     PetscCall(PetscFree(redund));
1314   }
1315   PetscFunctionReturn(0);
1316 }
1317 
1318 /*@C
1319    MatDestroy - Frees space taken by a matrix.
1320 
1321    Collective on Mat
1322 
1323    Input Parameter:
1324 .  A - the matrix
1325 
1326    Level: beginner
1327 
1328    Developer Notes:
1329    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1330    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1331    MatHeaderMerge() and MatHeaderReplace() also manipulate the data in the `Mat` object and likely need changes
1332    if changes are needed here.
1333 @*/
1334 PetscErrorCode MatDestroy(Mat *A)
1335 {
1336   PetscFunctionBegin;
1337   if (!*A) PetscFunctionReturn(0);
1338   PetscValidHeaderSpecific(*A,MAT_CLASSID,1);
1339   if (--((PetscObject)(*A))->refct > 0) {*A = NULL; PetscFunctionReturn(0);}
1340 
1341   /* if memory was published with SAWs then destroy it */
1342   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1343   if ((*A)->ops->destroy) PetscCall((*(*A)->ops->destroy)(*A));
1344 
1345   PetscCall(PetscFree((*A)->factorprefix));
1346   PetscCall(PetscFree((*A)->defaultvectype));
1347   PetscCall(PetscFree((*A)->bsizes));
1348   PetscCall(PetscFree((*A)->solvertype));
1349   for (PetscInt i=0; i<MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1350   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1351   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1352   PetscCall(MatProductClear(*A));
1353   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1354   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1355   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1356   PetscCall(MatDestroy(&(*A)->schur));
1357   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1358   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1359   PetscCall(PetscHeaderDestroy(A));
1360   PetscFunctionReturn(0);
1361 }
1362 
1363 /*@C
1364    MatSetValues - Inserts or adds a block of values into a matrix.
1365    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1366    MUST be called after all calls to `MatSetValues()` have been completed.
1367 
1368    Not Collective
1369 
1370    Input Parameters:
1371 +  mat - the matrix
1372 .  v - a logically two-dimensional array of values
1373 .  m, idxm - the number of rows and their global indices
1374 .  n, idxn - the number of columns and their global indices
1375 -  addv - either `ADD_VALUES` or `INSERT_VALUES`, where
1376    `ADD_VALUES` adds values to any existing entries, and
1377    `INSERT_VALUES` replaces existing entries with new values
1378 
1379    Notes:
1380    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1381       `MatSetUp()` before using this routine
1382 
1383    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1384 
1385    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1386    options cannot be mixed without intervening calls to the assembly
1387    routines.
1388 
1389    `MatSetValues()` uses 0-based row and column numbers in Fortran
1390    as well as in C.
1391 
1392    Negative indices may be passed in idxm and idxn, these rows and columns are
1393    simply ignored. This allows easily inserting element stiffness matrices
1394    with homogeneous Dirchlet boundary conditions that you don't want represented
1395    in the matrix.
1396 
1397    Efficiency Alert:
1398    The routine `MatSetValuesBlocked()` may offer much better efficiency
1399    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1400 
1401    Level: beginner
1402 
1403    Developer Notes:
1404    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1405    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1406 
1407 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1408           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1409 @*/
1410 PetscErrorCode MatSetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1411 {
1412   PetscFunctionBeginHot;
1413   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1414   PetscValidType(mat,1);
1415   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1416   PetscValidIntPointer(idxm,3);
1417   PetscValidIntPointer(idxn,5);
1418   MatCheckPreallocated(mat,1);
1419 
1420   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1421   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1422 
1423   if (PetscDefined(USE_DEBUG)) {
1424     PetscInt       i,j;
1425 
1426     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1427     PetscCheck(mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1428 
1429     for (i=0; i<m; i++) {
1430       for (j=0; j<n; j++) {
1431         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i*n+j]))
1432 #if defined(PETSC_USE_COMPLEX)
1433           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]);
1434 #else
1435           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]);
1436 #endif
1437       }
1438     }
1439     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);
1440     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);
1441   }
1442 
1443   if (mat->assembled) {
1444     mat->was_assembled = PETSC_TRUE;
1445     mat->assembled     = PETSC_FALSE;
1446   }
1447   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1448   PetscCall((*mat->ops->setvalues)(mat,m,idxm,n,idxn,v,addv));
1449   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1450   PetscFunctionReturn(0);
1451 }
1452 
1453 /*@C
1454    MatSetValuesIS - Inserts or adds a block of values into a matrix using IS to indicate the rows and columns
1455    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1456    MUST be called after all calls to `MatSetValues()` have been completed.
1457 
1458    Not Collective
1459 
1460    Input Parameters:
1461 +  mat - the matrix
1462 .  v - a logically two-dimensional array of values
1463 .  ism - the rows to provide
1464 .  isn - the columns to provide
1465 -  addv - either `ADD_VALUES` or `INSERT_VALUES`, where
1466    `ADD_VALUES` adds values to any existing entries, and
1467    `INSERT_VALUES` replaces existing entries with new values
1468 
1469    Notes:
1470    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1471       `MatSetUp()` before using this routine
1472 
1473    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1474 
1475    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1476    options cannot be mixed without intervening calls to the assembly
1477    routines.
1478 
1479    MatSetValues() uses 0-based row and column numbers in Fortran
1480    as well as in C.
1481 
1482    Negative indices may be passed in ism and isn, these rows and columns are
1483    simply ignored. This allows easily inserting element stiffness matrices
1484    with homogeneous Dirchlet boundary conditions that you don't want represented
1485    in the matrix.
1486 
1487    Efficiency Alert:
1488    The routine `MatSetValuesBlocked()` may offer much better efficiency
1489    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1490 
1491    Level: beginner
1492 
1493    Developer Notes:
1494     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1495                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1496 
1497     This is currently not optimized for any particular IS type
1498 
1499 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1500           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1501 @*/
1502 PetscErrorCode MatSetValuesIS(Mat mat,IS ism,IS isn,const PetscScalar v[],InsertMode addv)
1503 {
1504   PetscInt       m,n;
1505   const PetscInt *rows,*cols;
1506 
1507   PetscFunctionBeginHot;
1508   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1509   PetscCall(ISGetIndices(ism,&rows));
1510   PetscCall(ISGetIndices(isn,&cols));
1511   PetscCall(ISGetLocalSize(ism,&m));
1512   PetscCall(ISGetLocalSize(isn,&n));
1513   PetscCall(MatSetValues(mat,m,rows,n,cols,v,addv));
1514   PetscCall(ISRestoreIndices(ism,&rows));
1515   PetscCall(ISRestoreIndices(isn,&cols));
1516   PetscFunctionReturn(0);
1517 }
1518 
1519 /*@
1520    MatSetValuesRowLocal - Inserts a row (block row for BAIJ matrices) of nonzero
1521         values into a matrix
1522 
1523    Not Collective
1524 
1525    Input Parameters:
1526 +  mat - the matrix
1527 .  row - the (block) row to set
1528 -  v - a logically two-dimensional array of values
1529 
1530    Notes:
1531    By the values, v, are column-oriented (for the block version) and sorted
1532 
1533    All the nonzeros in the row must be provided
1534 
1535    The matrix must have previously had its column indices set
1536 
1537    The row must belong to this process
1538 
1539    Level: intermediate
1540 
1541 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1542           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1543 @*/
1544 PetscErrorCode MatSetValuesRowLocal(Mat mat,PetscInt row,const PetscScalar v[])
1545 {
1546   PetscInt globalrow;
1547 
1548   PetscFunctionBegin;
1549   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1550   PetscValidType(mat,1);
1551   PetscValidScalarPointer(v,3);
1552   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,1,&row,&globalrow));
1553   PetscCall(MatSetValuesRow(mat,globalrow,v));
1554   PetscFunctionReturn(0);
1555 }
1556 
1557 /*@
1558    MatSetValuesRow - Inserts a row (block row for BAIJ matrices) of nonzero
1559         values into a matrix
1560 
1561    Not Collective
1562 
1563    Input Parameters:
1564 +  mat - the matrix
1565 .  row - the (block) row to set
1566 -  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
1567 
1568    Notes:
1569    The values, v, are column-oriented for the block version.
1570 
1571    All the nonzeros in the row must be provided
1572 
1573    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1574 
1575    The row must belong to this process
1576 
1577    Level: advanced
1578 
1579 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1580           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1581 @*/
1582 PetscErrorCode MatSetValuesRow(Mat mat,PetscInt row,const PetscScalar v[])
1583 {
1584   PetscFunctionBeginHot;
1585   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1586   PetscValidType(mat,1);
1587   MatCheckPreallocated(mat,1);
1588   PetscValidScalarPointer(v,3);
1589   PetscCheck(mat->insertmode != ADD_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add and insert values");
1590   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1591   mat->insertmode = INSERT_VALUES;
1592 
1593   if (mat->assembled) {
1594     mat->was_assembled = PETSC_TRUE;
1595     mat->assembled     = PETSC_FALSE;
1596   }
1597   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1598   PetscCheck(mat->ops->setvaluesrow,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1599   PetscCall((*mat->ops->setvaluesrow)(mat,row,v));
1600   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1601   PetscFunctionReturn(0);
1602 }
1603 
1604 /*@
1605    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1606      Using structured grid indexing
1607 
1608    Not Collective
1609 
1610    Input Parameters:
1611 +  mat - the matrix
1612 .  m - number of rows being entered
1613 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1614 .  n - number of columns being entered
1615 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1616 .  v - a logically two-dimensional array of values
1617 -  addv - either ADD_VALUES or INSERT_VALUES, where
1618    ADD_VALUES adds values to any existing entries, and
1619    INSERT_VALUES replaces existing entries with new values
1620 
1621    Notes:
1622    By default the values, v, are row-oriented.  See `MatSetOption()` for other options.
1623 
1624    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1625    options cannot be mixed without intervening calls to the assembly
1626    routines.
1627 
1628    The grid coordinates are across the entire grid, not just the local portion
1629 
1630    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1631    as well as in C.
1632 
1633    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1634 
1635    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1636    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1637 
1638    The columns and rows in the stencil passed in MUST be contained within the
1639    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1640    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1641    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1642    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1643 
1644    In Fortran idxm and idxn should be declared as
1645 $     MatStencil idxm(4,m),idxn(4,n)
1646    and the values inserted using
1647 $    idxm(MatStencil_i,1) = i
1648 $    idxm(MatStencil_j,1) = j
1649 $    idxm(MatStencil_k,1) = k
1650 $    idxm(MatStencil_c,1) = c
1651    etc
1652 
1653    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1654    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1655    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1656    `DM_BOUNDARY_PERIODIC` boundary type.
1657 
1658    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
1659    a single value per point) you can skip filling those indices.
1660 
1661    Inspired by the structured grid interface to the HYPRE package
1662    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1663 
1664    Efficiency Alert:
1665    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1666    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1667 
1668    Level: beginner
1669 
1670 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1671           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1672 @*/
1673 PetscErrorCode MatSetValuesStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1674 {
1675   PetscInt       buf[8192],*bufm=NULL,*bufn=NULL,*jdxm,*jdxn;
1676   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1677   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1678 
1679   PetscFunctionBegin;
1680   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1681   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1682   PetscValidType(mat,1);
1683   PetscValidPointer(idxm,3);
1684   PetscValidPointer(idxn,5);
1685 
1686   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1687     jdxm = buf; jdxn = buf+m;
1688   } else {
1689     PetscCall(PetscMalloc2(m,&bufm,n,&bufn));
1690     jdxm = bufm; jdxn = bufn;
1691   }
1692   for (i=0; i<m; i++) {
1693     for (j=0; j<3-sdim; j++) dxm++;
1694     tmp = *dxm++ - starts[0];
1695     for (j=0; j<dim-1; j++) {
1696       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1697       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1698     }
1699     if (mat->stencil.noc) dxm++;
1700     jdxm[i] = tmp;
1701   }
1702   for (i=0; i<n; i++) {
1703     for (j=0; j<3-sdim; j++) dxn++;
1704     tmp = *dxn++ - starts[0];
1705     for (j=0; j<dim-1; j++) {
1706       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1707       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1708     }
1709     if (mat->stencil.noc) dxn++;
1710     jdxn[i] = tmp;
1711   }
1712   PetscCall(MatSetValuesLocal(mat,m,jdxm,n,jdxn,v,addv));
1713   PetscCall(PetscFree2(bufm,bufn));
1714   PetscFunctionReturn(0);
1715 }
1716 
1717 /*@
1718    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1719      Using structured grid indexing
1720 
1721    Not Collective
1722 
1723    Input Parameters:
1724 +  mat - the matrix
1725 .  m - number of rows being entered
1726 .  idxm - grid coordinates for matrix rows being entered
1727 .  n - number of columns being entered
1728 .  idxn - grid coordinates for matrix columns being entered
1729 .  v - a logically two-dimensional array of values
1730 -  addv - either ADD_VALUES or INSERT_VALUES, where
1731    ADD_VALUES adds values to any existing entries, and
1732    INSERT_VALUES replaces existing entries with new values
1733 
1734    Notes:
1735    By default the values, v, are row-oriented and unsorted.
1736    See MatSetOption() for other options.
1737 
1738    Calls to MatSetValuesBlockedStencil() with the INSERT_VALUES and ADD_VALUES
1739    options cannot be mixed without intervening calls to the assembly
1740    routines.
1741 
1742    The grid coordinates are across the entire grid, not just the local portion
1743 
1744    MatSetValuesBlockedStencil() uses 0-based row and column numbers in Fortran
1745    as well as in C.
1746 
1747    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1748 
1749    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1750    or call MatSetBlockSize(), MatSetLocalToGlobalMapping() and MatSetStencil() first.
1751 
1752    The columns and rows in the stencil passed in MUST be contained within the
1753    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1754    if you create a DMDA with an overlap of one grid level and on a particular process its first
1755    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1756    first i index you can use in your column and row indices in MatSetStencil() is 5.
1757 
1758    In Fortran idxm and idxn should be declared as
1759 $     MatStencil idxm(4,m),idxn(4,n)
1760    and the values inserted using
1761 $    idxm(MatStencil_i,1) = i
1762 $    idxm(MatStencil_j,1) = j
1763 $    idxm(MatStencil_k,1) = k
1764    etc
1765 
1766    Negative indices may be passed in idxm and idxn, these rows and columns are
1767    simply ignored. This allows easily inserting element stiffness matrices
1768    with homogeneous Dirchlet boundary conditions that you don't want represented
1769    in the matrix.
1770 
1771    Inspired by the structured grid interface to the HYPRE package
1772    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1773 
1774    Level: beginner
1775 
1776 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1777           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1778           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1779 @*/
1780 PetscErrorCode MatSetValuesBlockedStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1781 {
1782   PetscInt       buf[8192],*bufm=NULL,*bufn=NULL,*jdxm,*jdxn;
1783   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1784   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1785 
1786   PetscFunctionBegin;
1787   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1788   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1789   PetscValidType(mat,1);
1790   PetscValidPointer(idxm,3);
1791   PetscValidPointer(idxn,5);
1792   PetscValidScalarPointer(v,6);
1793 
1794   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1795     jdxm = buf; jdxn = buf+m;
1796   } else {
1797     PetscCall(PetscMalloc2(m,&bufm,n,&bufn));
1798     jdxm = bufm; jdxn = bufn;
1799   }
1800   for (i=0; i<m; i++) {
1801     for (j=0; j<3-sdim; j++) dxm++;
1802     tmp = *dxm++ - starts[0];
1803     for (j=0; j<sdim-1; j++) {
1804       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1805       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1806     }
1807     dxm++;
1808     jdxm[i] = tmp;
1809   }
1810   for (i=0; i<n; i++) {
1811     for (j=0; j<3-sdim; j++) dxn++;
1812     tmp = *dxn++ - starts[0];
1813     for (j=0; j<sdim-1; j++) {
1814       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1815       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1816     }
1817     dxn++;
1818     jdxn[i] = tmp;
1819   }
1820   PetscCall(MatSetValuesBlockedLocal(mat,m,jdxm,n,jdxn,v,addv));
1821   PetscCall(PetscFree2(bufm,bufn));
1822   PetscFunctionReturn(0);
1823 }
1824 
1825 /*@
1826    MatSetStencil - Sets the grid information for setting values into a matrix via
1827         MatSetValuesStencil()
1828 
1829    Not Collective
1830 
1831    Input Parameters:
1832 +  mat - the matrix
1833 .  dim - dimension of the grid 1, 2, or 3
1834 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1835 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1836 -  dof - number of degrees of freedom per node
1837 
1838    Inspired by the structured grid interface to the HYPRE package
1839    (www.llnl.gov/CASC/hyper)
1840 
1841    For matrices generated with DMCreateMatrix() this routine is automatically called and so not needed by the
1842    user.
1843 
1844    Level: beginner
1845 
1846 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1847           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1848 @*/
1849 PetscErrorCode MatSetStencil(Mat mat,PetscInt dim,const PetscInt dims[],const PetscInt starts[],PetscInt dof)
1850 {
1851   PetscFunctionBegin;
1852   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1853   PetscValidIntPointer(dims,3);
1854   PetscValidIntPointer(starts,4);
1855 
1856   mat->stencil.dim = dim + (dof > 1);
1857   for (PetscInt i=0; i<dim; i++) {
1858     mat->stencil.dims[i]   = dims[dim-i-1];      /* copy the values in backwards */
1859     mat->stencil.starts[i] = starts[dim-i-1];
1860   }
1861   mat->stencil.dims[dim]   = dof;
1862   mat->stencil.starts[dim] = 0;
1863   mat->stencil.noc         = (PetscBool)(dof == 1);
1864   PetscFunctionReturn(0);
1865 }
1866 
1867 /*@C
1868    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1869 
1870    Not Collective
1871 
1872    Input Parameters:
1873 +  mat - the matrix
1874 .  v - a logically two-dimensional array of values
1875 .  m, idxm - the number of block rows and their global block indices
1876 .  n, idxn - the number of block columns and their global block indices
1877 -  addv - either ADD_VALUES or INSERT_VALUES, where
1878    ADD_VALUES adds values to any existing entries, and
1879    INSERT_VALUES replaces existing entries with new values
1880 
1881    Notes:
1882    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call
1883    MatXXXXSetPreallocation() or MatSetUp() before using this routine.
1884 
1885    The m and n count the NUMBER of blocks in the row direction and column direction,
1886    NOT the total number of rows/columns; for example, if the block size is 2 and
1887    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1888    The values in idxm would be 1 2; that is the first index for each block divided by
1889    the block size.
1890 
1891    Note that you must call MatSetBlockSize() when constructing this matrix (before
1892    preallocating it).
1893 
1894    By default the values, v, are row-oriented, so the layout of
1895    v is the same as for MatSetValues(). See MatSetOption() for other options.
1896 
1897    Calls to MatSetValuesBlocked() with the INSERT_VALUES and ADD_VALUES
1898    options cannot be mixed without intervening calls to the assembly
1899    routines.
1900 
1901    MatSetValuesBlocked() uses 0-based row and column numbers in Fortran
1902    as well as in C.
1903 
1904    Negative indices may be passed in idxm and idxn, these rows and columns are
1905    simply ignored. This allows easily inserting element stiffness matrices
1906    with homogeneous Dirchlet boundary conditions that you don't want represented
1907    in the matrix.
1908 
1909    Each time an entry is set within a sparse matrix via MatSetValues(),
1910    internal searching must be done to determine where to place the
1911    data in the matrix storage space.  By instead inserting blocks of
1912    entries via MatSetValuesBlocked(), the overhead of matrix assembly is
1913    reduced.
1914 
1915    Example:
1916 $   Suppose m=n=2 and block size(bs) = 2 The array is
1917 $
1918 $   1  2  | 3  4
1919 $   5  6  | 7  8
1920 $   - - - | - - -
1921 $   9  10 | 11 12
1922 $   13 14 | 15 16
1923 $
1924 $   v[] should be passed in like
1925 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1926 $
1927 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1928 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1929 
1930    Level: intermediate
1931 
1932 .seealso: `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1933 @*/
1934 PetscErrorCode MatSetValuesBlocked(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1935 {
1936   PetscFunctionBeginHot;
1937   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1938   PetscValidType(mat,1);
1939   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1940   PetscValidIntPointer(idxm,3);
1941   PetscValidIntPointer(idxn,5);
1942   MatCheckPreallocated(mat,1);
1943   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1944   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1945   if (PetscDefined(USE_DEBUG)) {
1946     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1947     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1948   }
1949   if (PetscDefined(USE_DEBUG)) {
1950     PetscInt rbs,cbs,M,N,i;
1951     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
1952     PetscCall(MatGetSize(mat,&M,&N));
1953     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);
1954     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);
1955   }
1956   if (mat->assembled) {
1957     mat->was_assembled = PETSC_TRUE;
1958     mat->assembled     = PETSC_FALSE;
1959   }
1960   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1961   if (mat->ops->setvaluesblocked) {
1962     PetscCall((*mat->ops->setvaluesblocked)(mat,m,idxm,n,idxn,v,addv));
1963   } else {
1964     PetscInt buf[8192],*bufr=NULL,*bufc=NULL,*iidxm,*iidxn;
1965     PetscInt i,j,bs,cbs;
1966 
1967     PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
1968     if (m*bs+n*cbs <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1969       iidxm = buf;
1970       iidxn = buf + m*bs;
1971     } else {
1972       PetscCall(PetscMalloc2(m*bs,&bufr,n*cbs,&bufc));
1973       iidxm = bufr;
1974       iidxn = bufc;
1975     }
1976     for (i=0; i<m; i++) {
1977       for (j=0; j<bs; j++) {
1978         iidxm[i*bs+j] = bs*idxm[i] + j;
1979       }
1980     }
1981     if (m != n || bs != cbs || idxm != idxn) {
1982       for (i=0; i<n; i++) {
1983         for (j=0; j<cbs; j++) {
1984           iidxn[i*cbs+j] = cbs*idxn[i] + j;
1985         }
1986       }
1987     } else iidxn = iidxm;
1988     PetscCall(MatSetValues(mat,m*bs,iidxm,n*cbs,iidxn,v,addv));
1989     PetscCall(PetscFree2(bufr,bufc));
1990   }
1991   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1992   PetscFunctionReturn(0);
1993 }
1994 
1995 /*@C
1996    MatGetValues - Gets a block of values from a matrix.
1997 
1998    Not Collective; can only return values that are owned by the give process
1999 
2000    Input Parameters:
2001 +  mat - the matrix
2002 .  v - a logically two-dimensional array for storing the values
2003 .  m, idxm - the number of rows and their global indices
2004 -  n, idxn - the number of columns and their global indices
2005 
2006    Notes:
2007      The user must allocate space (m*n PetscScalars) for the values, v.
2008      The values, v, are then returned in a row-oriented format,
2009      analogous to that used by default in MatSetValues().
2010 
2011      MatGetValues() uses 0-based row and column numbers in
2012      Fortran as well as in C.
2013 
2014      MatGetValues() requires that the matrix has been assembled
2015      with MatAssemblyBegin()/MatAssemblyEnd().  Thus, calls to
2016      MatSetValues() and MatGetValues() CANNOT be made in succession
2017      without intermediate matrix assembly.
2018 
2019      Negative row or column indices will be ignored and those locations in v[] will be
2020      left unchanged.
2021 
2022      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2023      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2024      from MatGetOwnershipRange(mat,&rstart,&rend).
2025 
2026    Level: advanced
2027 
2028 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2029 @*/
2030 PetscErrorCode MatGetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
2031 {
2032   PetscFunctionBegin;
2033   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2034   PetscValidType(mat,1);
2035   if (!m || !n) PetscFunctionReturn(0);
2036   PetscValidIntPointer(idxm,3);
2037   PetscValidIntPointer(idxn,5);
2038   PetscValidScalarPointer(v,6);
2039   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2040   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2041   PetscCheck(mat->ops->getvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2042   MatCheckPreallocated(mat,1);
2043 
2044   PetscCall(PetscLogEventBegin(MAT_GetValues,mat,0,0,0));
2045   PetscCall((*mat->ops->getvalues)(mat,m,idxm,n,idxn,v));
2046   PetscCall(PetscLogEventEnd(MAT_GetValues,mat,0,0,0));
2047   PetscFunctionReturn(0);
2048 }
2049 
2050 /*@C
2051    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2052      defined previously by MatSetLocalToGlobalMapping()
2053 
2054    Not Collective
2055 
2056    Input Parameters:
2057 +  mat - the matrix
2058 .  nrow, irow - number of rows and their local indices
2059 -  ncol, icol - number of columns and their local indices
2060 
2061    Output Parameter:
2062 .  y -  a logically two-dimensional array of values
2063 
2064    Notes:
2065      If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine.
2066 
2067      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,
2068      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from MatGetOwnershipRange(mat,&rstart,&rend). One can
2069      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the ISLocalToGlobalMapping set
2070      with MatSetLocalToGlobalMapping().
2071 
2072    Developer Notes:
2073       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2074       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2075 
2076    Level: advanced
2077 
2078 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2079           `MatSetValuesLocal()`, `MatGetValues()`
2080 @*/
2081 PetscErrorCode MatGetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],PetscScalar y[])
2082 {
2083   PetscFunctionBeginHot;
2084   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2085   PetscValidType(mat,1);
2086   MatCheckPreallocated(mat,1);
2087   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2088   PetscValidIntPointer(irow,3);
2089   PetscValidIntPointer(icol,5);
2090   if (PetscDefined(USE_DEBUG)) {
2091     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2092     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2093   }
2094   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2095   PetscCall(PetscLogEventBegin(MAT_GetValues,mat,0,0,0));
2096   if (mat->ops->getvalueslocal) {
2097     PetscCall((*mat->ops->getvalueslocal)(mat,nrow,irow,ncol,icol,y));
2098   } else {
2099     PetscInt buf[8192],*bufr=NULL,*bufc=NULL,*irowm,*icolm;
2100     if ((nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2101       irowm = buf; icolm = buf+nrow;
2102     } else {
2103       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2104       irowm = bufr; icolm = bufc;
2105     }
2106     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2107     PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2108     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,irowm));
2109     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,icolm));
2110     PetscCall(MatGetValues(mat,nrow,irowm,ncol,icolm,y));
2111     PetscCall(PetscFree2(bufr,bufc));
2112   }
2113   PetscCall(PetscLogEventEnd(MAT_GetValues,mat,0,0,0));
2114   PetscFunctionReturn(0);
2115 }
2116 
2117 /*@
2118   MatSetValuesBatch - Adds (ADD_VALUES) many blocks of values into a matrix at once. The blocks must all be square and
2119   the same size. Currently, this can only be called once and creates the given matrix.
2120 
2121   Not Collective
2122 
2123   Input Parameters:
2124 + mat - the matrix
2125 . nb - the number of blocks
2126 . bs - the number of rows (and columns) in each block
2127 . rows - a concatenation of the rows for each block
2128 - v - a concatenation of logically two-dimensional arrays of values
2129 
2130   Notes:
2131   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2132 
2133   Level: advanced
2134 
2135 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2136           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
2137 @*/
2138 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2139 {
2140   PetscFunctionBegin;
2141   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2142   PetscValidType(mat,1);
2143   PetscValidIntPointer(rows,4);
2144   PetscValidScalarPointer(v,5);
2145   PetscAssert(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2146 
2147   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch,mat,0,0,0));
2148   if (mat->ops->setvaluesbatch) {
2149     PetscCall((*mat->ops->setvaluesbatch)(mat,nb,bs,rows,v));
2150   } else {
2151     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b*bs], bs, &rows[b*bs], &v[b*bs*bs], ADD_VALUES));
2152   }
2153   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch,mat,0,0,0));
2154   PetscFunctionReturn(0);
2155 }
2156 
2157 /*@
2158    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2159    the routine MatSetValuesLocal() to allow users to insert matrix entries
2160    using a local (per-processor) numbering.
2161 
2162    Not Collective
2163 
2164    Input Parameters:
2165 +  x - the matrix
2166 .  rmapping - row mapping created with ISLocalToGlobalMappingCreate() or ISLocalToGlobalMappingCreateIS()
2167 -  cmapping - column mapping
2168 
2169    Level: intermediate
2170 
2171 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2172 @*/
2173 PetscErrorCode MatSetLocalToGlobalMapping(Mat x,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
2174 {
2175   PetscFunctionBegin;
2176   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
2177   PetscValidType(x,1);
2178   if (rmapping) PetscValidHeaderSpecific(rmapping,IS_LTOGM_CLASSID,2);
2179   if (cmapping) PetscValidHeaderSpecific(cmapping,IS_LTOGM_CLASSID,3);
2180   if (x->ops->setlocaltoglobalmapping) {
2181     PetscCall((*x->ops->setlocaltoglobalmapping)(x,rmapping,cmapping));
2182   } else {
2183     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap,rmapping));
2184     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap,cmapping));
2185   }
2186   PetscFunctionReturn(0);
2187 }
2188 
2189 /*@
2190    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by MatSetLocalToGlobalMapping()
2191 
2192    Not Collective
2193 
2194    Input Parameter:
2195 .  A - the matrix
2196 
2197    Output Parameters:
2198 + rmapping - row mapping
2199 - cmapping - column mapping
2200 
2201    Level: advanced
2202 
2203 .seealso: `MatSetValuesLocal()`
2204 @*/
2205 PetscErrorCode MatGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping)
2206 {
2207   PetscFunctionBegin;
2208   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2209   PetscValidType(A,1);
2210   if (rmapping) {
2211     PetscValidPointer(rmapping,2);
2212     *rmapping = A->rmap->mapping;
2213   }
2214   if (cmapping) {
2215     PetscValidPointer(cmapping,3);
2216     *cmapping = A->cmap->mapping;
2217   }
2218   PetscFunctionReturn(0);
2219 }
2220 
2221 /*@
2222    MatSetLayouts - Sets the PetscLayout objects for rows and columns of a matrix
2223 
2224    Logically Collective on A
2225 
2226    Input Parameters:
2227 +  A - the matrix
2228 . rmap - row layout
2229 - cmap - column layout
2230 
2231    Level: advanced
2232 
2233 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2234 @*/
2235 PetscErrorCode MatSetLayouts(Mat A,PetscLayout rmap,PetscLayout cmap)
2236 {
2237   PetscFunctionBegin;
2238   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2239   PetscCall(PetscLayoutReference(rmap,&A->rmap));
2240   PetscCall(PetscLayoutReference(cmap,&A->cmap));
2241   PetscFunctionReturn(0);
2242 }
2243 
2244 /*@
2245    MatGetLayouts - Gets the PetscLayout objects for rows and columns
2246 
2247    Not Collective
2248 
2249    Input Parameter:
2250 .  A - the matrix
2251 
2252    Output Parameters:
2253 + rmap - row layout
2254 - cmap - column layout
2255 
2256    Level: advanced
2257 
2258 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2259 @*/
2260 PetscErrorCode MatGetLayouts(Mat A,PetscLayout *rmap,PetscLayout *cmap)
2261 {
2262   PetscFunctionBegin;
2263   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2264   PetscValidType(A,1);
2265   if (rmap) {
2266     PetscValidPointer(rmap,2);
2267     *rmap = A->rmap;
2268   }
2269   if (cmap) {
2270     PetscValidPointer(cmap,3);
2271     *cmap = A->cmap;
2272   }
2273   PetscFunctionReturn(0);
2274 }
2275 
2276 /*@C
2277    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2278    using a local numbering of the nodes.
2279 
2280    Not Collective
2281 
2282    Input Parameters:
2283 +  mat - the matrix
2284 .  nrow, irow - number of rows and their local indices
2285 .  ncol, icol - number of columns and their local indices
2286 .  y -  a logically two-dimensional array of values
2287 -  addv - either INSERT_VALUES or ADD_VALUES, where
2288    ADD_VALUES adds values to any existing entries, and
2289    INSERT_VALUES replaces existing entries with new values
2290 
2291    Notes:
2292    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2293       MatSetUp() before using this routine
2294 
2295    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine
2296 
2297    Calls to MatSetValuesLocal() with the INSERT_VALUES and ADD_VALUES
2298    options cannot be mixed without intervening calls to the assembly
2299    routines.
2300 
2301    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2302    MUST be called after all calls to MatSetValuesLocal() have been completed.
2303 
2304    Level: intermediate
2305 
2306    Developer Notes:
2307     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2308                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2309 
2310 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2311           `MatSetValueLocal()`, `MatGetValuesLocal()`
2312 @*/
2313 PetscErrorCode MatSetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2314 {
2315   PetscFunctionBeginHot;
2316   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2317   PetscValidType(mat,1);
2318   MatCheckPreallocated(mat,1);
2319   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2320   PetscValidIntPointer(irow,3);
2321   PetscValidIntPointer(icol,5);
2322   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2323   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2324   if (PetscDefined(USE_DEBUG)) {
2325     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2326     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2327   }
2328 
2329   if (mat->assembled) {
2330     mat->was_assembled = PETSC_TRUE;
2331     mat->assembled     = PETSC_FALSE;
2332   }
2333   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
2334   if (mat->ops->setvalueslocal) {
2335     PetscCall((*mat->ops->setvalueslocal)(mat,nrow,irow,ncol,icol,y,addv));
2336   } else {
2337     PetscInt       buf[8192],*bufr=NULL,*bufc=NULL;
2338     const PetscInt *irowm,*icolm;
2339 
2340     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2341       bufr  = buf;
2342       bufc  = buf + nrow;
2343       irowm = bufr;
2344       icolm = bufc;
2345     } else {
2346       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2347       irowm = bufr;
2348       icolm = bufc;
2349     }
2350     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,bufr));
2351     else irowm = irow;
2352     if (mat->cmap->mapping) {
2353       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2354         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,bufc));
2355       } else icolm = irowm;
2356     } else icolm = icol;
2357     PetscCall(MatSetValues(mat,nrow,irowm,ncol,icolm,y,addv));
2358     if (bufr != buf) PetscCall(PetscFree2(bufr,bufc));
2359   }
2360   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
2361   PetscFunctionReturn(0);
2362 }
2363 
2364 /*@C
2365    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2366    using a local ordering of the nodes a block at a time.
2367 
2368    Not Collective
2369 
2370    Input Parameters:
2371 +  x - the matrix
2372 .  nrow, irow - number of rows and their local indices
2373 .  ncol, icol - number of columns and their local indices
2374 .  y -  a logically two-dimensional array of values
2375 -  addv - either INSERT_VALUES or ADD_VALUES, where
2376    ADD_VALUES adds values to any existing entries, and
2377    INSERT_VALUES replaces existing entries with new values
2378 
2379    Notes:
2380    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2381       MatSetUp() before using this routine
2382 
2383    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetBlockSize() and MatSetLocalToGlobalMapping()
2384       before using this routineBefore calling MatSetValuesLocal(), the user must first set the
2385 
2386    Calls to MatSetValuesBlockedLocal() with the INSERT_VALUES and ADD_VALUES
2387    options cannot be mixed without intervening calls to the assembly
2388    routines.
2389 
2390    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2391    MUST be called after all calls to MatSetValuesBlockedLocal() have been completed.
2392 
2393    Level: intermediate
2394 
2395    Developer Notes:
2396     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2397                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2398 
2399 .seealso: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2400           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2401 @*/
2402 PetscErrorCode MatSetValuesBlockedLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2403 {
2404   PetscFunctionBeginHot;
2405   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2406   PetscValidType(mat,1);
2407   MatCheckPreallocated(mat,1);
2408   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2409   PetscValidIntPointer(irow,3);
2410   PetscValidIntPointer(icol,5);
2411   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2412   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2413   if (PetscDefined(USE_DEBUG)) {
2414     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2415     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);
2416   }
2417 
2418   if (mat->assembled) {
2419     mat->was_assembled = PETSC_TRUE;
2420     mat->assembled     = PETSC_FALSE;
2421   }
2422   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2423     PetscInt irbs, rbs;
2424     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2425     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&irbs));
2426     PetscCheck(rbs == irbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT,rbs,irbs);
2427   }
2428   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2429     PetscInt icbs, cbs;
2430     PetscCall(MatGetBlockSizes(mat,NULL,&cbs));
2431     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&icbs));
2432     PetscCheck(cbs == icbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT,cbs,icbs);
2433   }
2434   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
2435   if (mat->ops->setvaluesblockedlocal) {
2436     PetscCall((*mat->ops->setvaluesblockedlocal)(mat,nrow,irow,ncol,icol,y,addv));
2437   } else {
2438     PetscInt       buf[8192],*bufr=NULL,*bufc=NULL;
2439     const PetscInt *irowm,*icolm;
2440 
2441     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2442       bufr  = buf;
2443       bufc  = buf + nrow;
2444       irowm = bufr;
2445       icolm = bufc;
2446     } else {
2447       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2448       irowm = bufr;
2449       icolm = bufc;
2450     }
2451     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping,nrow,irow,bufr));
2452     else irowm = irow;
2453     if (mat->cmap->mapping) {
2454       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2455         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping,ncol,icol,bufc));
2456       } else icolm = irowm;
2457     } else icolm = icol;
2458     PetscCall(MatSetValuesBlocked(mat,nrow,irowm,ncol,icolm,y,addv));
2459     if (bufr != buf) PetscCall(PetscFree2(bufr,bufc));
2460   }
2461   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
2462   PetscFunctionReturn(0);
2463 }
2464 
2465 /*@
2466    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2467 
2468    Collective on Mat
2469 
2470    Input Parameters:
2471 +  mat - the matrix
2472 -  x   - the vector to be multiplied
2473 
2474    Output Parameters:
2475 .  y - the result
2476 
2477    Notes:
2478    The vectors x and y cannot be the same.  I.e., one cannot
2479    call MatMult(A,y,y).
2480 
2481    Level: developer
2482 
2483 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2484 @*/
2485 PetscErrorCode MatMultDiagonalBlock(Mat mat,Vec x,Vec y)
2486 {
2487   PetscFunctionBegin;
2488   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2489   PetscValidType(mat,1);
2490   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2491   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2492 
2493   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2494   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2495   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2496   MatCheckPreallocated(mat,1);
2497 
2498   PetscCheck(mat->ops->multdiagonalblock,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply defined",((PetscObject)mat)->type_name);
2499   PetscCall((*mat->ops->multdiagonalblock)(mat,x,y));
2500   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2501   PetscFunctionReturn(0);
2502 }
2503 
2504 /* --------------------------------------------------------*/
2505 /*@
2506    MatMult - Computes the matrix-vector product, y = Ax.
2507 
2508    Neighbor-wise Collective on Mat
2509 
2510    Input Parameters:
2511 +  mat - the matrix
2512 -  x   - the vector to be multiplied
2513 
2514    Output Parameters:
2515 .  y - the result
2516 
2517    Notes:
2518    The vectors x and y cannot be the same.  I.e., one cannot
2519    call MatMult(A,y,y).
2520 
2521    Level: beginner
2522 
2523 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2524 @*/
2525 PetscErrorCode MatMult(Mat mat,Vec x,Vec y)
2526 {
2527   PetscFunctionBegin;
2528   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2529   PetscValidType(mat,1);
2530   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2531   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2532   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2533   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2534   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2535   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);
2536   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);
2537   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);
2538   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);
2539   PetscCall(VecSetErrorIfLocked(y,3));
2540   if (mat->erroriffailure) PetscCall(VecValidValues(x,2,PETSC_TRUE));
2541   MatCheckPreallocated(mat,1);
2542 
2543   PetscCall(VecLockReadPush(x));
2544   PetscCheck(mat->ops->mult,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply defined",((PetscObject)mat)->type_name);
2545   PetscCall(PetscLogEventBegin(MAT_Mult,mat,x,y,0));
2546   PetscCall((*mat->ops->mult)(mat,x,y));
2547   PetscCall(PetscLogEventEnd(MAT_Mult,mat,x,y,0));
2548   if (mat->erroriffailure) PetscCall(VecValidValues(y,3,PETSC_FALSE));
2549   PetscCall(VecLockReadPop(x));
2550   PetscFunctionReturn(0);
2551 }
2552 
2553 /*@
2554    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2555 
2556    Neighbor-wise Collective on Mat
2557 
2558    Input Parameters:
2559 +  mat - the matrix
2560 -  x   - the vector to be multiplied
2561 
2562    Output Parameters:
2563 .  y - the result
2564 
2565    Notes:
2566    The vectors x and y cannot be the same.  I.e., one cannot
2567    call MatMultTranspose(A,y,y).
2568 
2569    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2570    use MatMultHermitianTranspose()
2571 
2572    Level: beginner
2573 
2574 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2575 @*/
2576 PetscErrorCode MatMultTranspose(Mat mat,Vec x,Vec y)
2577 {
2578   PetscErrorCode (*op)(Mat,Vec,Vec) = NULL;
2579 
2580   PetscFunctionBegin;
2581   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2582   PetscValidType(mat,1);
2583   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2584   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2585 
2586   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2587   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2588   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2589   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);
2590   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);
2591   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);
2592   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);
2593   if (mat->erroriffailure) PetscCall(VecValidValues(x,2,PETSC_TRUE));
2594   MatCheckPreallocated(mat,1);
2595 
2596   if (!mat->ops->multtranspose) {
2597     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2598     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);
2599   } else op = mat->ops->multtranspose;
2600   PetscCall(PetscLogEventBegin(MAT_MultTranspose,mat,x,y,0));
2601   PetscCall(VecLockReadPush(x));
2602   PetscCall((*op)(mat,x,y));
2603   PetscCall(VecLockReadPop(x));
2604   PetscCall(PetscLogEventEnd(MAT_MultTranspose,mat,x,y,0));
2605   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2606   if (mat->erroriffailure) PetscCall(VecValidValues(y,3,PETSC_FALSE));
2607   PetscFunctionReturn(0);
2608 }
2609 
2610 /*@
2611    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2612 
2613    Neighbor-wise Collective on Mat
2614 
2615    Input Parameters:
2616 +  mat - the matrix
2617 -  x   - the vector to be multilplied
2618 
2619    Output Parameters:
2620 .  y - the result
2621 
2622    Notes:
2623    The vectors x and y cannot be the same.  I.e., one cannot
2624    call MatMultHermitianTranspose(A,y,y).
2625 
2626    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2627 
2628    For real numbers MatMultTranspose() and MatMultHermitianTranspose() are identical.
2629 
2630    Level: beginner
2631 
2632 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2633 @*/
2634 PetscErrorCode MatMultHermitianTranspose(Mat mat,Vec x,Vec y)
2635 {
2636   PetscFunctionBegin;
2637   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2638   PetscValidType(mat,1);
2639   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2640   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2641 
2642   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2643   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2644   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2645   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);
2646   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);
2647   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);
2648   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);
2649   MatCheckPreallocated(mat,1);
2650 
2651   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose,mat,x,y,0));
2652 #if defined(PETSC_USE_COMPLEX)
2653   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2654     PetscCall(VecLockReadPush(x));
2655     if (mat->ops->multhermitiantranspose) {
2656       PetscCall((*mat->ops->multhermitiantranspose)(mat,x,y));
2657     } else {
2658       PetscCall((*mat->ops->mult)(mat,x,y));
2659     }
2660     PetscCall(VecLockReadPop(x));
2661   } else {
2662     Vec w;
2663     PetscCall(VecDuplicate(x,&w));
2664     PetscCall(VecCopy(x,w));
2665     PetscCall(VecConjugate(w));
2666     PetscCall(MatMultTranspose(mat,w,y));
2667     PetscCall(VecDestroy(&w));
2668     PetscCall(VecConjugate(y));
2669   }
2670   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2671 #else
2672   PetscCall(MatMultTranspose(mat,x,y));
2673 #endif
2674   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose,mat,x,y,0));
2675   PetscFunctionReturn(0);
2676 }
2677 
2678 /*@
2679     MatMultAdd -  Computes v3 = v2 + A * v1.
2680 
2681     Neighbor-wise Collective on Mat
2682 
2683     Input Parameters:
2684 +   mat - the matrix
2685 -   v1, v2 - the vectors
2686 
2687     Output Parameters:
2688 .   v3 - the result
2689 
2690     Notes:
2691     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2692     call MatMultAdd(A,v1,v2,v1).
2693 
2694     Level: beginner
2695 
2696 .seealso: `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2697 @*/
2698 PetscErrorCode MatMultAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2699 {
2700   PetscFunctionBegin;
2701   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2702   PetscValidType(mat,1);
2703   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2704   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2705   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2706 
2707   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2708   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2709   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);
2710   /* 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);
2711      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); */
2712   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);
2713   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);
2714   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2715   MatCheckPreallocated(mat,1);
2716 
2717   PetscCheck(mat->ops->multadd,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No MatMultAdd() for matrix type %s",((PetscObject)mat)->type_name);
2718   PetscCall(PetscLogEventBegin(MAT_MultAdd,mat,v1,v2,v3));
2719   PetscCall(VecLockReadPush(v1));
2720   PetscCall((*mat->ops->multadd)(mat,v1,v2,v3));
2721   PetscCall(VecLockReadPop(v1));
2722   PetscCall(PetscLogEventEnd(MAT_MultAdd,mat,v1,v2,v3));
2723   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2724   PetscFunctionReturn(0);
2725 }
2726 
2727 /*@
2728    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2729 
2730    Neighbor-wise Collective on Mat
2731 
2732    Input Parameters:
2733 +  mat - the matrix
2734 -  v1, v2 - the vectors
2735 
2736    Output Parameters:
2737 .  v3 - the result
2738 
2739    Notes:
2740    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2741    call MatMultTransposeAdd(A,v1,v2,v1).
2742 
2743    Level: beginner
2744 
2745 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2746 @*/
2747 PetscErrorCode MatMultTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2748 {
2749   PetscErrorCode (*op)(Mat,Vec,Vec,Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2750 
2751   PetscFunctionBegin;
2752   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2753   PetscValidType(mat,1);
2754   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2755   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2756   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2757 
2758   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2759   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2760   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);
2761   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);
2762   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);
2763   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2764   PetscCheck(op,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2765   MatCheckPreallocated(mat,1);
2766 
2767   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd,mat,v1,v2,v3));
2768   PetscCall(VecLockReadPush(v1));
2769   PetscCall((*op)(mat,v1,v2,v3));
2770   PetscCall(VecLockReadPop(v1));
2771   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd,mat,v1,v2,v3));
2772   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2773   PetscFunctionReturn(0);
2774 }
2775 
2776 /*@
2777    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2778 
2779    Neighbor-wise Collective on Mat
2780 
2781    Input Parameters:
2782 +  mat - the matrix
2783 -  v1, v2 - the vectors
2784 
2785    Output Parameters:
2786 .  v3 - the result
2787 
2788    Notes:
2789    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2790    call MatMultHermitianTransposeAdd(A,v1,v2,v1).
2791 
2792    Level: beginner
2793 
2794 .seealso: `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2795 @*/
2796 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2797 {
2798   PetscFunctionBegin;
2799   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2800   PetscValidType(mat,1);
2801   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2802   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2803   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2804 
2805   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2806   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2807   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2808   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);
2809   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);
2810   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);
2811   MatCheckPreallocated(mat,1);
2812 
2813   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3));
2814   PetscCall(VecLockReadPush(v1));
2815   if (mat->ops->multhermitiantransposeadd) {
2816     PetscCall((*mat->ops->multhermitiantransposeadd)(mat,v1,v2,v3));
2817   } else {
2818     Vec w,z;
2819     PetscCall(VecDuplicate(v1,&w));
2820     PetscCall(VecCopy(v1,w));
2821     PetscCall(VecConjugate(w));
2822     PetscCall(VecDuplicate(v3,&z));
2823     PetscCall(MatMultTranspose(mat,w,z));
2824     PetscCall(VecDestroy(&w));
2825     PetscCall(VecConjugate(z));
2826     if (v2 != v3) {
2827       PetscCall(VecWAXPY(v3,1.0,v2,z));
2828     } else {
2829       PetscCall(VecAXPY(v3,1.0,z));
2830     }
2831     PetscCall(VecDestroy(&z));
2832   }
2833   PetscCall(VecLockReadPop(v1));
2834   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3));
2835   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2836   PetscFunctionReturn(0);
2837 }
2838 
2839 /*@C
2840    MatGetFactorType - gets the type of factorization it is
2841 
2842    Not Collective
2843 
2844    Input Parameters:
2845 .  mat - the matrix
2846 
2847    Output Parameters:
2848 .  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2849 
2850    Level: intermediate
2851 
2852 .seealso: `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`
2853 @*/
2854 PetscErrorCode MatGetFactorType(Mat mat,MatFactorType *t)
2855 {
2856   PetscFunctionBegin;
2857   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2858   PetscValidType(mat,1);
2859   PetscValidPointer(t,2);
2860   *t = mat->factortype;
2861   PetscFunctionReturn(0);
2862 }
2863 
2864 /*@C
2865    MatSetFactorType - sets the type of factorization it is
2866 
2867    Logically Collective on Mat
2868 
2869    Input Parameters:
2870 +  mat - the matrix
2871 -  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2872 
2873    Level: intermediate
2874 
2875 .seealso: `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`
2876 @*/
2877 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2878 {
2879   PetscFunctionBegin;
2880   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2881   PetscValidType(mat,1);
2882   mat->factortype = t;
2883   PetscFunctionReturn(0);
2884 }
2885 
2886 /* ------------------------------------------------------------*/
2887 /*@C
2888    MatGetInfo - Returns information about matrix storage (number of
2889    nonzeros, memory, etc.).
2890 
2891    Collective on Mat if MAT_GLOBAL_MAX or MAT_GLOBAL_SUM is used as the flag
2892 
2893    Input Parameter:
2894 .  mat - the matrix
2895 
2896    Output Parameters:
2897 +  flag - flag indicating the type of parameters to be returned
2898    (MAT_LOCAL - local matrix, MAT_GLOBAL_MAX - maximum over all processors,
2899    MAT_GLOBAL_SUM - sum over all processors)
2900 -  info - matrix information context
2901 
2902    Notes:
2903    The MatInfo context contains a variety of matrix data, including
2904    number of nonzeros allocated and used, number of mallocs during
2905    matrix assembly, etc.  Additional information for factored matrices
2906    is provided (such as the fill ratio, number of mallocs during
2907    factorization, etc.).  Much of this info is printed to PETSC_STDOUT
2908    when using the runtime options
2909 $       -info -mat_view ::ascii_info
2910 
2911    Example for C/C++ Users:
2912    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2913    data within the MatInfo context.  For example,
2914 .vb
2915       MatInfo info;
2916       Mat     A;
2917       double  mal, nz_a, nz_u;
2918 
2919       MatGetInfo(A,MAT_LOCAL,&info);
2920       mal  = info.mallocs;
2921       nz_a = info.nz_allocated;
2922 .ve
2923 
2924    Example for Fortran Users:
2925    Fortran users should declare info as a double precision
2926    array of dimension MAT_INFO_SIZE, and then extract the parameters
2927    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2928    a complete list of parameter names.
2929 .vb
2930       double  precision info(MAT_INFO_SIZE)
2931       double  precision mal, nz_a
2932       Mat     A
2933       integer ierr
2934 
2935       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2936       mal = info(MAT_INFO_MALLOCS)
2937       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2938 .ve
2939 
2940     Level: intermediate
2941 
2942     Developer Note: fortran interface is not autogenerated as the f90
2943     interface definition cannot be generated correctly [due to MatInfo]
2944 
2945 .seealso: `MatStashGetInfo()`
2946 
2947 @*/
2948 PetscErrorCode MatGetInfo(Mat mat,MatInfoType flag,MatInfo *info)
2949 {
2950   PetscFunctionBegin;
2951   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2952   PetscValidType(mat,1);
2953   PetscValidPointer(info,3);
2954   PetscCheck(mat->ops->getinfo,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2955   MatCheckPreallocated(mat,1);
2956   PetscCall((*mat->ops->getinfo)(mat,flag,info));
2957   PetscFunctionReturn(0);
2958 }
2959 
2960 /*
2961    This is used by external packages where it is not easy to get the info from the actual
2962    matrix factorization.
2963 */
2964 PetscErrorCode MatGetInfo_External(Mat A,MatInfoType flag,MatInfo *info)
2965 {
2966   PetscFunctionBegin;
2967   PetscCall(PetscMemzero(info,sizeof(MatInfo)));
2968   PetscFunctionReturn(0);
2969 }
2970 
2971 /* ----------------------------------------------------------*/
2972 
2973 /*@C
2974    MatLUFactor - Performs in-place LU factorization of matrix.
2975 
2976    Collective on Mat
2977 
2978    Input Parameters:
2979 +  mat - the matrix
2980 .  row - row permutation
2981 .  col - column permutation
2982 -  info - options for factorization, includes
2983 $          fill - expected fill as ratio of original fill.
2984 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2985 $                   Run with the option -info to determine an optimal value to use
2986 
2987    Notes:
2988    Most users should employ the simplified KSP interface for linear solvers
2989    instead of working directly with matrix algebra routines such as this.
2990    See, e.g., KSPCreate().
2991 
2992    This changes the state of the matrix to a factored matrix; it cannot be used
2993    for example with MatSetValues() unless one first calls MatSetUnfactored().
2994 
2995    Level: developer
2996 
2997 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2998           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2999 
3000     Developer Note: fortran interface is not autogenerated as the f90
3001     interface definition cannot be generated correctly [due to MatFactorInfo]
3002 
3003 @*/
3004 PetscErrorCode MatLUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
3005 {
3006   MatFactorInfo  tinfo;
3007 
3008   PetscFunctionBegin;
3009   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3010   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
3011   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3012   if (info) PetscValidPointer(info,4);
3013   PetscValidType(mat,1);
3014   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3015   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3016   PetscCheck(mat->ops->lufactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3017   MatCheckPreallocated(mat,1);
3018   if (!info) {
3019     PetscCall(MatFactorInfoInitialize(&tinfo));
3020     info = &tinfo;
3021   }
3022 
3023   PetscCall(PetscLogEventBegin(MAT_LUFactor,mat,row,col,0));
3024   PetscCall((*mat->ops->lufactor)(mat,row,col,info));
3025   PetscCall(PetscLogEventEnd(MAT_LUFactor,mat,row,col,0));
3026   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3027   PetscFunctionReturn(0);
3028 }
3029 
3030 /*@C
3031    MatILUFactor - Performs in-place ILU factorization of matrix.
3032 
3033    Collective on Mat
3034 
3035    Input Parameters:
3036 +  mat - the matrix
3037 .  row - row permutation
3038 .  col - column permutation
3039 -  info - structure containing
3040 $      levels - number of levels of fill.
3041 $      expected fill - as ratio of original fill.
3042 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3043                 missing diagonal entries)
3044 
3045    Notes:
3046    Probably really in-place only when level of fill is zero, otherwise allocates
3047    new space to store factored matrix and deletes previous memory.
3048 
3049    Most users should employ the simplified KSP interface for linear solvers
3050    instead of working directly with matrix algebra routines such as this.
3051    See, e.g., KSPCreate().
3052 
3053    Level: developer
3054 
3055 .seealso: `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3056 
3057     Developer Note: fortran interface is not autogenerated as the f90
3058     interface definition cannot be generated correctly [due to MatFactorInfo]
3059 
3060 @*/
3061 PetscErrorCode MatILUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
3062 {
3063   PetscFunctionBegin;
3064   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3065   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
3066   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3067   PetscValidPointer(info,4);
3068   PetscValidType(mat,1);
3069   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
3070   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3071   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3072   PetscCheck(mat->ops->ilufactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3073   MatCheckPreallocated(mat,1);
3074 
3075   PetscCall(PetscLogEventBegin(MAT_ILUFactor,mat,row,col,0));
3076   PetscCall((*mat->ops->ilufactor)(mat,row,col,info));
3077   PetscCall(PetscLogEventEnd(MAT_ILUFactor,mat,row,col,0));
3078   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3079   PetscFunctionReturn(0);
3080 }
3081 
3082 /*@C
3083    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3084    Call this routine before calling MatLUFactorNumeric().
3085 
3086    Collective on Mat
3087 
3088    Input Parameters:
3089 +  fact - the factor matrix obtained with MatGetFactor()
3090 .  mat - the matrix
3091 .  row, col - row and column permutations
3092 -  info - options for factorization, includes
3093 $          fill - expected fill as ratio of original fill.
3094 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3095 $                   Run with the option -info to determine an optimal value to use
3096 
3097    Notes:
3098     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
3099 
3100    Most users should employ the simplified KSP interface for linear solvers
3101    instead of working directly with matrix algebra routines such as this.
3102    See, e.g., KSPCreate().
3103 
3104    Level: developer
3105 
3106 .seealso: `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3107 
3108     Developer Note: fortran interface is not autogenerated as the f90
3109     interface definition cannot be generated correctly [due to MatFactorInfo]
3110 
3111 @*/
3112 PetscErrorCode MatLUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
3113 {
3114   MatFactorInfo  tinfo;
3115 
3116   PetscFunctionBegin;
3117   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3118   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
3119   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
3120   if (info) PetscValidPointer(info,5);
3121   PetscValidType(mat,2);
3122   PetscValidPointer(fact,1);
3123   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3124   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3125   if (!(fact)->ops->lufactorsymbolic) {
3126     MatSolverType stype;
3127     PetscCall(MatFactorGetSolverType(fact,&stype));
3128     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic LU using solver package %s",((PetscObject)mat)->type_name,stype);
3129   }
3130   MatCheckPreallocated(mat,2);
3131   if (!info) {
3132     PetscCall(MatFactorInfoInitialize(&tinfo));
3133     info = &tinfo;
3134   }
3135 
3136   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic,mat,row,col,0));
3137   PetscCall((fact->ops->lufactorsymbolic)(fact,mat,row,col,info));
3138   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic,mat,row,col,0));
3139   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3140   PetscFunctionReturn(0);
3141 }
3142 
3143 /*@C
3144    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3145    Call this routine after first calling MatLUFactorSymbolic().
3146 
3147    Collective on Mat
3148 
3149    Input Parameters:
3150 +  fact - the factor matrix obtained with MatGetFactor()
3151 .  mat - the matrix
3152 -  info - options for factorization
3153 
3154    Notes:
3155    See MatLUFactor() for in-place factorization.  See
3156    MatCholeskyFactorNumeric() for the symmetric, positive definite case.
3157 
3158    Most users should employ the simplified KSP interface for linear solvers
3159    instead of working directly with matrix algebra routines such as this.
3160    See, e.g., KSPCreate().
3161 
3162    Level: developer
3163 
3164 .seealso: `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3165 
3166     Developer Note: fortran interface is not autogenerated as the f90
3167     interface definition cannot be generated correctly [due to MatFactorInfo]
3168 
3169 @*/
3170 PetscErrorCode MatLUFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3171 {
3172   MatFactorInfo  tinfo;
3173 
3174   PetscFunctionBegin;
3175   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3176   PetscValidType(mat,2);
3177   PetscValidPointer(fact,1);
3178   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3179   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3180   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);
3181 
3182   PetscCheck((fact)->ops->lufactornumeric,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric LU",((PetscObject)mat)->type_name);
3183   MatCheckPreallocated(mat,2);
3184   if (!info) {
3185     PetscCall(MatFactorInfoInitialize(&tinfo));
3186     info = &tinfo;
3187   }
3188 
3189   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric,mat,fact,0,0));
3190   else PetscCall(PetscLogEventBegin(MAT_LUFactor,mat,fact,0,0));
3191   PetscCall((fact->ops->lufactornumeric)(fact,mat,info));
3192   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric,mat,fact,0,0));
3193   else PetscCall(PetscLogEventEnd(MAT_LUFactor,mat,fact,0,0));
3194   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3195   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3196   PetscFunctionReturn(0);
3197 }
3198 
3199 /*@C
3200    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3201    symmetric matrix.
3202 
3203    Collective on Mat
3204 
3205    Input Parameters:
3206 +  mat - the matrix
3207 .  perm - row and column permutations
3208 -  f - expected fill as ratio of original fill
3209 
3210    Notes:
3211    See MatLUFactor() for the nonsymmetric case.  See also
3212    MatCholeskyFactorSymbolic(), and MatCholeskyFactorNumeric().
3213 
3214    Most users should employ the simplified KSP interface for linear solvers
3215    instead of working directly with matrix algebra routines such as this.
3216    See, e.g., KSPCreate().
3217 
3218    Level: developer
3219 
3220 .seealso: `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3221           `MatGetOrdering()`
3222 
3223     Developer Note: fortran interface is not autogenerated as the f90
3224     interface definition cannot be generated correctly [due to MatFactorInfo]
3225 
3226 @*/
3227 PetscErrorCode MatCholeskyFactor(Mat mat,IS perm,const MatFactorInfo *info)
3228 {
3229   MatFactorInfo  tinfo;
3230 
3231   PetscFunctionBegin;
3232   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3233   PetscValidType(mat,1);
3234   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,2);
3235   if (info) PetscValidPointer(info,3);
3236   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3237   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3238   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3239   PetscCheck(mat->ops->choleskyfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"In-place factorization for Mat type %s is not supported, try out-of-place factorization. See MatCholeskyFactorSymbolic/Numeric",((PetscObject)mat)->type_name);
3240   MatCheckPreallocated(mat,1);
3241   if (!info) {
3242     PetscCall(MatFactorInfoInitialize(&tinfo));
3243     info = &tinfo;
3244   }
3245 
3246   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor,mat,perm,0,0));
3247   PetscCall((*mat->ops->choleskyfactor)(mat,perm,info));
3248   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor,mat,perm,0,0));
3249   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3250   PetscFunctionReturn(0);
3251 }
3252 
3253 /*@C
3254    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3255    of a symmetric matrix.
3256 
3257    Collective on Mat
3258 
3259    Input Parameters:
3260 +  fact - the factor matrix obtained with MatGetFactor()
3261 .  mat - the matrix
3262 .  perm - row and column permutations
3263 -  info - options for factorization, includes
3264 $          fill - expected fill as ratio of original fill.
3265 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3266 $                   Run with the option -info to determine an optimal value to use
3267 
3268    Notes:
3269    See MatLUFactorSymbolic() for the nonsymmetric case.  See also
3270    MatCholeskyFactor() and MatCholeskyFactorNumeric().
3271 
3272    Most users should employ the simplified KSP interface for linear solvers
3273    instead of working directly with matrix algebra routines such as this.
3274    See, e.g., KSPCreate().
3275 
3276    Level: developer
3277 
3278 .seealso: `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3279           `MatGetOrdering()`
3280 
3281     Developer Note: fortran interface is not autogenerated as the f90
3282     interface definition cannot be generated correctly [due to MatFactorInfo]
3283 
3284 @*/
3285 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
3286 {
3287   MatFactorInfo  tinfo;
3288 
3289   PetscFunctionBegin;
3290   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3291   PetscValidType(mat,2);
3292   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
3293   if (info) PetscValidPointer(info,4);
3294   PetscValidPointer(fact,1);
3295   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3296   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3297   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3298   if (!(fact)->ops->choleskyfactorsymbolic) {
3299     MatSolverType stype;
3300     PetscCall(MatFactorGetSolverType(fact,&stype));
3301     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s symbolic factor Cholesky using solver package %s",((PetscObject)mat)->type_name,stype);
3302   }
3303   MatCheckPreallocated(mat,2);
3304   if (!info) {
3305     PetscCall(MatFactorInfoInitialize(&tinfo));
3306     info = &tinfo;
3307   }
3308 
3309   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic,mat,perm,0,0));
3310   PetscCall((fact->ops->choleskyfactorsymbolic)(fact,mat,perm,info));
3311   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic,mat,perm,0,0));
3312   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3313   PetscFunctionReturn(0);
3314 }
3315 
3316 /*@C
3317    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3318    of a symmetric matrix. Call this routine after first calling
3319    MatCholeskyFactorSymbolic().
3320 
3321    Collective on Mat
3322 
3323    Input Parameters:
3324 +  fact - the factor matrix obtained with MatGetFactor()
3325 .  mat - the initial matrix
3326 .  info - options for factorization
3327 -  fact - the symbolic factor of mat
3328 
3329    Notes:
3330    Most users should employ the simplified KSP interface for linear solvers
3331    instead of working directly with matrix algebra routines such as this.
3332    See, e.g., KSPCreate().
3333 
3334    Level: developer
3335 
3336 .seealso: `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3337 
3338     Developer Note: fortran interface is not autogenerated as the f90
3339     interface definition cannot be generated correctly [due to MatFactorInfo]
3340 
3341 @*/
3342 PetscErrorCode MatCholeskyFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3343 {
3344   MatFactorInfo  tinfo;
3345 
3346   PetscFunctionBegin;
3347   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3348   PetscValidType(mat,2);
3349   PetscValidPointer(fact,1);
3350   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3351   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3352   PetscCheck((fact)->ops->choleskyfactornumeric,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric factor Cholesky",((PetscObject)mat)->type_name);
3353   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);
3354   MatCheckPreallocated(mat,2);
3355   if (!info) {
3356     PetscCall(MatFactorInfoInitialize(&tinfo));
3357     info = &tinfo;
3358   }
3359 
3360   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric,mat,fact,0,0));
3361   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor,mat,fact,0,0));
3362   PetscCall((fact->ops->choleskyfactornumeric)(fact,mat,info));
3363   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric,mat,fact,0,0));
3364   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor,mat,fact,0,0));
3365   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3366   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3367   PetscFunctionReturn(0);
3368 }
3369 
3370 /*@
3371    MatQRFactor - Performs in-place QR factorization of matrix.
3372 
3373    Collective on Mat
3374 
3375    Input Parameters:
3376 +  mat - the matrix
3377 .  col - column permutation
3378 -  info - options for factorization, includes
3379 $          fill - expected fill as ratio of original fill.
3380 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3381 $                   Run with the option -info to determine an optimal value to use
3382 
3383    Notes:
3384    Most users should employ the simplified KSP interface for linear solvers
3385    instead of working directly with matrix algebra routines such as this.
3386    See, e.g., KSPCreate().
3387 
3388    This changes the state of the matrix to a factored matrix; it cannot be used
3389    for example with MatSetValues() unless one first calls MatSetUnfactored().
3390 
3391    Level: developer
3392 
3393 .seealso: `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3394           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3395 
3396     Developer Note: fortran interface is not autogenerated as the f90
3397     interface definition cannot be generated correctly [due to MatFactorInfo]
3398 
3399 @*/
3400 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3401 {
3402   PetscFunctionBegin;
3403   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3404   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,2);
3405   if (info) PetscValidPointer(info,3);
3406   PetscValidType(mat,1);
3407   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3408   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3409   MatCheckPreallocated(mat,1);
3410   PetscCall(PetscLogEventBegin(MAT_QRFactor,mat,col,0,0));
3411   PetscUseMethod(mat,"MatQRFactor_C", (Mat,IS,const MatFactorInfo*), (mat, col, info));
3412   PetscCall(PetscLogEventEnd(MAT_QRFactor,mat,col,0,0));
3413   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3414   PetscFunctionReturn(0);
3415 }
3416 
3417 /*@
3418    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3419    Call this routine before calling MatQRFactorNumeric().
3420 
3421    Collective on Mat
3422 
3423    Input Parameters:
3424 +  fact - the factor matrix obtained with MatGetFactor()
3425 .  mat - the matrix
3426 .  col - column permutation
3427 -  info - options for factorization, includes
3428 $          fill - expected fill as ratio of original fill.
3429 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3430 $                   Run with the option -info to determine an optimal value to use
3431 
3432    Most users should employ the simplified KSP interface for linear solvers
3433    instead of working directly with matrix algebra routines such as this.
3434    See, e.g., KSPCreate().
3435 
3436    Level: developer
3437 
3438 .seealso: `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3439 
3440     Developer Note: fortran interface is not autogenerated as the f90
3441     interface definition cannot be generated correctly [due to MatFactorInfo]
3442 
3443 @*/
3444 PetscErrorCode MatQRFactorSymbolic(Mat fact,Mat mat,IS col,const MatFactorInfo *info)
3445 {
3446   MatFactorInfo  tinfo;
3447 
3448   PetscFunctionBegin;
3449   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3450   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3451   if (info) PetscValidPointer(info,4);
3452   PetscValidType(mat,2);
3453   PetscValidPointer(fact,1);
3454   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3455   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3456   MatCheckPreallocated(mat,2);
3457   if (!info) {
3458     PetscCall(MatFactorInfoInitialize(&tinfo));
3459     info = &tinfo;
3460   }
3461 
3462   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic,fact,mat,col,0));
3463   PetscUseMethod(fact,"MatQRFactorSymbolic_C", (Mat,Mat,IS,const MatFactorInfo*), (fact, mat, col, info));
3464   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic,fact,mat,col,0));
3465   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3466   PetscFunctionReturn(0);
3467 }
3468 
3469 /*@
3470    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3471    Call this routine after first calling MatQRFactorSymbolic().
3472 
3473    Collective on Mat
3474 
3475    Input Parameters:
3476 +  fact - the factor matrix obtained with MatGetFactor()
3477 .  mat - the matrix
3478 -  info - options for factorization
3479 
3480    Notes:
3481    See MatQRFactor() for in-place factorization.
3482 
3483    Most users should employ the simplified KSP interface for linear solvers
3484    instead of working directly with matrix algebra routines such as this.
3485    See, e.g., KSPCreate().
3486 
3487    Level: developer
3488 
3489 .seealso: `MatQRFactorSymbolic()`, `MatLUFactor()`
3490 
3491     Developer Note: fortran interface is not autogenerated as the f90
3492     interface definition cannot be generated correctly [due to MatFactorInfo]
3493 
3494 @*/
3495 PetscErrorCode MatQRFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3496 {
3497   MatFactorInfo  tinfo;
3498 
3499   PetscFunctionBegin;
3500   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3501   PetscValidType(mat,2);
3502   PetscValidPointer(fact,1);
3503   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3504   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3505   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);
3506 
3507   MatCheckPreallocated(mat,2);
3508   if (!info) {
3509     PetscCall(MatFactorInfoInitialize(&tinfo));
3510     info = &tinfo;
3511   }
3512 
3513   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric,mat,fact,0,0));
3514   else  PetscCall(PetscLogEventBegin(MAT_QRFactor,mat,fact,0,0));
3515   PetscUseMethod(fact,"MatQRFactorNumeric_C", (Mat,Mat,const MatFactorInfo*), (fact, mat, info));
3516   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric,mat,fact,0,0));
3517   else PetscCall(PetscLogEventEnd(MAT_QRFactor,mat,fact,0,0));
3518   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3519   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3520   PetscFunctionReturn(0);
3521 }
3522 
3523 /* ----------------------------------------------------------------*/
3524 /*@
3525    MatSolve - Solves A x = b, given a factored matrix.
3526 
3527    Neighbor-wise Collective on Mat
3528 
3529    Input Parameters:
3530 +  mat - the factored matrix
3531 -  b - the right-hand-side vector
3532 
3533    Output Parameter:
3534 .  x - the result vector
3535 
3536    Notes:
3537    The vectors b and x cannot be the same.  I.e., one cannot
3538    call MatSolve(A,x,x).
3539 
3540    Notes:
3541    Most users should employ the simplified KSP interface for linear solvers
3542    instead of working directly with matrix algebra routines such as this.
3543    See, e.g., KSPCreate().
3544 
3545    Level: developer
3546 
3547 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3548 @*/
3549 PetscErrorCode MatSolve(Mat mat,Vec b,Vec x)
3550 {
3551   PetscFunctionBegin;
3552   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3553   PetscValidType(mat,1);
3554   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3555   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3556   PetscCheckSameComm(mat,1,b,2);
3557   PetscCheckSameComm(mat,1,x,3);
3558   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3559   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);
3560   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);
3561   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);
3562   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3563   MatCheckPreallocated(mat,1);
3564 
3565   PetscCall(PetscLogEventBegin(MAT_Solve,mat,b,x,0));
3566   if (mat->factorerrortype) {
3567     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
3568     PetscCall(VecSetInf(x));
3569   } else {
3570     PetscCheck(mat->ops->solve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3571     PetscCall((*mat->ops->solve)(mat,b,x));
3572   }
3573   PetscCall(PetscLogEventEnd(MAT_Solve,mat,b,x,0));
3574   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3575   PetscFunctionReturn(0);
3576 }
3577 
3578 static PetscErrorCode MatMatSolve_Basic(Mat A,Mat B,Mat X,PetscBool trans)
3579 {
3580   Vec            b,x;
3581   PetscInt       N,i;
3582   PetscErrorCode (*f)(Mat,Vec,Vec);
3583   PetscBool      Abound,Bneedconv = PETSC_FALSE,Xneedconv = PETSC_FALSE;
3584 
3585   PetscFunctionBegin;
3586   if (A->factorerrortype) {
3587     PetscCall(PetscInfo(A,"MatFactorError %d\n",A->factorerrortype));
3588     PetscCall(MatSetInf(X));
3589     PetscFunctionReturn(0);
3590   }
3591   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3592   PetscCheck(f,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
3593   PetscCall(MatBoundToCPU(A,&Abound));
3594   if (!Abound) {
3595     PetscCall(PetscObjectTypeCompareAny((PetscObject)B,&Bneedconv,MATSEQDENSE,MATMPIDENSE,""));
3596     PetscCall(PetscObjectTypeCompareAny((PetscObject)X,&Xneedconv,MATSEQDENSE,MATMPIDENSE,""));
3597   }
3598   if (Bneedconv) {
3599     PetscCall(MatConvert(B,MATDENSECUDA,MAT_INPLACE_MATRIX,&B));
3600   }
3601   if (Xneedconv) {
3602     PetscCall(MatConvert(X,MATDENSECUDA,MAT_INPLACE_MATRIX,&X));
3603   }
3604   PetscCall(MatGetSize(B,NULL,&N));
3605   for (i=0; i<N; i++) {
3606     PetscCall(MatDenseGetColumnVecRead(B,i,&b));
3607     PetscCall(MatDenseGetColumnVecWrite(X,i,&x));
3608     PetscCall((*f)(A,b,x));
3609     PetscCall(MatDenseRestoreColumnVecWrite(X,i,&x));
3610     PetscCall(MatDenseRestoreColumnVecRead(B,i,&b));
3611   }
3612   if (Bneedconv) {
3613     PetscCall(MatConvert(B,MATDENSE,MAT_INPLACE_MATRIX,&B));
3614   }
3615   if (Xneedconv) {
3616     PetscCall(MatConvert(X,MATDENSE,MAT_INPLACE_MATRIX,&X));
3617   }
3618   PetscFunctionReturn(0);
3619 }
3620 
3621 /*@
3622    MatMatSolve - Solves A X = B, given a factored matrix.
3623 
3624    Neighbor-wise Collective on Mat
3625 
3626    Input Parameters:
3627 +  A - the factored matrix
3628 -  B - the right-hand-side matrix MATDENSE (or sparse -- when using MUMPS)
3629 
3630    Output Parameter:
3631 .  X - the result matrix (dense matrix)
3632 
3633    Notes:
3634    If B is a MATDENSE matrix then one can call MatMatSolve(A,B,B) except with MKL_CPARDISO;
3635    otherwise, B and X cannot be the same.
3636 
3637    Notes:
3638    Most users should usually employ the simplified KSP interface for linear solvers
3639    instead of working directly with matrix algebra routines such as this.
3640    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3641    at a time.
3642 
3643    Level: developer
3644 
3645 .seealso: `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3646 @*/
3647 PetscErrorCode MatMatSolve(Mat A,Mat B,Mat X)
3648 {
3649   PetscFunctionBegin;
3650   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3651   PetscValidType(A,1);
3652   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3653   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3654   PetscCheckSameComm(A,1,B,2);
3655   PetscCheckSameComm(A,1,X,3);
3656   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);
3657   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);
3658   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");
3659   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3660   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3661   MatCheckPreallocated(A,1);
3662 
3663   PetscCall(PetscLogEventBegin(MAT_MatSolve,A,B,X,0));
3664   if (!A->ops->matsolve) {
3665     PetscCall(PetscInfo(A,"Mat type %s using basic MatMatSolve\n",((PetscObject)A)->type_name));
3666     PetscCall(MatMatSolve_Basic(A,B,X,PETSC_FALSE));
3667   } else {
3668     PetscCall((*A->ops->matsolve)(A,B,X));
3669   }
3670   PetscCall(PetscLogEventEnd(MAT_MatSolve,A,B,X,0));
3671   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3672   PetscFunctionReturn(0);
3673 }
3674 
3675 /*@
3676    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3677 
3678    Neighbor-wise Collective on Mat
3679 
3680    Input Parameters:
3681 +  A - the factored matrix
3682 -  B - the right-hand-side matrix  (dense matrix)
3683 
3684    Output Parameter:
3685 .  X - the result matrix (dense matrix)
3686 
3687    Notes:
3688    The matrices B and X cannot be the same.  I.e., one cannot
3689    call MatMatSolveTranspose(A,X,X).
3690 
3691    Notes:
3692    Most users should usually employ the simplified KSP interface for linear solvers
3693    instead of working directly with matrix algebra routines such as this.
3694    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3695    at a time.
3696 
3697    When using SuperLU_Dist or MUMPS as a parallel solver, PETSc will use their functionality to solve multiple right hand sides simultaneously.
3698 
3699    Level: developer
3700 
3701 .seealso: `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3702 @*/
3703 PetscErrorCode MatMatSolveTranspose(Mat A,Mat B,Mat X)
3704 {
3705   PetscFunctionBegin;
3706   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3707   PetscValidType(A,1);
3708   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3709   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3710   PetscCheckSameComm(A,1,B,2);
3711   PetscCheckSameComm(A,1,X,3);
3712   PetscCheck(X != B,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3713   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);
3714   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);
3715   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);
3716   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");
3717   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3718   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3719   MatCheckPreallocated(A,1);
3720 
3721   PetscCall(PetscLogEventBegin(MAT_MatSolve,A,B,X,0));
3722   if (!A->ops->matsolvetranspose) {
3723     PetscCall(PetscInfo(A,"Mat type %s using basic MatMatSolveTranspose\n",((PetscObject)A)->type_name));
3724     PetscCall(MatMatSolve_Basic(A,B,X,PETSC_TRUE));
3725   } else {
3726     PetscCall((*A->ops->matsolvetranspose)(A,B,X));
3727   }
3728   PetscCall(PetscLogEventEnd(MAT_MatSolve,A,B,X,0));
3729   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3730   PetscFunctionReturn(0);
3731 }
3732 
3733 /*@
3734    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3735 
3736    Neighbor-wise Collective on Mat
3737 
3738    Input Parameters:
3739 +  A - the factored matrix
3740 -  Bt - the transpose of right-hand-side matrix
3741 
3742    Output Parameter:
3743 .  X - the result matrix (dense matrix)
3744 
3745    Notes:
3746    Most users should usually employ the simplified KSP interface for linear solvers
3747    instead of working directly with matrix algebra routines such as this.
3748    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3749    at a time.
3750 
3751    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().
3752 
3753    Level: developer
3754 
3755 .seealso: `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3756 @*/
3757 PetscErrorCode MatMatTransposeSolve(Mat A,Mat Bt,Mat X)
3758 {
3759   PetscFunctionBegin;
3760   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3761   PetscValidType(A,1);
3762   PetscValidHeaderSpecific(Bt,MAT_CLASSID,2);
3763   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3764   PetscCheckSameComm(A,1,Bt,2);
3765   PetscCheckSameComm(A,1,X,3);
3766 
3767   PetscCheck(X != Bt,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3768   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);
3769   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);
3770   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");
3771   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3772   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3773   MatCheckPreallocated(A,1);
3774 
3775   PetscCheck(A->ops->mattransposesolve,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
3776   PetscCall(PetscLogEventBegin(MAT_MatTrSolve,A,Bt,X,0));
3777   PetscCall((*A->ops->mattransposesolve)(A,Bt,X));
3778   PetscCall(PetscLogEventEnd(MAT_MatTrSolve,A,Bt,X,0));
3779   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3780   PetscFunctionReturn(0);
3781 }
3782 
3783 /*@
3784    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3785                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3786 
3787    Neighbor-wise Collective on Mat
3788 
3789    Input Parameters:
3790 +  mat - the factored matrix
3791 -  b - the right-hand-side vector
3792 
3793    Output Parameter:
3794 .  x - the result vector
3795 
3796    Notes:
3797    MatSolve() should be used for most applications, as it performs
3798    a forward solve followed by a backward solve.
3799 
3800    The vectors b and x cannot be the same,  i.e., one cannot
3801    call MatForwardSolve(A,x,x).
3802 
3803    For matrix in seqsbaij format with block size larger than 1,
3804    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3805    MatForwardSolve() solves U^T*D y = b, and
3806    MatBackwardSolve() solves U x = y.
3807    Thus they do not provide a symmetric preconditioner.
3808 
3809    Most users should employ the simplified KSP interface for linear solvers
3810    instead of working directly with matrix algebra routines such as this.
3811    See, e.g., KSPCreate().
3812 
3813    Level: developer
3814 
3815 .seealso: `MatSolve()`, `MatBackwardSolve()`
3816 @*/
3817 PetscErrorCode MatForwardSolve(Mat mat,Vec b,Vec x)
3818 {
3819   PetscFunctionBegin;
3820   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3821   PetscValidType(mat,1);
3822   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3823   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3824   PetscCheckSameComm(mat,1,b,2);
3825   PetscCheckSameComm(mat,1,x,3);
3826   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3827   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);
3828   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);
3829   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);
3830   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3831   MatCheckPreallocated(mat,1);
3832 
3833   PetscCheck(mat->ops->forwardsolve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3834   PetscCall(PetscLogEventBegin(MAT_ForwardSolve,mat,b,x,0));
3835   PetscCall((*mat->ops->forwardsolve)(mat,b,x));
3836   PetscCall(PetscLogEventEnd(MAT_ForwardSolve,mat,b,x,0));
3837   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3838   PetscFunctionReturn(0);
3839 }
3840 
3841 /*@
3842    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3843                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3844 
3845    Neighbor-wise Collective on Mat
3846 
3847    Input Parameters:
3848 +  mat - the factored matrix
3849 -  b - the right-hand-side vector
3850 
3851    Output Parameter:
3852 .  x - the result vector
3853 
3854    Notes:
3855    MatSolve() should be used for most applications, as it performs
3856    a forward solve followed by a backward solve.
3857 
3858    The vectors b and x cannot be the same.  I.e., one cannot
3859    call MatBackwardSolve(A,x,x).
3860 
3861    For matrix in seqsbaij format with block size larger than 1,
3862    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3863    MatForwardSolve() solves U^T*D y = b, and
3864    MatBackwardSolve() solves U x = y.
3865    Thus they do not provide a symmetric preconditioner.
3866 
3867    Most users should employ the simplified KSP interface for linear solvers
3868    instead of working directly with matrix algebra routines such as this.
3869    See, e.g., KSPCreate().
3870 
3871    Level: developer
3872 
3873 .seealso: `MatSolve()`, `MatForwardSolve()`
3874 @*/
3875 PetscErrorCode MatBackwardSolve(Mat mat,Vec b,Vec x)
3876 {
3877   PetscFunctionBegin;
3878   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3879   PetscValidType(mat,1);
3880   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3881   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3882   PetscCheckSameComm(mat,1,b,2);
3883   PetscCheckSameComm(mat,1,x,3);
3884   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3885   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);
3886   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);
3887   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);
3888   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3889   MatCheckPreallocated(mat,1);
3890 
3891   PetscCheck(mat->ops->backwardsolve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3892   PetscCall(PetscLogEventBegin(MAT_BackwardSolve,mat,b,x,0));
3893   PetscCall((*mat->ops->backwardsolve)(mat,b,x));
3894   PetscCall(PetscLogEventEnd(MAT_BackwardSolve,mat,b,x,0));
3895   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3896   PetscFunctionReturn(0);
3897 }
3898 
3899 /*@
3900    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3901 
3902    Neighbor-wise Collective on Mat
3903 
3904    Input Parameters:
3905 +  mat - the factored matrix
3906 .  b - the right-hand-side vector
3907 -  y - the vector to be added to
3908 
3909    Output Parameter:
3910 .  x - the result vector
3911 
3912    Notes:
3913    The vectors b and x cannot be the same.  I.e., one cannot
3914    call MatSolveAdd(A,x,y,x).
3915 
3916    Most users should employ the simplified KSP interface for linear solvers
3917    instead of working directly with matrix algebra routines such as this.
3918    See, e.g., KSPCreate().
3919 
3920    Level: developer
3921 
3922 .seealso: `MatSolve()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3923 @*/
3924 PetscErrorCode MatSolveAdd(Mat mat,Vec b,Vec y,Vec x)
3925 {
3926   PetscScalar    one = 1.0;
3927   Vec            tmp;
3928 
3929   PetscFunctionBegin;
3930   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3931   PetscValidType(mat,1);
3932   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3933   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3934   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
3935   PetscCheckSameComm(mat,1,b,2);
3936   PetscCheckSameComm(mat,1,y,3);
3937   PetscCheckSameComm(mat,1,x,4);
3938   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3939   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);
3940   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);
3941   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);
3942   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);
3943   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);
3944   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3945    MatCheckPreallocated(mat,1);
3946 
3947   PetscCall(PetscLogEventBegin(MAT_SolveAdd,mat,b,x,y));
3948   if (mat->factorerrortype) {
3949 
3950     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
3951     PetscCall(VecSetInf(x));
3952   } else if (mat->ops->solveadd) {
3953     PetscCall((*mat->ops->solveadd)(mat,b,y,x));
3954   } else {
3955     /* do the solve then the add manually */
3956     if (x != y) {
3957       PetscCall(MatSolve(mat,b,x));
3958       PetscCall(VecAXPY(x,one,y));
3959     } else {
3960       PetscCall(VecDuplicate(x,&tmp));
3961       PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp));
3962       PetscCall(VecCopy(x,tmp));
3963       PetscCall(MatSolve(mat,b,x));
3964       PetscCall(VecAXPY(x,one,tmp));
3965       PetscCall(VecDestroy(&tmp));
3966     }
3967   }
3968   PetscCall(PetscLogEventEnd(MAT_SolveAdd,mat,b,x,y));
3969   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3970   PetscFunctionReturn(0);
3971 }
3972 
3973 /*@
3974    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3975 
3976    Neighbor-wise Collective on Mat
3977 
3978    Input Parameters:
3979 +  mat - the factored matrix
3980 -  b - the right-hand-side vector
3981 
3982    Output Parameter:
3983 .  x - the result vector
3984 
3985    Notes:
3986    The vectors b and x cannot be the same.  I.e., one cannot
3987    call MatSolveTranspose(A,x,x).
3988 
3989    Most users should employ the simplified KSP interface for linear solvers
3990    instead of working directly with matrix algebra routines such as this.
3991    See, e.g., KSPCreate().
3992 
3993    Level: developer
3994 
3995 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3996 @*/
3997 PetscErrorCode MatSolveTranspose(Mat mat,Vec b,Vec x)
3998 {
3999   PetscErrorCode (*f)(Mat,Vec,Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4000 
4001   PetscFunctionBegin;
4002   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4003   PetscValidType(mat,1);
4004   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4005   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
4006   PetscCheckSameComm(mat,1,b,2);
4007   PetscCheckSameComm(mat,1,x,3);
4008   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
4009   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);
4010   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);
4011   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4012   MatCheckPreallocated(mat,1);
4013   PetscCall(PetscLogEventBegin(MAT_SolveTranspose,mat,b,x,0));
4014   if (mat->factorerrortype) {
4015     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
4016     PetscCall(VecSetInf(x));
4017   } else {
4018     PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s",((PetscObject)mat)->type_name);
4019     PetscCall((*f)(mat,b,x));
4020   }
4021   PetscCall(PetscLogEventEnd(MAT_SolveTranspose,mat,b,x,0));
4022   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4023   PetscFunctionReturn(0);
4024 }
4025 
4026 /*@
4027    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4028                       factored matrix.
4029 
4030    Neighbor-wise Collective on Mat
4031 
4032    Input Parameters:
4033 +  mat - the factored matrix
4034 .  b - the right-hand-side vector
4035 -  y - the vector to be added to
4036 
4037    Output Parameter:
4038 .  x - the result vector
4039 
4040    Notes:
4041    The vectors b and x cannot be the same.  I.e., one cannot
4042    call MatSolveTransposeAdd(A,x,y,x).
4043 
4044    Most users should employ the simplified KSP interface for linear solvers
4045    instead of working directly with matrix algebra routines such as this.
4046    See, e.g., KSPCreate().
4047 
4048    Level: developer
4049 
4050 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4051 @*/
4052 PetscErrorCode MatSolveTransposeAdd(Mat mat,Vec b,Vec y,Vec x)
4053 {
4054   PetscScalar    one = 1.0;
4055   Vec            tmp;
4056   PetscErrorCode (*f)(Mat,Vec,Vec,Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4057 
4058   PetscFunctionBegin;
4059   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4060   PetscValidType(mat,1);
4061   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
4062   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4063   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
4064   PetscCheckSameComm(mat,1,b,2);
4065   PetscCheckSameComm(mat,1,y,3);
4066   PetscCheckSameComm(mat,1,x,4);
4067   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
4068   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);
4069   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);
4070   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);
4071   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);
4072   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4073   MatCheckPreallocated(mat,1);
4074 
4075   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd,mat,b,x,y));
4076   if (mat->factorerrortype) {
4077     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
4078     PetscCall(VecSetInf(x));
4079   } else if (f) {
4080     PetscCall((*f)(mat,b,y,x));
4081   } else {
4082     /* do the solve then the add manually */
4083     if (x != y) {
4084       PetscCall(MatSolveTranspose(mat,b,x));
4085       PetscCall(VecAXPY(x,one,y));
4086     } else {
4087       PetscCall(VecDuplicate(x,&tmp));
4088       PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp));
4089       PetscCall(VecCopy(x,tmp));
4090       PetscCall(MatSolveTranspose(mat,b,x));
4091       PetscCall(VecAXPY(x,one,tmp));
4092       PetscCall(VecDestroy(&tmp));
4093     }
4094   }
4095   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd,mat,b,x,y));
4096   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4097   PetscFunctionReturn(0);
4098 }
4099 /* ----------------------------------------------------------------*/
4100 
4101 /*@
4102    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4103 
4104    Neighbor-wise Collective on Mat
4105 
4106    Input Parameters:
4107 +  mat - the matrix
4108 .  b - the right hand side
4109 .  omega - the relaxation factor
4110 .  flag - flag indicating the type of SOR (see below)
4111 .  shift -  diagonal shift
4112 .  its - the number of iterations
4113 -  lits - the number of local iterations
4114 
4115    Output Parameter:
4116 .  x - the solution (can contain an initial guess, use option SOR_ZERO_INITIAL_GUESS to indicate no guess)
4117 
4118    SOR Flags:
4119 +     SOR_FORWARD_SWEEP - forward SOR
4120 .     SOR_BACKWARD_SWEEP - backward SOR
4121 .     SOR_SYMMETRIC_SWEEP - SSOR (symmetric SOR)
4122 .     SOR_LOCAL_FORWARD_SWEEP - local forward SOR
4123 .     SOR_LOCAL_BACKWARD_SWEEP - local forward SOR
4124 .     SOR_LOCAL_SYMMETRIC_SWEEP - local SSOR
4125 .     SOR_APPLY_UPPER, SOR_APPLY_LOWER - applies
4126          upper/lower triangular part of matrix to
4127          vector (with omega)
4128 -     SOR_ZERO_INITIAL_GUESS - zero initial guess
4129 
4130    Notes:
4131    SOR_LOCAL_FORWARD_SWEEP, SOR_LOCAL_BACKWARD_SWEEP, and
4132    SOR_LOCAL_SYMMETRIC_SWEEP perform separate independent smoothings
4133    on each processor.
4134 
4135    Application programmers will not generally use MatSOR() directly,
4136    but instead will employ the KSP/PC interface.
4137 
4138    Notes:
4139     for BAIJ, SBAIJ, and AIJ matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4140 
4141    Notes for Advanced Users:
4142    The flags are implemented as bitwise inclusive or operations.
4143    For example, use (SOR_ZERO_INITIAL_GUESS | SOR_SYMMETRIC_SWEEP)
4144    to specify a zero initial guess for SSOR.
4145 
4146    Most users should employ the simplified KSP interface for linear solvers
4147    instead of working directly with matrix algebra routines such as this.
4148    See, e.g., KSPCreate().
4149 
4150    Vectors x and b CANNOT be the same
4151 
4152    Developer Note: We should add block SOR support for AIJ matrices with block size set to great than one and no inodes
4153 
4154    Level: developer
4155 
4156 @*/
4157 PetscErrorCode MatSOR(Mat mat,Vec b,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec x)
4158 {
4159   PetscFunctionBegin;
4160   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4161   PetscValidType(mat,1);
4162   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4163   PetscValidHeaderSpecific(x,VEC_CLASSID,8);
4164   PetscCheckSameComm(mat,1,b,2);
4165   PetscCheckSameComm(mat,1,x,8);
4166   PetscCheck(mat->ops->sor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4167   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4168   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4169   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);
4170   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);
4171   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);
4172   PetscCheck(its > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %" PetscInt_FMT " positive",its);
4173   PetscCheck(lits > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires local its %" PetscInt_FMT " positive",lits);
4174   PetscCheck(b != x,PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"b and x vector cannot be the same");
4175 
4176   MatCheckPreallocated(mat,1);
4177   PetscCall(PetscLogEventBegin(MAT_SOR,mat,b,x,0));
4178   PetscCall((*mat->ops->sor)(mat,b,omega,flag,shift,its,lits,x));
4179   PetscCall(PetscLogEventEnd(MAT_SOR,mat,b,x,0));
4180   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4181   PetscFunctionReturn(0);
4182 }
4183 
4184 /*
4185       Default matrix copy routine.
4186 */
4187 PetscErrorCode MatCopy_Basic(Mat A,Mat B,MatStructure str)
4188 {
4189   PetscInt          i,rstart = 0,rend = 0,nz;
4190   const PetscInt    *cwork;
4191   const PetscScalar *vwork;
4192 
4193   PetscFunctionBegin;
4194   if (B->assembled) PetscCall(MatZeroEntries(B));
4195   if (str == SAME_NONZERO_PATTERN) {
4196     PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
4197     for (i=rstart; i<rend; i++) {
4198       PetscCall(MatGetRow(A,i,&nz,&cwork,&vwork));
4199       PetscCall(MatSetValues(B,1,&i,nz,cwork,vwork,INSERT_VALUES));
4200       PetscCall(MatRestoreRow(A,i,&nz,&cwork,&vwork));
4201     }
4202   } else {
4203     PetscCall(MatAYPX(B,0.0,A,str));
4204   }
4205   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
4206   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
4207   PetscFunctionReturn(0);
4208 }
4209 
4210 /*@
4211    MatCopy - Copies a matrix to another matrix.
4212 
4213    Collective on Mat
4214 
4215    Input Parameters:
4216 +  A - the matrix
4217 -  str - SAME_NONZERO_PATTERN or DIFFERENT_NONZERO_PATTERN
4218 
4219    Output Parameter:
4220 .  B - where the copy is put
4221 
4222    Notes:
4223    If you use SAME_NONZERO_PATTERN then the two matrices must have the same nonzero pattern or the routine will crash.
4224 
4225    MatCopy() copies the matrix entries of a matrix to another existing
4226    matrix (after first zeroing the second matrix).  A related routine is
4227    MatConvert(), which first creates a new matrix and then copies the data.
4228 
4229    Level: intermediate
4230 
4231 .seealso: `MatConvert()`, `MatDuplicate()`
4232 @*/
4233 PetscErrorCode MatCopy(Mat A,Mat B,MatStructure str)
4234 {
4235   PetscInt       i;
4236 
4237   PetscFunctionBegin;
4238   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4239   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4240   PetscValidType(A,1);
4241   PetscValidType(B,2);
4242   PetscCheckSameComm(A,1,B,2);
4243   MatCheckPreallocated(B,2);
4244   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4245   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4246   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);
4247   MatCheckPreallocated(A,1);
4248   if (A == B) PetscFunctionReturn(0);
4249 
4250   PetscCall(PetscLogEventBegin(MAT_Copy,A,B,0,0));
4251   if (A->ops->copy) {
4252     PetscCall((*A->ops->copy)(A,B,str));
4253   } else { /* generic conversion */
4254     PetscCall(MatCopy_Basic(A,B,str));
4255   }
4256 
4257   B->stencil.dim = A->stencil.dim;
4258   B->stencil.noc = A->stencil.noc;
4259   for (i=0; i<=A->stencil.dim; i++) {
4260     B->stencil.dims[i]   = A->stencil.dims[i];
4261     B->stencil.starts[i] = A->stencil.starts[i];
4262   }
4263 
4264   PetscCall(PetscLogEventEnd(MAT_Copy,A,B,0,0));
4265   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4266   PetscFunctionReturn(0);
4267 }
4268 
4269 /*@C
4270    MatConvert - Converts a matrix to another matrix, either of the same
4271    or different type.
4272 
4273    Collective on Mat
4274 
4275    Input Parameters:
4276 +  mat - the matrix
4277 .  newtype - new matrix type.  Use MATSAME to create a new matrix of the
4278    same type as the original matrix.
4279 -  reuse - denotes if the destination matrix is to be created or reused.
4280    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
4281    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).
4282 
4283    Output Parameter:
4284 .  M - pointer to place new matrix
4285 
4286    Notes:
4287    MatConvert() first creates a new matrix and then copies the data from
4288    the first matrix.  A related routine is MatCopy(), which copies the matrix
4289    entries of one matrix to another already existing matrix context.
4290 
4291    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4292    the MPI communicator of the generated matrix is always the same as the communicator
4293    of the input matrix.
4294 
4295    Level: intermediate
4296 
4297 .seealso: `MatCopy()`, `MatDuplicate()`
4298 @*/
4299 PetscErrorCode MatConvert(Mat mat,MatType newtype,MatReuse reuse,Mat *M)
4300 {
4301   PetscBool      sametype,issame,flg;
4302   PetscBool3     issymmetric,ishermitian;
4303   char           convname[256],mtype[256];
4304   Mat            B;
4305 
4306   PetscFunctionBegin;
4307   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4308   PetscValidType(mat,1);
4309   PetscValidPointer(M,4);
4310   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4311   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4312   MatCheckPreallocated(mat,1);
4313 
4314   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matconvert_type",mtype,sizeof(mtype),&flg));
4315   if (flg) newtype = mtype;
4316 
4317   PetscCall(PetscObjectTypeCompare((PetscObject)mat,newtype,&sametype));
4318   PetscCall(PetscStrcmp(newtype,"same",&issame));
4319   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M),PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires same input and output matrix");
4320   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");
4321 
4322   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4323     PetscCall(PetscInfo(mat,"Early return for inplace %s %d %d\n",((PetscObject)mat)->type_name,sametype,issame));
4324     PetscFunctionReturn(0);
4325   }
4326 
4327   /* Cache Mat options because some converters use MatHeaderReplace  */
4328   issymmetric = mat->symmetric;
4329   ishermitian = mat->hermitian;
4330 
4331   if ((sametype || issame) && (reuse==MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4332     PetscCall(PetscInfo(mat,"Calling duplicate for initial matrix %s %d %d\n",((PetscObject)mat)->type_name,sametype,issame));
4333     PetscCall((*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M));
4334   } else {
4335     PetscErrorCode (*conv)(Mat, MatType,MatReuse,Mat*)=NULL;
4336     const char     *prefix[3] = {"seq","mpi",""};
4337     PetscInt       i;
4338     /*
4339        Order of precedence:
4340        0) See if newtype is a superclass of the current matrix.
4341        1) See if a specialized converter is known to the current matrix.
4342        2) See if a specialized converter is known to the desired matrix class.
4343        3) See if a good general converter is registered for the desired class
4344           (as of 6/27/03 only MATMPIADJ falls into this category).
4345        4) See if a good general converter is known for the current matrix.
4346        5) Use a really basic converter.
4347     */
4348 
4349     /* 0) See if newtype is a superclass of the current matrix.
4350           i.e mat is mpiaij and newtype is aij */
4351     for (i=0; i<2; i++) {
4352       PetscCall(PetscStrncpy(convname,prefix[i],sizeof(convname)));
4353       PetscCall(PetscStrlcat(convname,newtype,sizeof(convname)));
4354       PetscCall(PetscStrcmp(convname,((PetscObject)mat)->type_name,&flg));
4355       PetscCall(PetscInfo(mat,"Check superclass %s %s -> %d\n",convname,((PetscObject)mat)->type_name,flg));
4356       if (flg) {
4357         if (reuse == MAT_INPLACE_MATRIX) {
4358           PetscCall(PetscInfo(mat,"Early return\n"));
4359           PetscFunctionReturn(0);
4360         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4361           PetscCall(PetscInfo(mat,"Calling MatDuplicate\n"));
4362           PetscCall((*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M));
4363           PetscFunctionReturn(0);
4364         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4365           PetscCall(PetscInfo(mat,"Calling MatCopy\n"));
4366           PetscCall(MatCopy(mat,*M,SAME_NONZERO_PATTERN));
4367           PetscFunctionReturn(0);
4368         }
4369       }
4370     }
4371     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4372     for (i=0; i<3; i++) {
4373       PetscCall(PetscStrncpy(convname,"MatConvert_",sizeof(convname)));
4374       PetscCall(PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname,"_",sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname,prefix[i],sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname,issame ? ((PetscObject)mat)->type_name : newtype,sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname,"_C",sizeof(convname)));
4379       PetscCall(PetscObjectQueryFunction((PetscObject)mat,convname,&conv));
4380       PetscCall(PetscInfo(mat,"Check specialized (1) %s (%s) -> %d\n",convname,((PetscObject)mat)->type_name,!!conv));
4381       if (conv) goto foundconv;
4382     }
4383 
4384     /* 2)  See if a specialized converter is known to the desired matrix class. */
4385     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&B));
4386     PetscCall(MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
4387     PetscCall(MatSetType(B,newtype));
4388     for (i=0; i<3; i++) {
4389       PetscCall(PetscStrncpy(convname,"MatConvert_",sizeof(convname)));
4390       PetscCall(PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname)));
4391       PetscCall(PetscStrlcat(convname,"_",sizeof(convname)));
4392       PetscCall(PetscStrlcat(convname,prefix[i],sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname,newtype,sizeof(convname)));
4394       PetscCall(PetscStrlcat(convname,"_C",sizeof(convname)));
4395       PetscCall(PetscObjectQueryFunction((PetscObject)B,convname,&conv));
4396       PetscCall(PetscInfo(mat,"Check specialized (2) %s (%s) -> %d\n",convname,((PetscObject)B)->type_name,!!conv));
4397       if (conv) {
4398         PetscCall(MatDestroy(&B));
4399         goto foundconv;
4400       }
4401     }
4402 
4403     /* 3) See if a good general converter is registered for the desired class */
4404     conv = B->ops->convertfrom;
4405     PetscCall(PetscInfo(mat,"Check convertfrom (%s) -> %d\n",((PetscObject)B)->type_name,!!conv));
4406     PetscCall(MatDestroy(&B));
4407     if (conv) goto foundconv;
4408 
4409     /* 4) See if a good general converter is known for the current matrix */
4410     if (mat->ops->convert) conv = mat->ops->convert;
4411     PetscCall(PetscInfo(mat,"Check general convert (%s) -> %d\n",((PetscObject)mat)->type_name,!!conv));
4412     if (conv) goto foundconv;
4413 
4414     /* 5) Use a really basic converter. */
4415     PetscCall(PetscInfo(mat,"Using MatConvert_Basic\n"));
4416     conv = MatConvert_Basic;
4417 
4418 foundconv:
4419     PetscCall(PetscLogEventBegin(MAT_Convert,mat,0,0,0));
4420     PetscCall((*conv)(mat,newtype,reuse,M));
4421     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4422       /* the block sizes must be same if the mappings are copied over */
4423       (*M)->rmap->bs = mat->rmap->bs;
4424       (*M)->cmap->bs = mat->cmap->bs;
4425       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4426       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4427       (*M)->rmap->mapping = mat->rmap->mapping;
4428       (*M)->cmap->mapping = mat->cmap->mapping;
4429     }
4430     (*M)->stencil.dim = mat->stencil.dim;
4431     (*M)->stencil.noc = mat->stencil.noc;
4432     for (i=0; i<=mat->stencil.dim; i++) {
4433       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4434       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4435     }
4436     PetscCall(PetscLogEventEnd(MAT_Convert,mat,0,0,0));
4437   }
4438   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4439 
4440   /* Copy Mat options */
4441   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M,MAT_SYMMETRIC,PETSC_TRUE));
4442   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M,MAT_SYMMETRIC,PETSC_FALSE));
4443   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M,MAT_HERMITIAN,PETSC_TRUE));
4444   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M,MAT_HERMITIAN,PETSC_FALSE));
4445   PetscFunctionReturn(0);
4446 }
4447 
4448 /*@C
4449    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4450 
4451    Not Collective
4452 
4453    Input Parameter:
4454 .  mat - the matrix, must be a factored matrix
4455 
4456    Output Parameter:
4457 .   type - the string name of the package (do not free this string)
4458 
4459    Notes:
4460       In Fortran you pass in a empty string and the package name will be copied into it.
4461     (Make sure the string is long enough)
4462 
4463    Level: intermediate
4464 
4465 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4466 @*/
4467 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4468 {
4469   PetscErrorCode (*conv)(Mat,MatSolverType*);
4470 
4471   PetscFunctionBegin;
4472   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4473   PetscValidType(mat,1);
4474   PetscValidPointer(type,2);
4475   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
4476   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorGetSolverType_C",&conv));
4477   if (conv) PetscCall((*conv)(mat,type));
4478   else *type = MATSOLVERPETSC;
4479   PetscFunctionReturn(0);
4480 }
4481 
4482 typedef struct _MatSolverTypeForSpecifcType* MatSolverTypeForSpecifcType;
4483 struct _MatSolverTypeForSpecifcType {
4484   MatType                        mtype;
4485   /* no entry for MAT_FACTOR_NONE */
4486   PetscErrorCode                 (*createfactor[MAT_FACTOR_NUM_TYPES-1])(Mat,MatFactorType,Mat*);
4487   MatSolverTypeForSpecifcType next;
4488 };
4489 
4490 typedef struct _MatSolverTypeHolder* MatSolverTypeHolder;
4491 struct _MatSolverTypeHolder {
4492   char                        *name;
4493   MatSolverTypeForSpecifcType handlers;
4494   MatSolverTypeHolder         next;
4495 };
4496 
4497 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4498 
4499 /*@C
4500    MatSolverTypeRegister - Registers a MatSolverType that works for a particular matrix type
4501 
4502    Input Parameters:
4503 +    package - name of the package, for example petsc or superlu
4504 .    mtype - the matrix type that works with this package
4505 .    ftype - the type of factorization supported by the package
4506 -    createfactor - routine that will create the factored matrix ready to be used
4507 
4508     Level: intermediate
4509 
4510 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4511 @*/
4512 PetscErrorCode MatSolverTypeRegister(MatSolverType package,MatType mtype,MatFactorType ftype,PetscErrorCode (*createfactor)(Mat,MatFactorType,Mat*))
4513 {
4514   MatSolverTypeHolder         next = MatSolverTypeHolders,prev = NULL;
4515   PetscBool                   flg;
4516   MatSolverTypeForSpecifcType inext,iprev = NULL;
4517 
4518   PetscFunctionBegin;
4519   PetscCall(MatInitializePackage());
4520   if (!next) {
4521     PetscCall(PetscNew(&MatSolverTypeHolders));
4522     PetscCall(PetscStrallocpy(package,&MatSolverTypeHolders->name));
4523     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4524     PetscCall(PetscStrallocpy(mtype,(char **)&MatSolverTypeHolders->handlers->mtype));
4525     MatSolverTypeHolders->handlers->createfactor[(int)ftype-1] = createfactor;
4526     PetscFunctionReturn(0);
4527   }
4528   while (next) {
4529     PetscCall(PetscStrcasecmp(package,next->name,&flg));
4530     if (flg) {
4531       PetscCheck(next->handlers,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatSolverTypeHolder is missing handlers");
4532       inext = next->handlers;
4533       while (inext) {
4534         PetscCall(PetscStrcasecmp(mtype,inext->mtype,&flg));
4535         if (flg) {
4536           inext->createfactor[(int)ftype-1] = createfactor;
4537           PetscFunctionReturn(0);
4538         }
4539         iprev = inext;
4540         inext = inext->next;
4541       }
4542       PetscCall(PetscNew(&iprev->next));
4543       PetscCall(PetscStrallocpy(mtype,(char **)&iprev->next->mtype));
4544       iprev->next->createfactor[(int)ftype-1] = createfactor;
4545       PetscFunctionReturn(0);
4546     }
4547     prev = next;
4548     next = next->next;
4549   }
4550   PetscCall(PetscNew(&prev->next));
4551   PetscCall(PetscStrallocpy(package,&prev->next->name));
4552   PetscCall(PetscNew(&prev->next->handlers));
4553   PetscCall(PetscStrallocpy(mtype,(char **)&prev->next->handlers->mtype));
4554   prev->next->handlers->createfactor[(int)ftype-1] = createfactor;
4555   PetscFunctionReturn(0);
4556 }
4557 
4558 /*@C
4559    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4560 
4561    Input Parameters:
4562 +    type - name of the package, for example petsc or superlu
4563 .    ftype - the type of factorization supported by the type
4564 -    mtype - the matrix type that works with this type
4565 
4566    Output Parameters:
4567 +   foundtype - PETSC_TRUE if the type was registered
4568 .   foundmtype - PETSC_TRUE if the type supports the requested mtype
4569 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4570 
4571     Level: intermediate
4572 
4573 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4574 @*/
4575 PetscErrorCode MatSolverTypeGet(MatSolverType type,MatType mtype,MatFactorType ftype,PetscBool *foundtype,PetscBool *foundmtype,PetscErrorCode (**createfactor)(Mat,MatFactorType,Mat*))
4576 {
4577   MatSolverTypeHolder         next = MatSolverTypeHolders;
4578   PetscBool                   flg;
4579   MatSolverTypeForSpecifcType inext;
4580 
4581   PetscFunctionBegin;
4582   if (foundtype) *foundtype = PETSC_FALSE;
4583   if (foundmtype) *foundmtype = PETSC_FALSE;
4584   if (createfactor) *createfactor = NULL;
4585 
4586   if (type) {
4587     while (next) {
4588       PetscCall(PetscStrcasecmp(type,next->name,&flg));
4589       if (flg) {
4590         if (foundtype) *foundtype = PETSC_TRUE;
4591         inext = next->handlers;
4592         while (inext) {
4593           PetscCall(PetscStrbeginswith(mtype,inext->mtype,&flg));
4594           if (flg) {
4595             if (foundmtype) *foundmtype = PETSC_TRUE;
4596             if (createfactor)  *createfactor  = inext->createfactor[(int)ftype-1];
4597             PetscFunctionReturn(0);
4598           }
4599           inext = inext->next;
4600         }
4601       }
4602       next = next->next;
4603     }
4604   } else {
4605     while (next) {
4606       inext = next->handlers;
4607       while (inext) {
4608         PetscCall(PetscStrcmp(mtype,inext->mtype,&flg));
4609         if (flg && inext->createfactor[(int)ftype-1]) {
4610           if (foundtype) *foundtype = PETSC_TRUE;
4611           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4612           if (createfactor) *createfactor = inext->createfactor[(int)ftype-1];
4613           PetscFunctionReturn(0);
4614         }
4615         inext = inext->next;
4616       }
4617       next = next->next;
4618     }
4619     /* try with base classes inext->mtype */
4620     next = MatSolverTypeHolders;
4621     while (next) {
4622       inext = next->handlers;
4623       while (inext) {
4624         PetscCall(PetscStrbeginswith(mtype,inext->mtype,&flg));
4625         if (flg && inext->createfactor[(int)ftype-1]) {
4626           if (foundtype) *foundtype = PETSC_TRUE;
4627           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4628           if (createfactor) *createfactor = inext->createfactor[(int)ftype-1];
4629           PetscFunctionReturn(0);
4630         }
4631         inext = inext->next;
4632       }
4633       next = next->next;
4634     }
4635   }
4636   PetscFunctionReturn(0);
4637 }
4638 
4639 PetscErrorCode MatSolverTypeDestroy(void)
4640 {
4641   MatSolverTypeHolder         next = MatSolverTypeHolders,prev;
4642   MatSolverTypeForSpecifcType inext,iprev;
4643 
4644   PetscFunctionBegin;
4645   while (next) {
4646     PetscCall(PetscFree(next->name));
4647     inext = next->handlers;
4648     while (inext) {
4649       PetscCall(PetscFree(inext->mtype));
4650       iprev = inext;
4651       inext = inext->next;
4652       PetscCall(PetscFree(iprev));
4653     }
4654     prev = next;
4655     next = next->next;
4656     PetscCall(PetscFree(prev));
4657   }
4658   MatSolverTypeHolders = NULL;
4659   PetscFunctionReturn(0);
4660 }
4661 
4662 /*@C
4663    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in MatLUFactorSymbolic(), MatCholeskyFactorSymbolic()
4664 
4665    Logically Collective on Mat
4666 
4667    Input Parameters:
4668 .  mat - the matrix
4669 
4670    Output Parameters:
4671 .  flg - PETSC_TRUE if uses the ordering
4672 
4673    Notes:
4674       Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4675       packages do not, thus we want to skip generating the ordering when it is not needed or used.
4676 
4677    Level: developer
4678 
4679 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4680 @*/
4681 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4682 {
4683   PetscFunctionBegin;
4684   *flg = mat->canuseordering;
4685   PetscFunctionReturn(0);
4686 }
4687 
4688 /*@C
4689    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4690 
4691    Logically Collective on Mat
4692 
4693    Input Parameters:
4694 .  mat - the matrix
4695 
4696    Output Parameters:
4697 .  otype - the preferred type
4698 
4699    Level: developer
4700 
4701 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4702 @*/
4703 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4704 {
4705   PetscFunctionBegin;
4706   *otype = mat->preferredordering[ftype];
4707   PetscCheck(*otype,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatFactor did not have a preferred ordering");
4708   PetscFunctionReturn(0);
4709 }
4710 
4711 /*@C
4712    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4713 
4714    Collective on Mat
4715 
4716    Input Parameters:
4717 +  mat - the matrix
4718 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4719 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4720 
4721    Output Parameters:
4722 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4723 
4724    Options Database Key:
4725 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4726                                   One can choose host to save device memory). Currently only supported with SEQAIJCUSPARSE matrices.
4727 
4728    Notes:
4729       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4730      such as pastix, superlu, mumps etc.
4731 
4732       PETSc must have been ./configure to use the external solver, using the option --download-package
4733 
4734       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4735       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4736       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4737 
4738    Developer Notes:
4739       This should actually be called MatCreateFactor() since it creates a new factor object
4740 
4741    Level: intermediate
4742 
4743 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`
4744 @*/
4745 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type,MatFactorType ftype,Mat *f)
4746 {
4747   PetscBool      foundtype,foundmtype;
4748   PetscErrorCode (*conv)(Mat,MatFactorType,Mat*);
4749 
4750   PetscFunctionBegin;
4751   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4752   PetscValidType(mat,1);
4753 
4754   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4755   MatCheckPreallocated(mat,1);
4756 
4757   PetscCall(MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,&foundtype,&foundmtype,&conv));
4758   if (!foundtype) {
4759     if (type) {
4760       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);
4761     } else {
4762       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);
4763     }
4764   }
4765   PetscCheck(foundmtype,PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"MatSolverType %s does not support matrix type %s",type,((PetscObject)mat)->type_name);
4766   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);
4767 
4768   PetscCall((*conv)(mat,ftype,f));
4769   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f,mat->factorprefix));
4770   PetscFunctionReturn(0);
4771 }
4772 
4773 /*@C
4774    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4775 
4776    Not Collective
4777 
4778    Input Parameters:
4779 +  mat - the matrix
4780 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4781 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4782 
4783    Output Parameter:
4784 .    flg - PETSC_TRUE if the factorization is available
4785 
4786    Notes:
4787       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4788      such as pastix, superlu, mumps etc.
4789 
4790       PETSc must have been ./configure to use the external solver, using the option --download-package
4791 
4792    Developer Notes:
4793       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4794 
4795    Level: intermediate
4796 
4797 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`
4798 @*/
4799 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type,MatFactorType ftype,PetscBool  *flg)
4800 {
4801   PetscErrorCode (*gconv)(Mat,MatFactorType,Mat*);
4802 
4803   PetscFunctionBegin;
4804   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4805   PetscValidType(mat,1);
4806   PetscValidBoolPointer(flg,4);
4807 
4808   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4809   MatCheckPreallocated(mat,1);
4810 
4811   PetscCall(MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,NULL,NULL,&gconv));
4812   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4813   PetscFunctionReturn(0);
4814 }
4815 
4816 /*@
4817    MatDuplicate - Duplicates a matrix including the non-zero structure.
4818 
4819    Collective on Mat
4820 
4821    Input Parameters:
4822 +  mat - the matrix
4823 -  op - One of MAT_DO_NOT_COPY_VALUES, MAT_COPY_VALUES, or MAT_SHARE_NONZERO_PATTERN.
4824         See the manual page for MatDuplicateOption for an explanation of these options.
4825 
4826    Output Parameter:
4827 .  M - pointer to place new matrix
4828 
4829    Level: intermediate
4830 
4831    Notes:
4832     You cannot change the nonzero pattern for the parent or child matrix if you use MAT_SHARE_NONZERO_PATTERN.
4833     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.
4834     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.
4835 
4836 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4837 @*/
4838 PetscErrorCode MatDuplicate(Mat mat,MatDuplicateOption op,Mat *M)
4839 {
4840   Mat            B;
4841   VecType        vtype;
4842   PetscInt       i;
4843   PetscObject    dm;
4844   void           (*viewf)(void);
4845 
4846   PetscFunctionBegin;
4847   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4848   PetscValidType(mat,1);
4849   PetscValidPointer(M,3);
4850   PetscCheck(op != MAT_COPY_VALUES || mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MAT_COPY_VALUES not allowed for unassembled matrix");
4851   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4852   MatCheckPreallocated(mat,1);
4853 
4854   *M = NULL;
4855   PetscCheck(mat->ops->duplicate,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not written for matrix type %s",((PetscObject)mat)->type_name);
4856   PetscCall(PetscLogEventBegin(MAT_Convert,mat,0,0,0));
4857   PetscCall((*mat->ops->duplicate)(mat,op,M));
4858   PetscCall(PetscLogEventEnd(MAT_Convert,mat,0,0,0));
4859   B    = *M;
4860 
4861   PetscCall(MatGetOperation(mat,MATOP_VIEW,&viewf));
4862   if (viewf) PetscCall(MatSetOperation(B,MATOP_VIEW,viewf));
4863   PetscCall(MatGetVecType(mat,&vtype));
4864   PetscCall(MatSetVecType(B,vtype));
4865 
4866   B->stencil.dim = mat->stencil.dim;
4867   B->stencil.noc = mat->stencil.noc;
4868   for (i=0; i<=mat->stencil.dim; i++) {
4869     B->stencil.dims[i]   = mat->stencil.dims[i];
4870     B->stencil.starts[i] = mat->stencil.starts[i];
4871   }
4872 
4873   B->nooffproczerorows = mat->nooffproczerorows;
4874   B->nooffprocentries  = mat->nooffprocentries;
4875 
4876   PetscCall(PetscObjectQuery((PetscObject) mat, "__PETSc_dm", &dm));
4877   if (dm) {
4878     PetscCall(PetscObjectCompose((PetscObject) B, "__PETSc_dm", dm));
4879   }
4880   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4881   PetscFunctionReturn(0);
4882 }
4883 
4884 /*@
4885    MatGetDiagonal - Gets the diagonal of a matrix.
4886 
4887    Logically Collective on Mat
4888 
4889    Input Parameters:
4890 +  mat - the matrix
4891 -  v - the vector for storing the diagonal
4892 
4893    Output Parameter:
4894 .  v - the diagonal of the matrix
4895 
4896    Level: intermediate
4897 
4898    Note:
4899    Currently only correct in parallel for square matrices.
4900 
4901 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4902 @*/
4903 PetscErrorCode MatGetDiagonal(Mat mat,Vec v)
4904 {
4905   PetscFunctionBegin;
4906   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4907   PetscValidType(mat,1);
4908   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4909   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4910   PetscCheck(mat->ops->getdiagonal,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4911   MatCheckPreallocated(mat,1);
4912 
4913   PetscCall((*mat->ops->getdiagonal)(mat,v));
4914   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4915   PetscFunctionReturn(0);
4916 }
4917 
4918 /*@C
4919    MatGetRowMin - Gets the minimum value (of the real part) of each
4920         row of the matrix
4921 
4922    Logically Collective on Mat
4923 
4924    Input Parameter:
4925 .  mat - the matrix
4926 
4927    Output Parameters:
4928 +  v - the vector for storing the maximums
4929 -  idx - the indices of the column found for each row (optional)
4930 
4931    Level: intermediate
4932 
4933    Notes:
4934     The result of this call are the same as if one converted the matrix to dense format
4935       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4936 
4937     This code is only implemented for a couple of matrix formats.
4938 
4939 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`,
4940           `MatGetRowMax()`
4941 @*/
4942 PetscErrorCode MatGetRowMin(Mat mat,Vec v,PetscInt idx[])
4943 {
4944   PetscFunctionBegin;
4945   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4946   PetscValidType(mat,1);
4947   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4948   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4949 
4950   if (!mat->cmap->N) {
4951     PetscCall(VecSet(v,PETSC_MAX_REAL));
4952     if (idx) {
4953       PetscInt i,m = mat->rmap->n;
4954       for (i=0; i<m; i++) idx[i] = -1;
4955     }
4956   } else {
4957     PetscCheck(mat->ops->getrowmin,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4958     MatCheckPreallocated(mat,1);
4959   }
4960   PetscCall((*mat->ops->getrowmin)(mat,v,idx));
4961   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4962   PetscFunctionReturn(0);
4963 }
4964 
4965 /*@C
4966    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4967         row of the matrix
4968 
4969    Logically Collective on Mat
4970 
4971    Input Parameter:
4972 .  mat - the matrix
4973 
4974    Output Parameters:
4975 +  v - the vector for storing the minimums
4976 -  idx - the indices of the column found for each row (or NULL if not needed)
4977 
4978    Level: intermediate
4979 
4980    Notes:
4981     if a row is completely empty or has only 0.0 values then the idx[] value for that
4982     row is 0 (the first column).
4983 
4984     This code is only implemented for a couple of matrix formats.
4985 
4986 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4987 @*/
4988 PetscErrorCode MatGetRowMinAbs(Mat mat,Vec v,PetscInt idx[])
4989 {
4990   PetscFunctionBegin;
4991   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4992   PetscValidType(mat,1);
4993   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4994   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4995   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4996 
4997   if (!mat->cmap->N) {
4998     PetscCall(VecSet(v,0.0));
4999     if (idx) {
5000       PetscInt i,m = mat->rmap->n;
5001       for (i=0; i<m; i++) idx[i] = -1;
5002     }
5003   } else {
5004     PetscCheck(mat->ops->getrowminabs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5005     MatCheckPreallocated(mat,1);
5006     if (idx) PetscCall(PetscArrayzero(idx,mat->rmap->n));
5007     PetscCall((*mat->ops->getrowminabs)(mat,v,idx));
5008   }
5009   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5010   PetscFunctionReturn(0);
5011 }
5012 
5013 /*@C
5014    MatGetRowMax - Gets the maximum value (of the real part) of each
5015         row of the matrix
5016 
5017    Logically Collective on Mat
5018 
5019    Input Parameter:
5020 .  mat - the matrix
5021 
5022    Output Parameters:
5023 +  v - the vector for storing the maximums
5024 -  idx - the indices of the column found for each row (optional)
5025 
5026    Level: intermediate
5027 
5028    Notes:
5029     The result of this call are the same as if one converted the matrix to dense format
5030       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5031 
5032     This code is only implemented for a couple of matrix formats.
5033 
5034 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5035 @*/
5036 PetscErrorCode MatGetRowMax(Mat mat,Vec v,PetscInt idx[])
5037 {
5038   PetscFunctionBegin;
5039   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5040   PetscValidType(mat,1);
5041   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5042   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5043 
5044   if (!mat->cmap->N) {
5045     PetscCall(VecSet(v,PETSC_MIN_REAL));
5046     if (idx) {
5047       PetscInt i,m = mat->rmap->n;
5048       for (i=0; i<m; i++) idx[i] = -1;
5049     }
5050   } else {
5051     PetscCheck(mat->ops->getrowmax,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5052     MatCheckPreallocated(mat,1);
5053     PetscCall((*mat->ops->getrowmax)(mat,v,idx));
5054   }
5055   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5056   PetscFunctionReturn(0);
5057 }
5058 
5059 /*@C
5060    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5061         row of the matrix
5062 
5063    Logically Collective on Mat
5064 
5065    Input Parameter:
5066 .  mat - the matrix
5067 
5068    Output Parameters:
5069 +  v - the vector for storing the maximums
5070 -  idx - the indices of the column found for each row (or NULL if not needed)
5071 
5072    Level: intermediate
5073 
5074    Notes:
5075     if a row is completely empty or has only 0.0 values then the idx[] value for that
5076     row is 0 (the first column).
5077 
5078     This code is only implemented for a couple of matrix formats.
5079 
5080 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`
5081 @*/
5082 PetscErrorCode MatGetRowMaxAbs(Mat mat,Vec v,PetscInt idx[])
5083 {
5084   PetscFunctionBegin;
5085   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5086   PetscValidType(mat,1);
5087   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5088   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5089 
5090   if (!mat->cmap->N) {
5091     PetscCall(VecSet(v,0.0));
5092     if (idx) {
5093       PetscInt i,m = mat->rmap->n;
5094       for (i=0; i<m; i++) idx[i] = -1;
5095     }
5096   } else {
5097     PetscCheck(mat->ops->getrowmaxabs,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5098     MatCheckPreallocated(mat,1);
5099     if (idx) PetscCall(PetscArrayzero(idx,mat->rmap->n));
5100     PetscCall((*mat->ops->getrowmaxabs)(mat,v,idx));
5101   }
5102   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5103   PetscFunctionReturn(0);
5104 }
5105 
5106 /*@
5107    MatGetRowSum - Gets the sum of each row of the matrix
5108 
5109    Logically or Neighborhood Collective on Mat
5110 
5111    Input Parameters:
5112 .  mat - the matrix
5113 
5114    Output Parameter:
5115 .  v - the vector for storing the sum of rows
5116 
5117    Level: intermediate
5118 
5119    Notes:
5120     This code is slow since it is not currently specialized for different formats
5121 
5122 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`
5123 @*/
5124 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5125 {
5126   Vec            ones;
5127 
5128   PetscFunctionBegin;
5129   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5130   PetscValidType(mat,1);
5131   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5132   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5133   MatCheckPreallocated(mat,1);
5134   PetscCall(MatCreateVecs(mat,&ones,NULL));
5135   PetscCall(VecSet(ones,1.));
5136   PetscCall(MatMult(mat,ones,v));
5137   PetscCall(VecDestroy(&ones));
5138   PetscFunctionReturn(0);
5139 }
5140 
5141 /*@
5142    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5143    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5144 
5145    Collective on Mat
5146 
5147    Input Parameter:
5148 .  mat - the matrix to provide the transpose
5149 
5150    Output Parameter:
5151 .  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
5152 
5153    Level: advanced
5154 
5155    Note:
5156    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
5157    routine allows bypassing that call.
5158 
5159 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5160 @*/
5161 PetscErrorCode MatTransposeSetPrecursor(Mat mat,Mat B)
5162 {
5163   PetscContainer rB = NULL;
5164   MatParentState *rb = NULL;
5165 
5166   PetscFunctionBegin;
5167   PetscCall(PetscNew(&rb));
5168   rb->id           = ((PetscObject)mat)->id;
5169   rb->state        = 0;
5170   PetscCall(MatGetNonzeroState(mat,&rb->nonzerostate));
5171   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B),&rB));
5172   PetscCall(PetscContainerSetPointer(rB,rb));
5173   PetscCall(PetscContainerSetUserDestroy(rB,PetscContainerUserDestroyDefault));
5174   PetscCall(PetscObjectCompose((PetscObject)B,"MatTransposeParent",(PetscObject)rB));
5175   PetscCall(PetscObjectDereference((PetscObject)rB));
5176   PetscFunctionReturn(0);
5177 }
5178 
5179 /*@
5180    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5181 
5182    Collective on Mat
5183 
5184    Input Parameters:
5185 +  mat - the matrix to transpose
5186 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5187 
5188    Output Parameter:
5189 .  B - the transpose
5190 
5191    Notes:
5192      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5193 
5194      `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
5195      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5196 
5197      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.
5198 
5199      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5200 
5201      If mat is unchanged from the last call this function returns immediately without recomputing the result
5202 
5203      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5204 
5205    Level: intermediate
5206 
5207 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5208           `MatTransposeSymbolic()`
5209 @*/
5210 PetscErrorCode MatTranspose(Mat mat,MatReuse reuse,Mat *B)
5211 {
5212   PetscContainer rB = NULL;
5213   MatParentState *rb = NULL;
5214 
5215   PetscFunctionBegin;
5216   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5217   PetscValidType(mat,1);
5218   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5219   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5220   PetscCheck(mat->ops->transpose,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5221   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires last matrix to match first");
5222   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Perhaps you mean MAT_INPLACE_MATRIX");
5223   MatCheckPreallocated(mat,1);
5224   if (reuse == MAT_REUSE_MATRIX) {
5225     PetscCall(PetscObjectQuery((PetscObject)*B,"MatTransposeParent",(PetscObject*)&rB));
5226     PetscCheck(rB,PetscObjectComm((PetscObject)*B),PETSC_ERR_ARG_WRONG,"Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5227     PetscCall(PetscContainerGetPointer(rB,(void**)&rb));
5228     PetscCheck(rb->id == ((PetscObject)mat)->id,PetscObjectComm((PetscObject)*B),PETSC_ERR_ARG_WRONG,"Reuse matrix used was not generated from input matrix");
5229     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0);
5230   }
5231 
5232   PetscCall(PetscLogEventBegin(MAT_Transpose,mat,0,0,0));
5233   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5234     PetscCall((*mat->ops->transpose)(mat,reuse,B));
5235     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5236   }
5237   PetscCall(PetscLogEventEnd(MAT_Transpose,mat,0,0,0));
5238 
5239   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat,*B));
5240   if (reuse != MAT_INPLACE_MATRIX) {
5241     PetscCall(PetscObjectQuery((PetscObject)*B,"MatTransposeParent",(PetscObject*)&rB));
5242     PetscCall(PetscContainerGetPointer(rB,(void**)&rb));
5243     rb->state        = ((PetscObject)mat)->state;
5244     rb->nonzerostate = mat->nonzerostate;
5245   }
5246   PetscFunctionReturn(0);
5247 }
5248 
5249 /*@
5250    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5251 
5252    Collective on Mat
5253 
5254    Input Parameters:
5255 .  A - the matrix to transpose
5256 
5257    Output Parameter:
5258 .  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
5259       numerical portion.
5260 
5261    Level: intermediate
5262 
5263    Note:
5264    This is not supported for many matrix types, use `MatTranspose()` in those cases
5265 
5266 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5267 @*/
5268 PetscErrorCode MatTransposeSymbolic(Mat A,Mat *B)
5269 {
5270   PetscFunctionBegin;
5271   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5272   PetscValidType(A,1);
5273   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5274   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5275   PetscCheck(A->ops->transposesymbolic,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
5276   PetscCall(PetscLogEventBegin(MAT_Transpose,A,0,0,0));
5277   PetscCall((*A->ops->transposesymbolic)(A,B));
5278   PetscCall(PetscLogEventEnd(MAT_Transpose,A,0,0,0));
5279 
5280   PetscCall(MatTransposeSetPrecursor(A,*B));
5281   PetscFunctionReturn(0);
5282 }
5283 
5284 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A,Mat B)
5285 {
5286   PetscContainer  rB;
5287   MatParentState  *rb;
5288 
5289   PetscFunctionBegin;
5290   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5291   PetscValidType(A,1);
5292   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5293   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5294   PetscCall(PetscObjectQuery((PetscObject)B,"MatTransposeParent",(PetscObject*)&rB));
5295   PetscCheck(rB,PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONG,"Reuse matrix used was not generated from call to MatTranspose()");
5296   PetscCall(PetscContainerGetPointer(rB,(void**)&rb));
5297   PetscCheck(rb->id == ((PetscObject)A)->id,PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONG,"Reuse matrix used was not generated from input matrix");
5298   PetscCheck(rb->nonzerostate == A->nonzerostate,PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Reuse matrix has changed nonzero structure");
5299   PetscFunctionReturn(0);
5300 }
5301 
5302 /*@
5303    MatIsTranspose - Test whether a matrix is another one's transpose,
5304         or its own, in which case it tests symmetry.
5305 
5306    Collective on Mat
5307 
5308    Input Parameters:
5309 +  A - the matrix to test
5310 -  B - the matrix to test against, this can equal the first parameter
5311 
5312    Output Parameters:
5313 .  flg - the result
5314 
5315    Notes:
5316    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5317    has a running time of the order of the number of nonzeros; the parallel
5318    test involves parallel copies of the block-offdiagonal parts of the matrix.
5319 
5320    Level: intermediate
5321 
5322 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5323 @*/
5324 PetscErrorCode MatIsTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5325 {
5326   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5327 
5328   PetscFunctionBegin;
5329   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5330   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5331   PetscValidBoolPointer(flg,4);
5332   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsTranspose_C",&f));
5333   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsTranspose_C",&g));
5334   *flg = PETSC_FALSE;
5335   if (f && g) {
5336     PetscCheck(f == g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for symmetry test");
5337     PetscCall((*f)(A,B,tol,flg));
5338   } else {
5339     MatType mattype;
5340 
5341     PetscCall(MatGetType(f ? B : A,&mattype));
5342     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for transpose",mattype);
5343   }
5344   PetscFunctionReturn(0);
5345 }
5346 
5347 /*@
5348    MatHermitianTranspose - Computes an in-place or out-of-place transpose of a matrix in complex conjugate.
5349 
5350    Collective on Mat
5351 
5352    Input Parameters:
5353 +  mat - the matrix to transpose and complex conjugate
5354 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5355 
5356    Output Parameter:
5357 .  B - the Hermitian
5358 
5359    Level: intermediate
5360 
5361 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5362 @*/
5363 PetscErrorCode MatHermitianTranspose(Mat mat,MatReuse reuse,Mat *B)
5364 {
5365   PetscFunctionBegin;
5366   PetscCall(MatTranspose(mat,reuse,B));
5367 #if defined(PETSC_USE_COMPLEX)
5368   PetscCall(MatConjugate(*B));
5369 #endif
5370   PetscFunctionReturn(0);
5371 }
5372 
5373 /*@
5374    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5375 
5376    Collective on Mat
5377 
5378    Input Parameters:
5379 +  A - the matrix to test
5380 -  B - the matrix to test against, this can equal the first parameter
5381 
5382    Output Parameters:
5383 .  flg - the result
5384 
5385    Notes:
5386    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5387    has a running time of the order of the number of nonzeros; the parallel
5388    test involves parallel copies of the block-offdiagonal parts of the matrix.
5389 
5390    Level: intermediate
5391 
5392 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5393 @*/
5394 PetscErrorCode MatIsHermitianTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5395 {
5396   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5397 
5398   PetscFunctionBegin;
5399   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5400   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5401   PetscValidBoolPointer(flg,4);
5402   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsHermitianTranspose_C",&f));
5403   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsHermitianTranspose_C",&g));
5404   if (f && g) {
5405     PetscCheck(f != g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for Hermitian test");
5406     PetscCall((*f)(A,B,tol,flg));
5407   }
5408   PetscFunctionReturn(0);
5409 }
5410 
5411 /*@
5412    MatPermute - Creates a new matrix with rows and columns permuted from the
5413    original.
5414 
5415    Collective on Mat
5416 
5417    Input Parameters:
5418 +  mat - the matrix to permute
5419 .  row - row permutation, each processor supplies only the permutation for its rows
5420 -  col - column permutation, each processor supplies only the permutation for its columns
5421 
5422    Output Parameters:
5423 .  B - the permuted matrix
5424 
5425    Level: advanced
5426 
5427    Note:
5428    The index sets map from row/col of permuted matrix to row/col of original matrix.
5429    The index sets should be on the same communicator as Mat and have the same local sizes.
5430 
5431    Developer Note:
5432      If you want to implement MatPermute for a matrix type, and your approach doesn't
5433      exploit the fact that row and col are permutations, consider implementing the
5434      more general MatCreateSubMatrix() instead.
5435 
5436 .seealso: `MatGetOrdering()`, `ISAllGather()`
5437 
5438 @*/
5439 PetscErrorCode MatPermute(Mat mat,IS row,IS col,Mat *B)
5440 {
5441   PetscFunctionBegin;
5442   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5443   PetscValidType(mat,1);
5444   PetscValidHeaderSpecific(row,IS_CLASSID,2);
5445   PetscValidHeaderSpecific(col,IS_CLASSID,3);
5446   PetscValidPointer(B,4);
5447   PetscCheckSameComm(mat,1,row,2);
5448   if (row != col) PetscCheckSameComm(row,2,col,3);
5449   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5450   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5451   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatPermute not available for Mat type %s",((PetscObject)mat)->type_name);
5452   MatCheckPreallocated(mat,1);
5453 
5454   if (mat->ops->permute) {
5455     PetscCall((*mat->ops->permute)(mat,row,col,B));
5456     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5457   } else {
5458     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5459   }
5460   PetscFunctionReturn(0);
5461 }
5462 
5463 /*@
5464    MatEqual - Compares two matrices.
5465 
5466    Collective on Mat
5467 
5468    Input Parameters:
5469 +  A - the first matrix
5470 -  B - the second matrix
5471 
5472    Output Parameter:
5473 .  flg - PETSC_TRUE if the matrices are equal; PETSC_FALSE otherwise.
5474 
5475    Level: intermediate
5476 
5477 @*/
5478 PetscErrorCode MatEqual(Mat A,Mat B,PetscBool *flg)
5479 {
5480   PetscFunctionBegin;
5481   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5482   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5483   PetscValidType(A,1);
5484   PetscValidType(B,2);
5485   PetscValidBoolPointer(flg,3);
5486   PetscCheckSameComm(A,1,B,2);
5487   MatCheckPreallocated(A,1);
5488   MatCheckPreallocated(B,2);
5489   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5490   PetscCheck(B->assembled,PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5491   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);
5492   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5493     PetscCall((*A->ops->equal)(A,B,flg));
5494   } else {
5495     PetscCall(MatMultEqual(A,B,10,flg));
5496   }
5497   PetscFunctionReturn(0);
5498 }
5499 
5500 /*@
5501    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5502    matrices that are stored as vectors.  Either of the two scaling
5503    matrices can be NULL.
5504 
5505    Collective on Mat
5506 
5507    Input Parameters:
5508 +  mat - the matrix to be scaled
5509 .  l - the left scaling vector (or NULL)
5510 -  r - the right scaling vector (or NULL)
5511 
5512    Notes:
5513    MatDiagonalScale() computes A = LAR, where
5514    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5515    The L scales the rows of the matrix, the R scales the columns of the matrix.
5516 
5517    Level: intermediate
5518 
5519 .seealso: `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5520 @*/
5521 PetscErrorCode MatDiagonalScale(Mat mat,Vec l,Vec r)
5522 {
5523   PetscFunctionBegin;
5524   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5525   PetscValidType(mat,1);
5526   if (l) {PetscValidHeaderSpecific(l,VEC_CLASSID,2);PetscCheckSameComm(mat,1,l,2);}
5527   if (r) {PetscValidHeaderSpecific(r,VEC_CLASSID,3);PetscCheckSameComm(mat,1,r,3);}
5528   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5529   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5530   MatCheckPreallocated(mat,1);
5531   if (!l && !r) PetscFunctionReturn(0);
5532 
5533   PetscCheck(mat->ops->diagonalscale,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5534   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5535   PetscCall((*mat->ops->diagonalscale)(mat,l,r));
5536   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5537   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5538   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5539   PetscFunctionReturn(0);
5540 }
5541 
5542 /*@
5543     MatScale - Scales all elements of a matrix by a given number.
5544 
5545     Logically Collective on Mat
5546 
5547     Input Parameters:
5548 +   mat - the matrix to be scaled
5549 -   a  - the scaling value
5550 
5551     Output Parameter:
5552 .   mat - the scaled matrix
5553 
5554     Level: intermediate
5555 
5556 .seealso: `MatDiagonalScale()`
5557 @*/
5558 PetscErrorCode MatScale(Mat mat,PetscScalar a)
5559 {
5560   PetscFunctionBegin;
5561   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5562   PetscValidType(mat,1);
5563   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5564   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5565   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5566   PetscValidLogicalCollectiveScalar(mat,a,2);
5567   MatCheckPreallocated(mat,1);
5568 
5569   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5570   if (a != (PetscScalar)1.0) {
5571     PetscCall((*mat->ops->scale)(mat,a));
5572     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5573   }
5574   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5575   PetscFunctionReturn(0);
5576 }
5577 
5578 /*@
5579    MatNorm - Calculates various norms of a matrix.
5580 
5581    Collective on Mat
5582 
5583    Input Parameters:
5584 +  mat - the matrix
5585 -  type - the type of norm, NORM_1, NORM_FROBENIUS, NORM_INFINITY
5586 
5587    Output Parameter:
5588 .  nrm - the resulting norm
5589 
5590    Level: intermediate
5591 
5592 @*/
5593 PetscErrorCode MatNorm(Mat mat,NormType type,PetscReal *nrm)
5594 {
5595   PetscFunctionBegin;
5596   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5597   PetscValidType(mat,1);
5598   PetscValidRealPointer(nrm,3);
5599 
5600   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5601   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5602   PetscCheck(mat->ops->norm,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5603   MatCheckPreallocated(mat,1);
5604 
5605   PetscCall((*mat->ops->norm)(mat,type,nrm));
5606   PetscFunctionReturn(0);
5607 }
5608 
5609 /*
5610      This variable is used to prevent counting of MatAssemblyBegin() that
5611    are called from within a MatAssemblyEnd().
5612 */
5613 static PetscInt MatAssemblyEnd_InUse = 0;
5614 /*@
5615    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5616    be called after completing all calls to MatSetValues().
5617 
5618    Collective on Mat
5619 
5620    Input Parameters:
5621 +  mat - the matrix
5622 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5623 
5624    Notes:
5625    MatSetValues() generally caches the values.  The matrix is ready to
5626    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5627    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5628    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5629    using the matrix.
5630 
5631    ALL processes that share a matrix MUST call MatAssemblyBegin() and MatAssemblyEnd() the SAME NUMBER of times, and each time with the
5632    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
5633    a global collective operation requring all processes that share the matrix.
5634 
5635    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5636    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5637    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5638 
5639    Level: beginner
5640 
5641 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5642 @*/
5643 PetscErrorCode MatAssemblyBegin(Mat mat,MatAssemblyType type)
5644 {
5645   PetscFunctionBegin;
5646   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5647   PetscValidType(mat,1);
5648   MatCheckPreallocated(mat,1);
5649   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5650   if (mat->assembled) {
5651     mat->was_assembled = PETSC_TRUE;
5652     mat->assembled     = PETSC_FALSE;
5653   }
5654 
5655   if (!MatAssemblyEnd_InUse) {
5656     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin,mat,0,0,0));
5657     if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5658     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin,mat,0,0,0));
5659   } else if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5660   PetscFunctionReturn(0);
5661 }
5662 
5663 /*@
5664    MatAssembled - Indicates if a matrix has been assembled and is ready for
5665      use; for example, in matrix-vector product.
5666 
5667    Not Collective
5668 
5669    Input Parameter:
5670 .  mat - the matrix
5671 
5672    Output Parameter:
5673 .  assembled - PETSC_TRUE or PETSC_FALSE
5674 
5675    Level: advanced
5676 
5677 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5678 @*/
5679 PetscErrorCode MatAssembled(Mat mat,PetscBool *assembled)
5680 {
5681   PetscFunctionBegin;
5682   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5683   PetscValidBoolPointer(assembled,2);
5684   *assembled = mat->assembled;
5685   PetscFunctionReturn(0);
5686 }
5687 
5688 /*@
5689    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5690    be called after MatAssemblyBegin().
5691 
5692    Collective on Mat
5693 
5694    Input Parameters:
5695 +  mat - the matrix
5696 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5697 
5698    Options Database Keys:
5699 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatEndAssembly()
5700 .  -mat_view ::ascii_info_detail - Prints more detailed info
5701 .  -mat_view - Prints matrix in ASCII format
5702 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5703 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
5704 .  -display <name> - Sets display name (default is host)
5705 .  -draw_pause <sec> - Sets number of seconds to pause after display
5706 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab)
5707 .  -viewer_socket_machine <machine> - Machine to use for socket
5708 .  -viewer_socket_port <port> - Port number to use for socket
5709 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5710 
5711    Notes:
5712    MatSetValues() generally caches the values.  The matrix is ready to
5713    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5714    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5715    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5716    using the matrix.
5717 
5718    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5719    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5720    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5721 
5722    Level: beginner
5723 
5724 .seealso: `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5725 @*/
5726 PetscErrorCode MatAssemblyEnd(Mat mat,MatAssemblyType type)
5727 {
5728   static PetscInt inassm = 0;
5729   PetscBool       flg    = PETSC_FALSE;
5730 
5731   PetscFunctionBegin;
5732   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5733   PetscValidType(mat,1);
5734 
5735   inassm++;
5736   MatAssemblyEnd_InUse++;
5737   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5738     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd,mat,0,0,0));
5739     if (mat->ops->assemblyend) PetscCall((*mat->ops->assemblyend)(mat,type));
5740     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd,mat,0,0,0));
5741   } else if (mat->ops->assemblyend) PetscCall((*mat->ops->assemblyend)(mat,type));
5742 
5743   /* Flush assembly is not a true assembly */
5744   if (type != MAT_FLUSH_ASSEMBLY) {
5745     if (mat->num_ass) {
5746       if (!mat->symmetry_eternal) {
5747         mat->symmetric              = PETSC_BOOL3_UNKNOWN;
5748         mat->hermitian              = PETSC_BOOL3_UNKNOWN;
5749       }
5750       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) {
5751         mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5752       }
5753       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5754     }
5755     mat->num_ass++;
5756     mat->assembled        = PETSC_TRUE;
5757     mat->ass_nonzerostate = mat->nonzerostate;
5758   }
5759 
5760   mat->insertmode = NOT_SET_VALUES;
5761   MatAssemblyEnd_InUse--;
5762   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5763   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5764     PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5765 
5766     if (mat->checksymmetryonassembly) {
5767       PetscCall(MatIsSymmetric(mat,mat->checksymmetrytol,&flg));
5768       if (flg) {
5769         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5770       } else {
5771         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is not symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5772       }
5773     }
5774     if (mat->nullsp && mat->checknullspaceonassembly) {
5775       PetscCall(MatNullSpaceTest(mat->nullsp,mat,NULL));
5776     }
5777   }
5778   inassm--;
5779   PetscFunctionReturn(0);
5780 }
5781 
5782 /*@
5783    MatSetOption - Sets a parameter option for a matrix. Some options
5784    may be specific to certain storage formats.  Some options
5785    determine how values will be inserted (or added). Sorted,
5786    row-oriented input will generally assemble the fastest. The default
5787    is row-oriented.
5788 
5789    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5790 
5791    Input Parameters:
5792 +  mat - the matrix
5793 .  option - the option, one of those listed below (and possibly others),
5794 -  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5795 
5796   Options Describing Matrix Structure:
5797 +    MAT_SPD - symmetric positive definite
5798 .    MAT_SYMMETRIC - symmetric in terms of both structure and value
5799 .    MAT_HERMITIAN - transpose is the complex conjugation
5800 .    MAT_STRUCTURALLY_SYMMETRIC - symmetric nonzero structure
5801 .    MAT_SYMMETRY_ETERNAL - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5802 .    MAT_STRUCTURAL_SYMMETRY_ETERNAL - indicates the structural symmetry or its absence will persist through any changes to the matrix
5803 -    MAT_SPD_ETERNAL - indicates the value of MAT_SPD (true or false) will persist through any changes to the matrix
5804 
5805    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5806    do not need to be computed (usually at a high cost)
5807 
5808    Options For Use with MatSetValues():
5809    Insert a logically dense subblock, which can be
5810 .    MAT_ROW_ORIENTED - row-oriented (default)
5811 
5812    Note these options reflect the data you pass in with MatSetValues(); it has
5813    nothing to do with how the data is stored internally in the matrix
5814    data structure.
5815 
5816    When (re)assembling a matrix, we can restrict the input for
5817    efficiency/debugging purposes.  These options include
5818 +    MAT_NEW_NONZERO_LOCATIONS - additional insertions will be allowed if they generate a new nonzero (slow)
5819 .    MAT_FORCE_DIAGONAL_ENTRIES - forces diagonal entries to be allocated
5820 .    MAT_IGNORE_OFF_PROC_ENTRIES - drops off-processor entries
5821 .    MAT_NEW_NONZERO_LOCATION_ERR - generates an error for new matrix entry
5822 .    MAT_USE_HASH_TABLE - uses a hash table to speed up matrix assembly
5823 .    MAT_NO_OFF_PROC_ENTRIES - you know each process will only set values for its own rows, will generate an error if
5824         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5825         performance for very large process counts.
5826 -    MAT_SUBSET_OFF_PROC_ENTRIES - you know that the first assembly after setting this flag will set a superset
5827         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5828         functions, instead sending only neighbor messages.
5829 
5830    Notes:
5831    Except for MAT_UNUSED_NONZERO_LOCATION_ERR and  MAT_ROW_ORIENTED all processes that share the matrix must pass the same value in flg!
5832 
5833    Some options are relevant only for particular matrix types and
5834    are thus ignored by others.  Other options are not supported by
5835    certain matrix types and will generate an error message if set.
5836 
5837    If using a Fortran 77 module to compute a matrix, one may need to
5838    use the column-oriented option (or convert to the row-oriented
5839    format).
5840 
5841    MAT_NEW_NONZERO_LOCATIONS set to PETSC_FALSE indicates that any add or insertion
5842    that would generate a new entry in the nonzero structure is instead
5843    ignored.  Thus, if memory has not alredy been allocated for this particular
5844    data, then the insertion is ignored. For dense matrices, in which
5845    the entire array is allocated, no entries are ever ignored.
5846    Set after the first MatAssemblyEnd(). If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5847 
5848    MAT_NEW_NONZERO_LOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5849    that would generate a new entry in the nonzero structure instead produces
5850    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
5851 
5852    MAT_NEW_NONZERO_ALLOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5853    that would generate a new entry that has not been preallocated will
5854    instead produce an error. (Currently supported for AIJ and BAIJ formats
5855    only.) This is a useful flag when debugging matrix memory preallocation.
5856    If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5857 
5858    MAT_IGNORE_OFF_PROC_ENTRIES set to PETSC_TRUE indicates entries destined for
5859    other processors should be dropped, rather than stashed.
5860    This is useful if you know that the "owning" processor is also
5861    always generating the correct matrix entries, so that PETSc need
5862    not transfer duplicate entries generated on another processor.
5863 
5864    MAT_USE_HASH_TABLE indicates that a hash table be used to improve the
5865    searches during matrix assembly. When this flag is set, the hash table
5866    is created during the first Matrix Assembly. This hash table is
5867    used the next time through, during MatSetVaules()/MatSetVaulesBlocked()
5868    to improve the searching of indices. MAT_NEW_NONZERO_LOCATIONS flag
5869    should be used with MAT_USE_HASH_TABLE flag. This option is currently
5870    supported by MATMPIBAIJ format only.
5871 
5872    MAT_KEEP_NONZERO_PATTERN indicates when MatZeroRows() is called the zeroed entries
5873    are kept in the nonzero structure
5874 
5875    MAT_IGNORE_ZERO_ENTRIES - for AIJ/IS matrices this will stop zero values from creating
5876    a zero location in the matrix
5877 
5878    MAT_USE_INODES - indicates using inode version of the code - works with AIJ matrix types
5879 
5880    MAT_NO_OFF_PROC_ZERO_ROWS - you know each process will only zero its own rows. This avoids all reductions in the
5881         zero row routines and thus improves performance for very large process counts.
5882 
5883    MAT_IGNORE_LOWER_TRIANGULAR - For SBAIJ matrices will ignore any insertions you make in the lower triangular
5884         part of the matrix (since they should match the upper triangular part).
5885 
5886    MAT_SORTED_FULL - each process provides exactly its local rows; all column indices for a given row are passed in a
5887                      single call to MatSetValues(), preallocation is perfect, row oriented, INSERT_VALUES is used. Common
5888                      with finite difference schemes with non-periodic boundary conditions.
5889 
5890    Developer Note:
5891    MAT_SYMMETRY_ETERNAL, MAT_STRUCTURAL_SYMMETRY_ETERNAL, and MAT_SPD_ETERNAL are used by MatAssemblyEnd() and in other
5892    places where otherwise the value of MAT_SYMMETRIC, MAT_STRUCTURAL_SYMMETRIC or MAT_SPD would need to be changed back
5893    to PETSC_BOOL3_UNKNOWN because the matrix values had changed so the code cannot be certain that the related property had
5894    not changed.
5895 
5896    Level: intermediate
5897 
5898 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5899 
5900 @*/
5901 PetscErrorCode MatSetOption(Mat mat,MatOption op,PetscBool flg)
5902 {
5903   PetscFunctionBegin;
5904   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5905   if (op > 0) {
5906     PetscValidLogicalCollectiveEnum(mat,op,2);
5907     PetscValidLogicalCollectiveBool(mat,flg,3);
5908   }
5909 
5910   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);
5911 
5912   switch (op) {
5913   case MAT_FORCE_DIAGONAL_ENTRIES:
5914     mat->force_diagonals = flg;
5915     PetscFunctionReturn(0);
5916   case MAT_NO_OFF_PROC_ENTRIES:
5917     mat->nooffprocentries = flg;
5918     PetscFunctionReturn(0);
5919   case MAT_SUBSET_OFF_PROC_ENTRIES:
5920     mat->assembly_subset = flg;
5921     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5922 #if !defined(PETSC_HAVE_MPIUNI)
5923       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5924 #endif
5925       mat->stash.first_assembly_done = PETSC_FALSE;
5926     }
5927     PetscFunctionReturn(0);
5928   case MAT_NO_OFF_PROC_ZERO_ROWS:
5929     mat->nooffproczerorows = flg;
5930     PetscFunctionReturn(0);
5931   case MAT_SPD:
5932     if (flg) {
5933       mat->spd                     = PETSC_BOOL3_TRUE;
5934       mat->symmetric               = PETSC_BOOL3_TRUE;
5935       mat->structurally_symmetric  = PETSC_BOOL3_TRUE;
5936     } else {
5937       mat->spd = PETSC_BOOL3_FALSE;
5938     }
5939     break;
5940   case MAT_SYMMETRIC:
5941     mat->symmetric                       = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5942     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5943 #if !defined(PETSC_USE_COMPLEX)
5944     mat->hermitian                       = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5945 #endif
5946     break;
5947   case MAT_HERMITIAN:
5948     mat->hermitian                       = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5949     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5950 #if !defined(PETSC_USE_COMPLEX)
5951     mat->symmetric                       = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5952 #endif
5953     break;
5954   case MAT_STRUCTURALLY_SYMMETRIC:
5955     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5956     break;
5957   case MAT_SYMMETRY_ETERNAL:
5958     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");
5959                mat->symmetry_eternal = flg;
5960     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5961     break;
5962   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5963     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");
5964     mat->structural_symmetry_eternal = flg;
5965     break;
5966   case MAT_SPD_ETERNAL:
5967     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");
5968     mat->spd_eternal = flg;
5969     if (flg) {
5970       mat->structural_symmetry_eternal = PETSC_TRUE;
5971       mat->symmetry_eternal            = PETSC_TRUE;
5972     }
5973     break;
5974   case MAT_STRUCTURE_ONLY:
5975     mat->structure_only = flg;
5976     break;
5977   case MAT_SORTED_FULL:
5978     mat->sortedfull = flg;
5979     break;
5980   default:
5981     break;
5982   }
5983   if (mat->ops->setoption) PetscCall((*mat->ops->setoption)(mat,op,flg));
5984   PetscFunctionReturn(0);
5985 }
5986 
5987 /*@
5988    MatGetOption - Gets a parameter option that has been set for a matrix.
5989 
5990    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5991 
5992    Input Parameters:
5993 +  mat - the matrix
5994 -  option - the option, this only responds to certain options, check the code for which ones
5995 
5996    Output Parameter:
5997 .  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5998 
5999     Notes:
6000     Can only be called after MatSetSizes() and MatSetType() have been set.
6001 
6002     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`, or
6003     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
6004 
6005    Level: intermediate
6006 
6007 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`,
6008     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
6009 
6010 @*/
6011 PetscErrorCode MatGetOption(Mat mat,MatOption op,PetscBool *flg)
6012 {
6013   PetscFunctionBegin;
6014   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6015   PetscValidType(mat,1);
6016 
6017   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);
6018   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()");
6019 
6020   switch (op) {
6021   case MAT_NO_OFF_PROC_ENTRIES:
6022     *flg = mat->nooffprocentries;
6023     break;
6024   case MAT_NO_OFF_PROC_ZERO_ROWS:
6025     *flg = mat->nooffproczerorows;
6026     break;
6027   case MAT_SYMMETRIC:
6028     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Use MatIsSymmetric() or MatIsSymmetricKnown()");
6029     break;
6030   case MAT_HERMITIAN:
6031     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Use MatIsHermitian() or MatIsHermitianKnown()");
6032     break;
6033   case MAT_STRUCTURALLY_SYMMETRIC:
6034     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6035     break;
6036   case MAT_SPD:
6037     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Use MatIsSPDKnown()");
6038     break;
6039   case MAT_SYMMETRY_ETERNAL:
6040     *flg = mat->symmetry_eternal;
6041     break;
6042   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6043     *flg = mat->symmetry_eternal;
6044     break;
6045   default:
6046     break;
6047   }
6048   PetscFunctionReturn(0);
6049 }
6050 
6051 /*@
6052    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6053    this routine retains the old nonzero structure.
6054 
6055    Logically Collective on Mat
6056 
6057    Input Parameters:
6058 .  mat - the matrix
6059 
6060    Level: intermediate
6061 
6062    Notes:
6063     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.
6064    See the Performance chapter of the users manual for information on preallocating matrices.
6065 
6066 .seealso: `MatZeroRows()`
6067 @*/
6068 PetscErrorCode MatZeroEntries(Mat mat)
6069 {
6070   PetscFunctionBegin;
6071   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6072   PetscValidType(mat,1);
6073   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6074   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");
6075   PetscCheck(mat->ops->zeroentries,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6076   MatCheckPreallocated(mat,1);
6077 
6078   PetscCall(PetscLogEventBegin(MAT_ZeroEntries,mat,0,0,0));
6079   PetscCall((*mat->ops->zeroentries)(mat));
6080   PetscCall(PetscLogEventEnd(MAT_ZeroEntries,mat,0,0,0));
6081   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6082   PetscFunctionReturn(0);
6083 }
6084 
6085 /*@
6086    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6087    of a set of rows and columns of a matrix.
6088 
6089    Collective on Mat
6090 
6091    Input Parameters:
6092 +  mat - the matrix
6093 .  numRows - the number of rows to remove
6094 .  rows - the global row indices
6095 .  diag - value put in the diagonal of the eliminated rows
6096 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6097 -  b - optional vector of right hand side, that will be adjusted by provided solution
6098 
6099    Notes:
6100    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6101 
6102    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6103    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
6104 
6105    If the resulting linear system is to be solved with KSP then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6106    Krylov method to take advantage of the known solution on the zeroed rows.
6107 
6108    For the parallel case, all processes that share the matrix (i.e.,
6109    those in the communicator used for matrix creation) MUST call this
6110    routine, regardless of whether any rows being zeroed are owned by
6111    them.
6112 
6113    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6114 
6115    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6116    list only rows local to itself).
6117 
6118    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
6119 
6120    Level: intermediate
6121 
6122 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6123           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6124 @*/
6125 PetscErrorCode MatZeroRowsColumns(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6126 {
6127   PetscFunctionBegin;
6128   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6129   PetscValidType(mat,1);
6130   if (numRows) PetscValidIntPointer(rows,3);
6131   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6132   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6133   PetscCheck(mat->ops->zerorowscolumns,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6134   MatCheckPreallocated(mat,1);
6135 
6136   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,rows,diag,x,b));
6137   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
6138   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6139   PetscFunctionReturn(0);
6140 }
6141 
6142 /*@
6143    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6144    of a set of rows and columns of a matrix.
6145 
6146    Collective on Mat
6147 
6148    Input Parameters:
6149 +  mat - the matrix
6150 .  is - the rows to zero
6151 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6152 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6153 -  b - optional vector of right hand side, that will be adjusted by provided solution
6154 
6155    Note:
6156    See `MatZeroRowsColumns()` for details on how this routine operates.
6157 
6158    Level: intermediate
6159 
6160 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6161           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6162 @*/
6163 PetscErrorCode MatZeroRowsColumnsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6164 {
6165   PetscInt       numRows;
6166   const PetscInt *rows;
6167 
6168   PetscFunctionBegin;
6169   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6170   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6171   PetscValidType(mat,1);
6172   PetscValidType(is,2);
6173   PetscCall(ISGetLocalSize(is,&numRows));
6174   PetscCall(ISGetIndices(is,&rows));
6175   PetscCall(MatZeroRowsColumns(mat,numRows,rows,diag,x,b));
6176   PetscCall(ISRestoreIndices(is,&rows));
6177   PetscFunctionReturn(0);
6178 }
6179 
6180 /*@
6181    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6182    of a set of rows of a matrix.
6183 
6184    Collective on Mat
6185 
6186    Input Parameters:
6187 +  mat - the matrix
6188 .  numRows - the number of rows to remove
6189 .  rows - the global row indices
6190 .  diag - value put in the diagonal of the eliminated rows
6191 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6192 -  b - optional vector of right hand side, that will be adjusted by provided solution
6193 
6194    Notes:
6195    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6196 
6197    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6198 
6199    If the resulting linear system is to be solved with KSP then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6200    Krylov method to take advantage of the known solution on the zeroed rows.
6201 
6202    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)
6203    from the matrix.
6204 
6205    Unlike `MatZeroRowsColumns()` for the AIJ and BAIJ matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6206    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
6207    formats this does not alter the nonzero structure.
6208 
6209    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6210    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6211    merely zeroed.
6212 
6213    The user can set a value in the diagonal entry (or for the AIJ and
6214    row formats can optionally remove the main diagonal entry from the
6215    nonzero structure as well, by passing 0.0 as the final argument).
6216 
6217    For the parallel case, all processes that share the matrix (i.e.,
6218    those in the communicator used for matrix creation) MUST call this
6219    routine, regardless of whether any rows being zeroed are owned by
6220    them.
6221 
6222    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6223    list only rows local to itself).
6224 
6225    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6226    owns that are to be zeroed. This saves a global synchronization in the implementation.
6227 
6228    Level: intermediate
6229 
6230 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6231           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6232 @*/
6233 PetscErrorCode MatZeroRows(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6234 {
6235   PetscFunctionBegin;
6236   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6237   PetscValidType(mat,1);
6238   if (numRows) PetscValidIntPointer(rows,3);
6239   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6240   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6241   PetscCheck(mat->ops->zerorows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6242   MatCheckPreallocated(mat,1);
6243 
6244   PetscCall((*mat->ops->zerorows)(mat,numRows,rows,diag,x,b));
6245   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
6246   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6247   PetscFunctionReturn(0);
6248 }
6249 
6250 /*@
6251    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6252    of a set of rows of a matrix.
6253 
6254    Collective on Mat
6255 
6256    Input Parameters:
6257 +  mat - the matrix
6258 .  is - index set of rows to remove (if NULL then no row is removed)
6259 .  diag - value put in all diagonals of eliminated rows
6260 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6261 -  b - optional vector of right hand side, that will be adjusted by provided solution
6262 
6263    Note:
6264    See `MatZeroRows()` for details on how this routine operates.
6265 
6266    Level: intermediate
6267 
6268 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6269           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6270 @*/
6271 PetscErrorCode MatZeroRowsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6272 {
6273   PetscInt       numRows = 0;
6274   const PetscInt *rows = NULL;
6275 
6276   PetscFunctionBegin;
6277   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6278   PetscValidType(mat,1);
6279   if (is) {
6280     PetscValidHeaderSpecific(is,IS_CLASSID,2);
6281     PetscCall(ISGetLocalSize(is,&numRows));
6282     PetscCall(ISGetIndices(is,&rows));
6283   }
6284   PetscCall(MatZeroRows(mat,numRows,rows,diag,x,b));
6285   if (is) {
6286     PetscCall(ISRestoreIndices(is,&rows));
6287   }
6288   PetscFunctionReturn(0);
6289 }
6290 
6291 /*@
6292    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6293    of a set of rows of a matrix. These rows must be local to the process.
6294 
6295    Collective on Mat
6296 
6297    Input Parameters:
6298 +  mat - the matrix
6299 .  numRows - the number of rows to remove
6300 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6301 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6302 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6303 -  b - optional vector of right hand side, that will be adjusted by provided solution
6304 
6305    Notes:
6306    See `MatZeroRows()` for details on how this routine operates.
6307 
6308    The grid coordinates are across the entire grid, not just the local portion
6309 
6310    In Fortran idxm and idxn should be declared as
6311 $     MatStencil idxm(4,m)
6312    and the values inserted using
6313 $    idxm(MatStencil_i,1) = i
6314 $    idxm(MatStencil_j,1) = j
6315 $    idxm(MatStencil_k,1) = k
6316 $    idxm(MatStencil_c,1) = c
6317    etc
6318 
6319    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6320    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6321    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6322    DM_BOUNDARY_PERIODIC boundary type.
6323 
6324    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
6325    a single value per point) you can skip filling those indices.
6326 
6327    Level: intermediate
6328 
6329 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6330           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6331 @*/
6332 PetscErrorCode MatZeroRowsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6333 {
6334   PetscInt       dim     = mat->stencil.dim;
6335   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6336   PetscInt       *dims   = mat->stencil.dims+1;
6337   PetscInt       *starts = mat->stencil.starts;
6338   PetscInt       *dxm    = (PetscInt*) rows;
6339   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6340 
6341   PetscFunctionBegin;
6342   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6343   PetscValidType(mat,1);
6344   if (numRows) PetscValidPointer(rows,3);
6345 
6346   PetscCall(PetscMalloc1(numRows, &jdxm));
6347   for (i = 0; i < numRows; ++i) {
6348     /* Skip unused dimensions (they are ordered k, j, i, c) */
6349     for (j = 0; j < 3-sdim; ++j) dxm++;
6350     /* Local index in X dir */
6351     tmp = *dxm++ - starts[0];
6352     /* Loop over remaining dimensions */
6353     for (j = 0; j < dim-1; ++j) {
6354       /* If nonlocal, set index to be negative */
6355       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6356       /* Update local index */
6357       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6358     }
6359     /* Skip component slot if necessary */
6360     if (mat->stencil.noc) dxm++;
6361     /* Local row number */
6362     if (tmp >= 0) {
6363       jdxm[numNewRows++] = tmp;
6364     }
6365   }
6366   PetscCall(MatZeroRowsLocal(mat,numNewRows,jdxm,diag,x,b));
6367   PetscCall(PetscFree(jdxm));
6368   PetscFunctionReturn(0);
6369 }
6370 
6371 /*@
6372    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6373    of a set of rows and columns of a matrix.
6374 
6375    Collective on Mat
6376 
6377    Input Parameters:
6378 +  mat - the matrix
6379 .  numRows - the number of rows/columns to remove
6380 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6381 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6382 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6383 -  b - optional vector of right hand side, that will be adjusted by provided solution
6384 
6385    Notes:
6386    See `MatZeroRowsColumns()` for details on how this routine operates.
6387 
6388    The grid coordinates are across the entire grid, not just the local portion
6389 
6390    In Fortran idxm and idxn should be declared as
6391 $     MatStencil idxm(4,m)
6392    and the values inserted using
6393 $    idxm(MatStencil_i,1) = i
6394 $    idxm(MatStencil_j,1) = j
6395 $    idxm(MatStencil_k,1) = k
6396 $    idxm(MatStencil_c,1) = c
6397    etc
6398 
6399    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6400    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6401    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6402    DM_BOUNDARY_PERIODIC boundary type.
6403 
6404    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
6405    a single value per point) you can skip filling those indices.
6406 
6407    Level: intermediate
6408 
6409 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6410           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6411 @*/
6412 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6413 {
6414   PetscInt       dim     = mat->stencil.dim;
6415   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6416   PetscInt       *dims   = mat->stencil.dims+1;
6417   PetscInt       *starts = mat->stencil.starts;
6418   PetscInt       *dxm    = (PetscInt*) rows;
6419   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6420 
6421   PetscFunctionBegin;
6422   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6423   PetscValidType(mat,1);
6424   if (numRows) PetscValidPointer(rows,3);
6425 
6426   PetscCall(PetscMalloc1(numRows, &jdxm));
6427   for (i = 0; i < numRows; ++i) {
6428     /* Skip unused dimensions (they are ordered k, j, i, c) */
6429     for (j = 0; j < 3-sdim; ++j) dxm++;
6430     /* Local index in X dir */
6431     tmp = *dxm++ - starts[0];
6432     /* Loop over remaining dimensions */
6433     for (j = 0; j < dim-1; ++j) {
6434       /* If nonlocal, set index to be negative */
6435       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6436       /* Update local index */
6437       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6438     }
6439     /* Skip component slot if necessary */
6440     if (mat->stencil.noc) dxm++;
6441     /* Local row number */
6442     if (tmp >= 0) {
6443       jdxm[numNewRows++] = tmp;
6444     }
6445   }
6446   PetscCall(MatZeroRowsColumnsLocal(mat,numNewRows,jdxm,diag,x,b));
6447   PetscCall(PetscFree(jdxm));
6448   PetscFunctionReturn(0);
6449 }
6450 
6451 /*@C
6452    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6453    of a set of rows of a matrix; using local numbering of rows.
6454 
6455    Collective on Mat
6456 
6457    Input Parameters:
6458 +  mat - the matrix
6459 .  numRows - the number of rows to remove
6460 .  rows - the local row indices
6461 .  diag - value put in all diagonals of eliminated rows
6462 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6463 -  b - optional vector of right hand side, that will be adjusted by provided solution
6464 
6465    Notes:
6466    Before calling `MatZeroRowsLocal()`, the user must first set the
6467    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6468 
6469    See `MatZeroRows()` for details on how this routine operates.
6470 
6471    Level: intermediate
6472 
6473 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6474           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6475 @*/
6476 PetscErrorCode MatZeroRowsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6477 {
6478   PetscFunctionBegin;
6479   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6480   PetscValidType(mat,1);
6481   if (numRows) PetscValidIntPointer(rows,3);
6482   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6483   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6484   MatCheckPreallocated(mat,1);
6485 
6486   if (mat->ops->zerorowslocal) {
6487     PetscCall((*mat->ops->zerorowslocal)(mat,numRows,rows,diag,x,b));
6488   } else {
6489     IS             is, newis;
6490     const PetscInt *newRows;
6491 
6492     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6493     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6494     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping,is,&newis));
6495     PetscCall(ISGetIndices(newis,&newRows));
6496     PetscCall((*mat->ops->zerorows)(mat,numRows,newRows,diag,x,b));
6497     PetscCall(ISRestoreIndices(newis,&newRows));
6498     PetscCall(ISDestroy(&newis));
6499     PetscCall(ISDestroy(&is));
6500   }
6501   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6502   PetscFunctionReturn(0);
6503 }
6504 
6505 /*@
6506    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6507    of a set of rows of a matrix; using local numbering of rows.
6508 
6509    Collective on Mat
6510 
6511    Input Parameters:
6512 +  mat - the matrix
6513 .  is - index set of rows to remove
6514 .  diag - value put in all diagonals of eliminated rows
6515 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6516 -  b - optional vector of right hand side, that will be adjusted by provided solution
6517 
6518    Notes:
6519    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6520    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`.
6521 
6522    See `MatZeroRows()` for details on how this routine operates.
6523 
6524    Level: intermediate
6525 
6526 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6527           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6528 @*/
6529 PetscErrorCode MatZeroRowsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6530 {
6531   PetscInt       numRows;
6532   const PetscInt *rows;
6533 
6534   PetscFunctionBegin;
6535   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6536   PetscValidType(mat,1);
6537   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6538   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6539   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6540   MatCheckPreallocated(mat,1);
6541 
6542   PetscCall(ISGetLocalSize(is,&numRows));
6543   PetscCall(ISGetIndices(is,&rows));
6544   PetscCall(MatZeroRowsLocal(mat,numRows,rows,diag,x,b));
6545   PetscCall(ISRestoreIndices(is,&rows));
6546   PetscFunctionReturn(0);
6547 }
6548 
6549 /*@
6550    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6551    of a set of rows and columns of a matrix; using local numbering of rows.
6552 
6553    Collective on Mat
6554 
6555    Input Parameters:
6556 +  mat - the matrix
6557 .  numRows - the number of rows to remove
6558 .  rows - the global row indices
6559 .  diag - value put in all diagonals of eliminated rows
6560 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6561 -  b - optional vector of right hand side, that will be adjusted by provided solution
6562 
6563    Notes:
6564    Before calling MatZeroRowsColumnsLocal(), the user must first set the
6565    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6566 
6567    See `MatZeroRowsColumns()` for details on how this routine operates.
6568 
6569    Level: intermediate
6570 
6571 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6572           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6573 @*/
6574 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6575 {
6576   IS             is, newis;
6577   const PetscInt *newRows;
6578 
6579   PetscFunctionBegin;
6580   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6581   PetscValidType(mat,1);
6582   if (numRows) PetscValidIntPointer(rows,3);
6583   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6584   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6585   MatCheckPreallocated(mat,1);
6586 
6587   PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6588   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6589   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping,is,&newis));
6590   PetscCall(ISGetIndices(newis,&newRows));
6591   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,newRows,diag,x,b));
6592   PetscCall(ISRestoreIndices(newis,&newRows));
6593   PetscCall(ISDestroy(&newis));
6594   PetscCall(ISDestroy(&is));
6595   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6596   PetscFunctionReturn(0);
6597 }
6598 
6599 /*@
6600    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6601    of a set of rows and columns of a matrix; using local numbering of rows.
6602 
6603    Collective on Mat
6604 
6605    Input Parameters:
6606 +  mat - the matrix
6607 .  is - index set of rows to remove
6608 .  diag - value put in all diagonals of eliminated rows
6609 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6610 -  b - optional vector of right hand side, that will be adjusted by provided solution
6611 
6612    Notes:
6613    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6614    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`.
6615 
6616    See `MatZeroRowsColumns()` for details on how this routine operates.
6617 
6618    Level: intermediate
6619 
6620 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6621           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6622 @*/
6623 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6624 {
6625   PetscInt       numRows;
6626   const PetscInt *rows;
6627 
6628   PetscFunctionBegin;
6629   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6630   PetscValidType(mat,1);
6631   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6632   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6633   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6634   MatCheckPreallocated(mat,1);
6635 
6636   PetscCall(ISGetLocalSize(is,&numRows));
6637   PetscCall(ISGetIndices(is,&rows));
6638   PetscCall(MatZeroRowsColumnsLocal(mat,numRows,rows,diag,x,b));
6639   PetscCall(ISRestoreIndices(is,&rows));
6640   PetscFunctionReturn(0);
6641 }
6642 
6643 /*@C
6644    MatGetSize - Returns the numbers of rows and columns in a matrix.
6645 
6646    Not Collective
6647 
6648    Input Parameter:
6649 .  mat - the matrix
6650 
6651    Output Parameters:
6652 +  m - the number of global rows
6653 -  n - the number of global columns
6654 
6655    Note: both output parameters can be NULL on input.
6656 
6657    Level: beginner
6658 
6659 .seealso: `MatGetLocalSize()`
6660 @*/
6661 PetscErrorCode MatGetSize(Mat mat,PetscInt *m,PetscInt *n)
6662 {
6663   PetscFunctionBegin;
6664   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6665   if (m) *m = mat->rmap->N;
6666   if (n) *n = mat->cmap->N;
6667   PetscFunctionReturn(0);
6668 }
6669 
6670 /*@C
6671    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6672    of a matrix. For all matrices this is the local size of the left and right vectors as returned by MatCreateVecs().
6673 
6674    Not Collective
6675 
6676    Input Parameter:
6677 .  mat - the matrix
6678 
6679    Output Parameters:
6680 +  m - the number of local rows, use `NULL` to not obtain this value
6681 -  n - the number of local columns, use `NULL` to not obtain this value
6682 
6683    Level: beginner
6684 
6685 .seealso: `MatGetSize()`
6686 @*/
6687 PetscErrorCode MatGetLocalSize(Mat mat,PetscInt *m,PetscInt *n)
6688 {
6689   PetscFunctionBegin;
6690   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6691   if (m) PetscValidIntPointer(m,2);
6692   if (n) PetscValidIntPointer(n,3);
6693   if (m) *m = mat->rmap->n;
6694   if (n) *n = mat->cmap->n;
6695   PetscFunctionReturn(0);
6696 }
6697 
6698 /*@C
6699    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6700    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6701 
6702    Not Collective, unless matrix has not been allocated, then collective on Mat
6703 
6704    Input Parameter:
6705 .  mat - the matrix
6706 
6707    Output Parameters:
6708 +  m - the global index of the first local column, use `NULL` to not obtain this value
6709 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6710 
6711    Level: developer
6712 
6713 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6714 
6715 @*/
6716 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat,PetscInt *m,PetscInt *n)
6717 {
6718   PetscFunctionBegin;
6719   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6720   PetscValidType(mat,1);
6721   if (m) PetscValidIntPointer(m,2);
6722   if (n) PetscValidIntPointer(n,3);
6723   MatCheckPreallocated(mat,1);
6724   if (m) *m = mat->cmap->rstart;
6725   if (n) *n = mat->cmap->rend;
6726   PetscFunctionReturn(0);
6727 }
6728 
6729 /*@C
6730    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6731    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
6732    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6733 
6734    Not Collective
6735 
6736    Input Parameter:
6737 .  mat - the matrix
6738 
6739    Output Parameters:
6740 +  m - the global index of the first local row, use `NULL` to not obtain this value
6741 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6742 
6743    Note:
6744   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6745   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6746   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6747 
6748    Level: beginner
6749 
6750 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6751           `PetscLayout`
6752 
6753 @*/
6754 PetscErrorCode MatGetOwnershipRange(Mat mat,PetscInt *m,PetscInt *n)
6755 {
6756   PetscFunctionBegin;
6757   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6758   PetscValidType(mat,1);
6759   if (m) PetscValidIntPointer(m,2);
6760   if (n) PetscValidIntPointer(n,3);
6761   MatCheckPreallocated(mat,1);
6762   if (m) *m = mat->rmap->rstart;
6763   if (n) *n = mat->rmap->rend;
6764   PetscFunctionReturn(0);
6765 }
6766 
6767 /*@C
6768    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6769    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
6770    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6771 
6772    Not Collective, unless matrix has not been allocated, then collective on Mat
6773 
6774    Input Parameters:
6775 .  mat - the matrix
6776 
6777    Output Parameters:
6778 .  ranges - start of each processors portion plus one more than the total length at the end
6779 
6780    Level: beginner
6781 
6782 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6783 
6784 @*/
6785 PetscErrorCode MatGetOwnershipRanges(Mat mat,const PetscInt **ranges)
6786 {
6787   PetscFunctionBegin;
6788   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6789   PetscValidType(mat,1);
6790   MatCheckPreallocated(mat,1);
6791   PetscCall(PetscLayoutGetRanges(mat->rmap,ranges));
6792   PetscFunctionReturn(0);
6793 }
6794 
6795 /*@C
6796    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6797    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6798 
6799    Not Collective, unless matrix has not been allocated, then collective on Mat
6800 
6801    Input Parameters:
6802 .  mat - the matrix
6803 
6804    Output Parameters:
6805 .  ranges - start of each processors portion plus one more then the total length at the end
6806 
6807    Level: beginner
6808 
6809 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6810 
6811 @*/
6812 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat,const PetscInt **ranges)
6813 {
6814   PetscFunctionBegin;
6815   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6816   PetscValidType(mat,1);
6817   MatCheckPreallocated(mat,1);
6818   PetscCall(PetscLayoutGetRanges(mat->cmap,ranges));
6819   PetscFunctionReturn(0);
6820 }
6821 
6822 /*@C
6823    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6824    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6825    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6826 
6827    Not Collective
6828 
6829    Input Parameter:
6830 .  A - matrix
6831 
6832    Output Parameters:
6833 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6834 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6835 
6836    Level: intermediate
6837 
6838 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6839 @*/
6840 PetscErrorCode MatGetOwnershipIS(Mat A,IS *rows,IS *cols)
6841 {
6842   PetscErrorCode (*f)(Mat,IS*,IS*);
6843 
6844   PetscFunctionBegin;
6845   MatCheckPreallocated(A,1);
6846   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatGetOwnershipIS_C",&f));
6847   if (f) {
6848     PetscCall((*f)(A,rows,cols));
6849   } else {   /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6850     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->rmap->n,A->rmap->rstart,1,rows));
6851     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->cmap->N,0,1,cols));
6852   }
6853   PetscFunctionReturn(0);
6854 }
6855 
6856 /*@C
6857    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix.
6858    Uses levels of fill only, not drop tolerance. Use MatLUFactorNumeric()
6859    to complete the factorization.
6860 
6861    Collective on Mat
6862 
6863    Input Parameters:
6864 +  mat - the matrix
6865 .  row - row permutation
6866 .  column - column permutation
6867 -  info - structure containing
6868 $      levels - number of levels of fill.
6869 $      expected fill - as ratio of original fill.
6870 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6871                 missing diagonal entries)
6872 
6873    Output Parameters:
6874 .  fact - new matrix that has been symbolically factored
6875 
6876    Notes:
6877     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
6878 
6879    Most users should employ the simplified KSP interface for linear solvers
6880    instead of working directly with matrix algebra routines such as this.
6881    See, e.g., KSPCreate().
6882 
6883    Level: developer
6884 
6885 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6886           `MatGetOrdering()`, `MatFactorInfo`
6887 
6888     Note: this uses the definition of level of fill as in Y. Saad, 2003
6889 
6890     Developer Note: fortran interface is not autogenerated as the f90
6891     interface definition cannot be generated correctly [due to MatFactorInfo]
6892 
6893    References:
6894 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6895 @*/
6896 PetscErrorCode MatILUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
6897 {
6898   PetscFunctionBegin;
6899   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6900   PetscValidType(mat,2);
6901   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
6902   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
6903   PetscValidPointer(info,5);
6904   PetscValidPointer(fact,1);
6905   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels of fill negative %" PetscInt_FMT,(PetscInt)info->levels);
6906   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6907   if (!fact->ops->ilufactorsymbolic) {
6908     MatSolverType stype;
6909     PetscCall(MatFactorGetSolverType(fact,&stype));
6910     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ILU using solver type %s",((PetscObject)mat)->type_name,stype);
6911   }
6912   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6913   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6914   MatCheckPreallocated(mat,2);
6915 
6916   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic,mat,row,col,0));
6917   PetscCall((fact->ops->ilufactorsymbolic)(fact,mat,row,col,info));
6918   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic,mat,row,col,0));
6919   PetscFunctionReturn(0);
6920 }
6921 
6922 /*@C
6923    MatICCFactorSymbolic - Performs symbolic incomplete
6924    Cholesky factorization for a symmetric matrix.  Use
6925    MatCholeskyFactorNumeric() to complete the factorization.
6926 
6927    Collective on Mat
6928 
6929    Input Parameters:
6930 +  mat - the matrix
6931 .  perm - row and column permutation
6932 -  info - structure containing
6933 $      levels - number of levels of fill.
6934 $      expected fill - as ratio of original fill.
6935 
6936    Output Parameter:
6937 .  fact - the factored matrix
6938 
6939    Notes:
6940    Most users should employ the KSP interface for linear solvers
6941    instead of working directly with matrix algebra routines such as this.
6942    See, e.g., KSPCreate().
6943 
6944    Level: developer
6945 
6946 .seealso: `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6947 
6948     Note: this uses the definition of level of fill as in Y. Saad, 2003
6949 
6950     Developer Note: fortran interface is not autogenerated as the f90
6951     interface definition cannot be generated correctly [due to MatFactorInfo]
6952 
6953    References:
6954 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6955 @*/
6956 PetscErrorCode MatICCFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
6957 {
6958   PetscFunctionBegin;
6959   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6960   PetscValidType(mat,2);
6961   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
6962   PetscValidPointer(info,4);
6963   PetscValidPointer(fact,1);
6964   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6965   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels negative %" PetscInt_FMT,(PetscInt) info->levels);
6966   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6967   if (!(fact)->ops->iccfactorsymbolic) {
6968     MatSolverType stype;
6969     PetscCall(MatFactorGetSolverType(fact,&stype));
6970     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ICC using solver type %s",((PetscObject)mat)->type_name,stype);
6971   }
6972   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6973   MatCheckPreallocated(mat,2);
6974 
6975   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic,mat,perm,0,0));
6976   PetscCall((fact->ops->iccfactorsymbolic)(fact,mat,perm,info));
6977   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic,mat,perm,0,0));
6978   PetscFunctionReturn(0);
6979 }
6980 
6981 /*@C
6982    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6983    points to an array of valid matrices, they may be reused to store the new
6984    submatrices.
6985 
6986    Collective on Mat
6987 
6988    Input Parameters:
6989 +  mat - the matrix
6990 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6991 .  irow, icol - index sets of rows and columns to extract
6992 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6993 
6994    Output Parameter:
6995 .  submat - the array of submatrices
6996 
6997    Notes:
6998    MatCreateSubMatrices() can extract ONLY sequential submatrices
6999    (from both sequential and parallel matrices). Use MatCreateSubMatrix()
7000    to extract a parallel submatrix.
7001 
7002    Some matrix types place restrictions on the row and column
7003    indices, such as that they be sorted or that they be equal to each other.
7004 
7005    The index sets may not have duplicate entries.
7006 
7007    When extracting submatrices from a parallel matrix, each processor can
7008    form a different submatrix by setting the rows and columns of its
7009    individual index sets according to the local submatrix desired.
7010 
7011    When finished using the submatrices, the user should destroy
7012    them with MatDestroySubMatrices().
7013 
7014    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
7015    original matrix has not changed from that last call to MatCreateSubMatrices().
7016 
7017    This routine creates the matrices in submat; you should NOT create them before
7018    calling it. It also allocates the array of matrix pointers submat.
7019 
7020    For BAIJ matrices the index sets must respect the block structure, that is if they
7021    request one row/column in a block, they must request all rows/columns that are in
7022    that block. For example, if the block size is 2 you cannot request just row 0 and
7023    column 0.
7024 
7025    Fortran Note:
7026    The Fortran interface is slightly different from that given below; it
7027    requires one to pass in  as submat a Mat (integer) array of size at least n+1.
7028 
7029    Level: advanced
7030 
7031 .seealso: `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7032 @*/
7033 PetscErrorCode MatCreateSubMatrices(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     for (i=0; i<n; i++) PetscValidHeaderSpecific(irow[i],IS_CLASSID,3);
7044     PetscValidPointer(icol,4);
7045     for (i=0; i<n; i++) PetscValidHeaderSpecific(icol[i],IS_CLASSID,4);
7046   }
7047   PetscValidPointer(submat,6);
7048   if (n && scall == MAT_REUSE_MATRIX) {
7049     PetscValidPointer(*submat,6);
7050     for (i=0; i<n; i++) PetscValidHeaderSpecific((*submat)[i],MAT_CLASSID,6);
7051   }
7052   PetscCheck(mat->ops->createsubmatrices,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7053   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7054   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7055   MatCheckPreallocated(mat,1);
7056   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
7057   PetscCall((*mat->ops->createsubmatrices)(mat,n,irow,icol,scall,submat));
7058   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
7059   for (i=0; i<n; i++) {
7060     (*submat)[i]->factortype = MAT_FACTOR_NONE;  /* in case in place factorization was previously done on submatrix */
7061     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
7062     if (eq) {
7063       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
7064     }
7065 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
7066     if (mat->boundtocpu && mat->bindingpropagates) {
7067       PetscCall(MatBindToCPU((*submat)[i],PETSC_TRUE));
7068       PetscCall(MatSetBindingPropagates((*submat)[i],PETSC_TRUE));
7069     }
7070 #endif
7071   }
7072   PetscFunctionReturn(0);
7073 }
7074 
7075 /*@C
7076    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of IS that may live on subcomms).
7077 
7078    Collective on Mat
7079 
7080    Input Parameters:
7081 +  mat - the matrix
7082 .  n   - the number of submatrixes to be extracted
7083 .  irow, icol - index sets of rows and columns to extract
7084 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
7085 
7086    Output Parameter:
7087 .  submat - the array of submatrices
7088 
7089    Level: advanced
7090 
7091 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7092 @*/
7093 PetscErrorCode MatCreateSubMatricesMPI(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
7094 {
7095   PetscInt       i;
7096   PetscBool      eq;
7097 
7098   PetscFunctionBegin;
7099   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7100   PetscValidType(mat,1);
7101   if (n) {
7102     PetscValidPointer(irow,3);
7103     PetscValidHeaderSpecific(*irow,IS_CLASSID,3);
7104     PetscValidPointer(icol,4);
7105     PetscValidHeaderSpecific(*icol,IS_CLASSID,4);
7106   }
7107   PetscValidPointer(submat,6);
7108   if (n && scall == MAT_REUSE_MATRIX) {
7109     PetscValidPointer(*submat,6);
7110     PetscValidHeaderSpecific(**submat,MAT_CLASSID,6);
7111   }
7112   PetscCheck(mat->ops->createsubmatricesmpi,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7113   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7114   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7115   MatCheckPreallocated(mat,1);
7116 
7117   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
7118   PetscCall((*mat->ops->createsubmatricesmpi)(mat,n,irow,icol,scall,submat));
7119   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
7120   for (i=0; i<n; i++) {
7121     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
7122     if (eq) {
7123       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
7124     }
7125   }
7126   PetscFunctionReturn(0);
7127 }
7128 
7129 /*@C
7130    MatDestroyMatrices - Destroys an array of matrices.
7131 
7132    Collective on Mat
7133 
7134    Input Parameters:
7135 +  n - the number of local matrices
7136 -  mat - the matrices (note that this is a pointer to the array of matrices)
7137 
7138    Level: advanced
7139 
7140     Notes:
7141     Frees not only the matrices, but also the array that contains the matrices
7142            In Fortran will not free the array.
7143 
7144 .seealso: `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7145 @*/
7146 PetscErrorCode MatDestroyMatrices(PetscInt n,Mat *mat[])
7147 {
7148   PetscInt       i;
7149 
7150   PetscFunctionBegin;
7151   if (!*mat) PetscFunctionReturn(0);
7152   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7153   PetscValidPointer(mat,2);
7154 
7155   for (i=0; i<n; i++) {
7156     PetscCall(MatDestroy(&(*mat)[i]));
7157   }
7158 
7159   /* memory is allocated even if n = 0 */
7160   PetscCall(PetscFree(*mat));
7161   PetscFunctionReturn(0);
7162 }
7163 
7164 /*@C
7165    MatDestroySubMatrices - Destroys a set of matrices obtained with MatCreateSubMatrices().
7166 
7167    Collective on Mat
7168 
7169    Input Parameters:
7170 +  n - the number of local matrices
7171 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7172                        sequence of MatCreateSubMatrices())
7173 
7174    Level: advanced
7175 
7176     Notes:
7177     Frees not only the matrices, but also the array that contains the matrices
7178            In Fortran will not free the array.
7179 
7180 .seealso: `MatCreateSubMatrices()`
7181 @*/
7182 PetscErrorCode MatDestroySubMatrices(PetscInt n,Mat *mat[])
7183 {
7184   Mat            mat0;
7185 
7186   PetscFunctionBegin;
7187   if (!*mat) PetscFunctionReturn(0);
7188   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7189   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7190   PetscValidPointer(mat,2);
7191 
7192   mat0 = (*mat)[0];
7193   if (mat0 && mat0->ops->destroysubmatrices) {
7194     PetscCall((mat0->ops->destroysubmatrices)(n,mat));
7195   } else {
7196     PetscCall(MatDestroyMatrices(n,mat));
7197   }
7198   PetscFunctionReturn(0);
7199 }
7200 
7201 /*@C
7202    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7203 
7204    Collective on Mat
7205 
7206    Input Parameters:
7207 .  mat - the matrix
7208 
7209    Output Parameter:
7210 .  matstruct - the sequential matrix with the nonzero structure of mat
7211 
7212   Level: intermediate
7213 
7214 .seealso: `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7215 @*/
7216 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat,Mat *matstruct)
7217 {
7218   PetscFunctionBegin;
7219   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7220   PetscValidPointer(matstruct,2);
7221 
7222   PetscValidType(mat,1);
7223   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7224   MatCheckPreallocated(mat,1);
7225 
7226   PetscCheck(mat->ops->getseqnonzerostructure,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)mat)->type_name);
7227   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7228   PetscCall((*mat->ops->getseqnonzerostructure)(mat,matstruct));
7229   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7230   PetscFunctionReturn(0);
7231 }
7232 
7233 /*@C
7234    MatDestroySeqNonzeroStructure - Destroys matrix obtained with MatGetSeqNonzeroStructure().
7235 
7236    Collective on Mat
7237 
7238    Input Parameters:
7239 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7240                        sequence of MatGetSequentialNonzeroStructure())
7241 
7242    Level: advanced
7243 
7244     Notes:
7245     Frees not only the matrices, but also the array that contains the matrices
7246 
7247 .seealso: `MatGetSeqNonzeroStructure()`
7248 @*/
7249 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7250 {
7251   PetscFunctionBegin;
7252   PetscValidPointer(mat,1);
7253   PetscCall(MatDestroy(mat));
7254   PetscFunctionReturn(0);
7255 }
7256 
7257 /*@
7258    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7259    replaces the index sets by larger ones that represent submatrices with
7260    additional overlap.
7261 
7262    Collective on Mat
7263 
7264    Input Parameters:
7265 +  mat - the matrix
7266 .  n   - the number of index sets
7267 .  is  - the array of index sets (these index sets will changed during the call)
7268 -  ov  - the additional overlap requested
7269 
7270    Options Database:
7271 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7272 
7273    Level: developer
7274 
7275    Developer Note:
7276    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.
7277 
7278 .seealso: `MatCreateSubMatrices()`
7279 @*/
7280 PetscErrorCode MatIncreaseOverlap(Mat mat,PetscInt n,IS is[],PetscInt ov)
7281 {
7282   PetscInt       i,bs,cbs;
7283 
7284   PetscFunctionBegin;
7285   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7286   PetscValidType(mat,1);
7287   PetscValidLogicalCollectiveInt(mat,n,2);
7288   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7289   if (n) {
7290     PetscValidPointer(is,3);
7291     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i],IS_CLASSID,3);
7292   }
7293   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7294   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7295   MatCheckPreallocated(mat,1);
7296 
7297   if (!ov || !n) PetscFunctionReturn(0);
7298   PetscCheck(mat->ops->increaseoverlap,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7299   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7300   PetscCall((*mat->ops->increaseoverlap)(mat,n,is,ov));
7301   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7302   PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
7303   if (bs == cbs) {
7304     for (i=0; i<n; i++) {
7305       PetscCall(ISSetBlockSize(is[i],bs));
7306     }
7307   }
7308   PetscFunctionReturn(0);
7309 }
7310 
7311 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat,IS*,PetscInt);
7312 
7313 /*@
7314    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7315    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7316    additional overlap.
7317 
7318    Collective on Mat
7319 
7320    Input Parameters:
7321 +  mat - the matrix
7322 .  n   - the number of index sets
7323 .  is  - the array of index sets (these index sets will changed during the call)
7324 -  ov  - the additional overlap requested
7325 
7326    Options Database:
7327 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7328 
7329    Level: developer
7330 
7331 .seealso: `MatCreateSubMatrices()`
7332 @*/
7333 PetscErrorCode MatIncreaseOverlapSplit(Mat mat,PetscInt n,IS is[],PetscInt ov)
7334 {
7335   PetscInt       i;
7336 
7337   PetscFunctionBegin;
7338   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7339   PetscValidType(mat,1);
7340   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7341   if (n) {
7342     PetscValidPointer(is,3);
7343     PetscValidHeaderSpecific(*is,IS_CLASSID,3);
7344   }
7345   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7346   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7347   MatCheckPreallocated(mat,1);
7348   if (!ov) PetscFunctionReturn(0);
7349   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7350   for (i=0; i<n; i++) {
7351     PetscCall(MatIncreaseOverlapSplit_Single(mat,&is[i],ov));
7352   }
7353   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7354   PetscFunctionReturn(0);
7355 }
7356 
7357 /*@
7358    MatGetBlockSize - Returns the matrix block size.
7359 
7360    Not Collective
7361 
7362    Input Parameter:
7363 .  mat - the matrix
7364 
7365    Output Parameter:
7366 .  bs - block size
7367 
7368    Notes:
7369     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7370 
7371    If the block size has not been set yet this routine returns 1.
7372 
7373    Level: intermediate
7374 
7375 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7376 @*/
7377 PetscErrorCode MatGetBlockSize(Mat mat,PetscInt *bs)
7378 {
7379   PetscFunctionBegin;
7380   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7381   PetscValidIntPointer(bs,2);
7382   *bs = PetscAbs(mat->rmap->bs);
7383   PetscFunctionReturn(0);
7384 }
7385 
7386 /*@
7387    MatGetBlockSizes - Returns the matrix block row and column sizes.
7388 
7389    Not Collective
7390 
7391    Input Parameter:
7392 .  mat - the matrix
7393 
7394    Output Parameters:
7395 +  rbs - row block size
7396 -  cbs - column block size
7397 
7398    Notes:
7399     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7400     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7401 
7402    If a block size has not been set yet this routine returns 1.
7403 
7404    Level: intermediate
7405 
7406 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7407 @*/
7408 PetscErrorCode MatGetBlockSizes(Mat mat,PetscInt *rbs, PetscInt *cbs)
7409 {
7410   PetscFunctionBegin;
7411   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7412   if (rbs) PetscValidIntPointer(rbs,2);
7413   if (cbs) PetscValidIntPointer(cbs,3);
7414   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7415   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7416   PetscFunctionReturn(0);
7417 }
7418 
7419 /*@
7420    MatSetBlockSize - Sets the matrix block size.
7421 
7422    Logically Collective on Mat
7423 
7424    Input Parameters:
7425 +  mat - the matrix
7426 -  bs - block size
7427 
7428    Notes:
7429     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7430     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7431 
7432     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block size
7433     is compatible with the matrix local sizes.
7434 
7435    Level: intermediate
7436 
7437 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7438 @*/
7439 PetscErrorCode MatSetBlockSize(Mat mat,PetscInt bs)
7440 {
7441   PetscFunctionBegin;
7442   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7443   PetscValidLogicalCollectiveInt(mat,bs,2);
7444   PetscCall(MatSetBlockSizes(mat,bs,bs));
7445   PetscFunctionReturn(0);
7446 }
7447 
7448 typedef struct {
7449   PetscInt         n;
7450   IS               *is;
7451   Mat              *mat;
7452   PetscObjectState nonzerostate;
7453   Mat              C;
7454 } EnvelopeData;
7455 
7456 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7457 {
7458   for (PetscInt i=0; i<edata->n; i++) {
7459     PetscCall(ISDestroy(&edata->is[i]));
7460   }
7461   PetscCall(PetscFree(edata->is));
7462   PetscCall(PetscFree(edata));
7463   return 0;
7464 }
7465 
7466 /*
7467    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7468          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7469 
7470    Collective on mat
7471 
7472    Input Parameter:
7473 .  mat - the matrix
7474 
7475    Notes:
7476      There can be zeros within the blocks
7477 
7478      The blocks can overlap between processes, including laying on more than two processes
7479 
7480 */
7481 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7482 {
7483   PetscInt                    n,*sizes,*starts,i = 0,env = 0, tbs = 0, lblocks = 0,rstart,II,ln = 0,cnt = 0,cstart,cend;
7484   PetscInt                    *diag,*odiag,sc;
7485   VecScatter                  scatter;
7486   PetscScalar                 *seqv;
7487   const PetscScalar           *parv;
7488   const PetscInt              *ia,*ja;
7489   PetscBool                   set,flag,done;
7490   Mat                         AA = mat,A;
7491   MPI_Comm                    comm;
7492   PetscMPIInt                 rank,size,tag;
7493   MPI_Status                  status;
7494   PetscContainer              container;
7495   EnvelopeData                *edata;
7496   Vec                         seq,par;
7497   IS                          isglobal;
7498 
7499   PetscFunctionBegin;
7500   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7501   PetscCall(MatIsSymmetricKnown(mat,&set,&flag));
7502   if (!set || !flag) {
7503     /* TOO: only needs nonzero structure of transpose */
7504     PetscCall(MatTranspose(mat,MAT_INITIAL_MATRIX,&AA));
7505     PetscCall(MatAXPY(AA,1.0,mat,DIFFERENT_NONZERO_PATTERN));
7506   }
7507   PetscCall(MatAIJGetLocalMat(AA,&A));
7508   PetscCall(MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7509   PetscCheck(done,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unable to get IJ structure from matrix");
7510 
7511   PetscCall(MatGetLocalSize(mat,&n,NULL));
7512   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag));
7513   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
7514   PetscCallMPI(MPI_Comm_size(comm,&size));
7515   PetscCallMPI(MPI_Comm_rank(comm,&rank));
7516 
7517   PetscCall(PetscMalloc2(n,&sizes,n,&starts));
7518 
7519   if (rank > 0) {
7520     PetscCallMPI(MPI_Recv(&env,1,MPIU_INT,rank-1,tag,comm,&status));
7521     PetscCallMPI(MPI_Recv(&tbs,1,MPIU_INT,rank-1,tag,comm,&status));
7522   }
7523   PetscCall(MatGetOwnershipRange(mat,&rstart,NULL));
7524   for (i=0; i<n; i++) {
7525     env = PetscMax(env,ja[ia[i+1]-1]);
7526     II = rstart + i;
7527     if (env == II) {
7528       starts[lblocks]  = tbs;
7529       sizes[lblocks++] = 1 + II - tbs;
7530       tbs = 1 + II;
7531     }
7532   }
7533   if (rank < size-1) {
7534     PetscCallMPI(MPI_Send(&env,1,MPIU_INT,rank+1,tag,comm));
7535     PetscCallMPI(MPI_Send(&tbs,1,MPIU_INT,rank+1,tag,comm));
7536   }
7537 
7538   PetscCall(MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7539   if (!set || !flag) {
7540     PetscCall(MatDestroy(&AA));
7541   }
7542   PetscCall(MatDestroy(&A));
7543 
7544   PetscCall(PetscNew(&edata));
7545   PetscCall(MatGetNonzeroState(mat,&edata->nonzerostate));
7546   edata->n = lblocks;
7547   /* create IS needed for extracting blocks from the original matrix */
7548   PetscCall(PetscMalloc1(lblocks,&edata->is));
7549   for (PetscInt i=0; i<lblocks; i++) {
7550     PetscCall(ISCreateStride(PETSC_COMM_SELF,sizes[i],starts[i],1,&edata->is[i]));
7551   }
7552 
7553   /* Create the resulting inverse matrix structure with preallocation information */
7554   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&edata->C));
7555   PetscCall(MatSetSizes(edata->C,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
7556   PetscCall(MatSetBlockSizesFromMats(edata->C,mat,mat));
7557   PetscCall(MatSetType(edata->C,MATAIJ));
7558 
7559   /* Communicate the start and end of each row, from each block to the correct rank */
7560   /* TODO: Use PetscSF instead of VecScatter */
7561   for (PetscInt i=0; i<lblocks; i++) ln += sizes[i];
7562   PetscCall(VecCreateSeq(PETSC_COMM_SELF,2*ln,&seq));
7563   PetscCall(VecGetArrayWrite(seq,&seqv));
7564   for (PetscInt i=0; i<lblocks; i++) {
7565     for (PetscInt j=0; j<sizes[i]; j++) {
7566       seqv[cnt]   = starts[i];
7567       seqv[cnt+1] = starts[i] + sizes[i];
7568       cnt += 2;
7569     }
7570   }
7571   PetscCall(VecRestoreArrayWrite(seq,&seqv));
7572   PetscCallMPI(MPI_Scan(&cnt,&sc,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
7573   sc -= cnt;
7574   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat),2*mat->rmap->n,2*mat->rmap->N,&par));
7575   PetscCall(ISCreateStride(PETSC_COMM_SELF,cnt,sc,1,&isglobal));
7576   PetscCall(VecScatterCreate(seq, NULL  ,par, isglobal,&scatter));
7577   PetscCall(ISDestroy(&isglobal));
7578   PetscCall(VecScatterBegin(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7579   PetscCall(VecScatterEnd(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7580   PetscCall(VecScatterDestroy(&scatter));
7581   PetscCall(VecDestroy(&seq));
7582   PetscCall(MatGetOwnershipRangeColumn(mat,&cstart,&cend));
7583   PetscCall(PetscMalloc2(mat->rmap->n,&diag,mat->rmap->n,&odiag));
7584   PetscCall(VecGetArrayRead(par,&parv));
7585   cnt = 0;
7586   PetscCall(MatGetSize(mat,NULL,&n));
7587   for (PetscInt i=0; i<mat->rmap->n; i++) {
7588     PetscInt start,end,d = 0,od = 0;
7589 
7590     start = (PetscInt)PetscRealPart(parv[cnt]);
7591     end   = (PetscInt)PetscRealPart(parv[cnt+1]);
7592     cnt  += 2;
7593 
7594     if (start < cstart) {od += cstart - start + n - cend; d += cend - cstart;}
7595     else if (start < cend) {od += n - cend; d += cend - start;}
7596     else od += n - start;
7597     if (end <= cstart) {od -= cstart - end + n - cend; d -= cend - cstart;}
7598     else if (end < cend) {od -= n - cend; d -= cend - end;}
7599     else od -= n - end;
7600 
7601     odiag[i] = od;
7602     diag[i]  = d;
7603   }
7604   PetscCall(VecRestoreArrayRead(par,&parv));
7605   PetscCall(VecDestroy(&par));
7606   PetscCall(MatXAIJSetPreallocation(edata->C,mat->rmap->bs,diag,odiag,NULL,NULL));
7607   PetscCall(PetscFree2(diag,odiag));
7608   PetscCall(PetscFree2(sizes,starts));
7609 
7610   PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&container));
7611   PetscCall(PetscContainerSetPointer(container,edata));
7612   PetscCall(PetscContainerSetUserDestroy(container,(PetscErrorCode (*)(void*))EnvelopeDataDestroy));
7613   PetscCall(PetscObjectCompose((PetscObject)mat,"EnvelopeData",(PetscObject)container));
7614   PetscCall(PetscObjectDereference((PetscObject)container));
7615   PetscFunctionReturn(0);
7616 }
7617 
7618 /*@
7619   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7620 
7621   Collective on Mat
7622 
7623   Input Parameters:
7624 . A - the matrix
7625 
7626   Output Parameters:
7627 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7628 
7629   Notes:
7630      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7631 
7632   Level: advanced
7633 
7634 .seealso: MatInvertBlockDiagonal(), MatComputeBlockDiagonal()
7635 @*/
7636 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A,MatReuse reuse, Mat *C)
7637 {
7638   PetscContainer    container;
7639   EnvelopeData      *edata;
7640   PetscObjectState  nonzerostate;
7641 
7642   PetscFunctionBegin;
7643   PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7644   if (!container) {
7645     PetscCall(MatComputeVariableBlockEnvelope(A));
7646     PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7647   }
7648   PetscCall(PetscContainerGetPointer(container,(void**)&edata));
7649   PetscCall(MatGetNonzeroState(A,&nonzerostate));
7650   PetscCheck(nonzerostate <= edata->nonzerostate,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Cannot handle changes to matrix nonzero structure");
7651   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"C matrix must be the same as previously output");
7652 
7653   PetscCall(MatCreateSubMatrices(A,edata->n,edata->is,edata->is,MAT_INITIAL_MATRIX,&edata->mat));
7654   *C   = edata->C;
7655 
7656   for (PetscInt i=0; i<edata->n; i++) {
7657     Mat         D;
7658     PetscScalar *dvalues;
7659 
7660     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE,MAT_INITIAL_MATRIX,&D));
7661     PetscCall(MatSetOption(*C,MAT_ROW_ORIENTED,PETSC_FALSE));
7662     PetscCall(MatSeqDenseInvert(D));
7663     PetscCall(MatDenseGetArray(D,&dvalues));
7664     PetscCall(MatSetValuesIS(*C,edata->is[i],edata->is[i],dvalues,INSERT_VALUES));
7665     PetscCall(MatDestroy(&D));
7666   }
7667   PetscCall(MatDestroySubMatrices(edata->n,&edata->mat));
7668   PetscCall(MatAssemblyBegin(*C,MAT_FINAL_ASSEMBLY));
7669   PetscCall(MatAssemblyEnd(*C,MAT_FINAL_ASSEMBLY));
7670   PetscFunctionReturn(0);
7671 }
7672 
7673 /*@
7674    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7675 
7676    Logically Collective on Mat
7677 
7678    Input Parameters:
7679 +  mat - the matrix
7680 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7681 -  bsizes - the block sizes
7682 
7683    Notes:
7684     Currently used by PCVPBJACOBI for AIJ matrices
7685 
7686     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.
7687 
7688    Level: intermediate
7689 
7690 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7691 @*/
7692 PetscErrorCode MatSetVariableBlockSizes(Mat mat,PetscInt nblocks,PetscInt *bsizes)
7693 {
7694   PetscInt       i,ncnt = 0, nlocal;
7695 
7696   PetscFunctionBegin;
7697   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7698   PetscCheck(nblocks >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Number of local blocks must be great than or equal to zero");
7699   PetscCall(MatGetLocalSize(mat,&nlocal,NULL));
7700   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
7701   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);
7702   PetscCall(PetscFree(mat->bsizes));
7703   mat->nblocks = nblocks;
7704   PetscCall(PetscMalloc1(nblocks,&mat->bsizes));
7705   PetscCall(PetscArraycpy(mat->bsizes,bsizes,nblocks));
7706   PetscFunctionReturn(0);
7707 }
7708 
7709 /*@C
7710    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7711 
7712    Logically Collective on Mat
7713 
7714    Input Parameter:
7715 .  mat - the matrix
7716 
7717    Output Parameters:
7718 +  nblocks - the number of blocks on this process
7719 -  bsizes - the block sizes
7720 
7721    Notes: Currently not supported from Fortran
7722 
7723    Level: intermediate
7724 
7725 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7726 @*/
7727 PetscErrorCode MatGetVariableBlockSizes(Mat mat,PetscInt *nblocks,const PetscInt **bsizes)
7728 {
7729   PetscFunctionBegin;
7730   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7731   *nblocks = mat->nblocks;
7732   *bsizes  = mat->bsizes;
7733   PetscFunctionReturn(0);
7734 }
7735 
7736 /*@
7737    MatSetBlockSizes - Sets the matrix block row and column sizes.
7738 
7739    Logically Collective on Mat
7740 
7741    Input Parameters:
7742 +  mat - the matrix
7743 .  rbs - row block size
7744 -  cbs - column block size
7745 
7746    Notes:
7747     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7748     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7749     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7750 
7751     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block sizes
7752     are compatible with the matrix local sizes.
7753 
7754     The row and column block size determine the blocksize of the "row" and "column" vectors returned by MatCreateVecs().
7755 
7756    Level: intermediate
7757 
7758 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7759 @*/
7760 PetscErrorCode MatSetBlockSizes(Mat mat,PetscInt rbs,PetscInt cbs)
7761 {
7762   PetscFunctionBegin;
7763   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7764   PetscValidLogicalCollectiveInt(mat,rbs,2);
7765   PetscValidLogicalCollectiveInt(mat,cbs,3);
7766   if (mat->ops->setblocksizes) PetscCall((*mat->ops->setblocksizes)(mat,rbs,cbs));
7767   if (mat->rmap->refcnt) {
7768     ISLocalToGlobalMapping l2g = NULL;
7769     PetscLayout            nmap = NULL;
7770 
7771     PetscCall(PetscLayoutDuplicate(mat->rmap,&nmap));
7772     if (mat->rmap->mapping) {
7773       PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping,&l2g));
7774     }
7775     PetscCall(PetscLayoutDestroy(&mat->rmap));
7776     mat->rmap = nmap;
7777     mat->rmap->mapping = l2g;
7778   }
7779   if (mat->cmap->refcnt) {
7780     ISLocalToGlobalMapping l2g = NULL;
7781     PetscLayout            nmap = NULL;
7782 
7783     PetscCall(PetscLayoutDuplicate(mat->cmap,&nmap));
7784     if (mat->cmap->mapping) {
7785       PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping,&l2g));
7786     }
7787     PetscCall(PetscLayoutDestroy(&mat->cmap));
7788     mat->cmap = nmap;
7789     mat->cmap->mapping = l2g;
7790   }
7791   PetscCall(PetscLayoutSetBlockSize(mat->rmap,rbs));
7792   PetscCall(PetscLayoutSetBlockSize(mat->cmap,cbs));
7793   PetscFunctionReturn(0);
7794 }
7795 
7796 /*@
7797    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7798 
7799    Logically Collective on Mat
7800 
7801    Input Parameters:
7802 +  mat - the matrix
7803 .  fromRow - matrix from which to copy row block size
7804 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7805 
7806    Level: developer
7807 
7808 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7809 @*/
7810 PetscErrorCode MatSetBlockSizesFromMats(Mat mat,Mat fromRow,Mat fromCol)
7811 {
7812   PetscFunctionBegin;
7813   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7814   PetscValidHeaderSpecific(fromRow,MAT_CLASSID,2);
7815   PetscValidHeaderSpecific(fromCol,MAT_CLASSID,3);
7816   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap,fromRow->rmap->bs));
7817   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap,fromCol->cmap->bs));
7818   PetscFunctionReturn(0);
7819 }
7820 
7821 /*@
7822    MatResidual - Default routine to calculate the residual.
7823 
7824    Collective on Mat
7825 
7826    Input Parameters:
7827 +  mat - the matrix
7828 .  b   - the right-hand-side
7829 -  x   - the approximate solution
7830 
7831    Output Parameter:
7832 .  r - location to store the residual
7833 
7834    Level: developer
7835 
7836 .seealso: `PCMGSetResidual()`
7837 @*/
7838 PetscErrorCode MatResidual(Mat mat,Vec b,Vec x,Vec r)
7839 {
7840   PetscFunctionBegin;
7841   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7842   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
7843   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
7844   PetscValidHeaderSpecific(r,VEC_CLASSID,4);
7845   PetscValidType(mat,1);
7846   MatCheckPreallocated(mat,1);
7847   PetscCall(PetscLogEventBegin(MAT_Residual,mat,0,0,0));
7848   if (!mat->ops->residual) {
7849     PetscCall(MatMult(mat,x,r));
7850     PetscCall(VecAYPX(r,-1.0,b));
7851   } else {
7852     PetscCall((*mat->ops->residual)(mat,b,x,r));
7853   }
7854   PetscCall(PetscLogEventEnd(MAT_Residual,mat,0,0,0));
7855   PetscFunctionReturn(0);
7856 }
7857 
7858 /*@C
7859     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7860 
7861    Collective on Mat
7862 
7863     Input Parameters:
7864 +   mat - the matrix
7865 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7866 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be   symmetrized
7867 -   inodecompressed - PETSC_TRUE or PETSC_FALSE  indicating if the nonzero structure of the
7868                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7869                  always used.
7870 
7871     Output Parameters:
7872 +   n - number of local rows in the (possibly compressed) matrix
7873 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7874 .   ja - the column indices
7875 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7876            are responsible for handling the case when done == PETSC_FALSE and ia and ja are not set
7877 
7878     Level: developer
7879 
7880     Notes:
7881     You CANNOT change any of the ia[] or ja[] values.
7882 
7883     Use MatRestoreRowIJ() when you are finished accessing the ia[] and ja[] values.
7884 
7885     Fortran Notes:
7886     In Fortran use
7887 $
7888 $      PetscInt ia(1), ja(1)
7889 $      PetscOffset iia, jja
7890 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7891 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7892 
7893      or
7894 $
7895 $    PetscInt, pointer :: ia(:),ja(:)
7896 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7897 $    ! Access the ith and jth entries via ia(i) and ja(j)
7898 
7899 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7900 @*/
7901 PetscErrorCode MatGetRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7902 {
7903   PetscFunctionBegin;
7904   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7905   PetscValidType(mat,1);
7906   if (n) PetscValidIntPointer(n,5);
7907   if (ia) PetscValidPointer(ia,6);
7908   if (ja) PetscValidPointer(ja,7);
7909   if (done) PetscValidBoolPointer(done,8);
7910   MatCheckPreallocated(mat,1);
7911   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7912   else {
7913     if (done) *done = PETSC_TRUE;
7914     PetscCall(PetscLogEventBegin(MAT_GetRowIJ,mat,0,0,0));
7915     PetscCall((*mat->ops->getrowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7916     PetscCall(PetscLogEventEnd(MAT_GetRowIJ,mat,0,0,0));
7917   }
7918   PetscFunctionReturn(0);
7919 }
7920 
7921 /*@C
7922     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7923 
7924     Collective on Mat
7925 
7926     Input Parameters:
7927 +   mat - the matrix
7928 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7929 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7930                 symmetrized
7931 .   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7932                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7933                  always used.
7934 .   n - number of columns in the (possibly compressed) matrix
7935 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7936 -   ja - the row indices
7937 
7938     Output Parameters:
7939 .   done - PETSC_TRUE or PETSC_FALSE, indicating whether the values have been returned
7940 
7941     Level: developer
7942 
7943 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7944 @*/
7945 PetscErrorCode MatGetColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7946 {
7947   PetscFunctionBegin;
7948   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7949   PetscValidType(mat,1);
7950   PetscValidIntPointer(n,5);
7951   if (ia) PetscValidPointer(ia,6);
7952   if (ja) PetscValidPointer(ja,7);
7953   PetscValidBoolPointer(done,8);
7954   MatCheckPreallocated(mat,1);
7955   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7956   else {
7957     *done = PETSC_TRUE;
7958     PetscCall((*mat->ops->getcolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7959   }
7960   PetscFunctionReturn(0);
7961 }
7962 
7963 /*@C
7964     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with
7965     MatGetRowIJ().
7966 
7967     Collective on Mat
7968 
7969     Input Parameters:
7970 +   mat - the matrix
7971 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7972 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7973                 symmetrized
7974 .   inodecompressed -  PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7975                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7976                  always used.
7977 .   n - size of (possibly compressed) matrix
7978 .   ia - the row pointers
7979 -   ja - the column indices
7980 
7981     Output Parameters:
7982 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7983 
7984     Note:
7985     This routine zeros out n, ia, and ja. This is to prevent accidental
7986     us of the array after it has been restored. If you pass NULL, it will
7987     not zero the pointers.  Use of ia or ja after MatRestoreRowIJ() is invalid.
7988 
7989     Level: developer
7990 
7991 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7992 @*/
7993 PetscErrorCode MatRestoreRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7994 {
7995   PetscFunctionBegin;
7996   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7997   PetscValidType(mat,1);
7998   if (ia) PetscValidPointer(ia,6);
7999   if (ja) PetscValidPointer(ja,7);
8000   if (done) PetscValidBoolPointer(done,8);
8001   MatCheckPreallocated(mat,1);
8002 
8003   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8004   else {
8005     if (done) *done = PETSC_TRUE;
8006     PetscCall((*mat->ops->restorerowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
8007     if (n)  *n = 0;
8008     if (ia) *ia = NULL;
8009     if (ja) *ja = NULL;
8010   }
8011   PetscFunctionReturn(0);
8012 }
8013 
8014 /*@C
8015     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with
8016     MatGetColumnIJ().
8017 
8018     Collective on Mat
8019 
8020     Input Parameters:
8021 +   mat - the matrix
8022 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8023 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
8024                 symmetrized
8025 -   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
8026                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
8027                  always used.
8028 
8029     Output Parameters:
8030 +   n - size of (possibly compressed) matrix
8031 .   ia - the column pointers
8032 .   ja - the row indices
8033 -   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
8034 
8035     Level: developer
8036 
8037 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8038 @*/
8039 PetscErrorCode MatRestoreColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
8040 {
8041   PetscFunctionBegin;
8042   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8043   PetscValidType(mat,1);
8044   if (ia) PetscValidPointer(ia,6);
8045   if (ja) PetscValidPointer(ja,7);
8046   PetscValidBoolPointer(done,8);
8047   MatCheckPreallocated(mat,1);
8048 
8049   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8050   else {
8051     *done = PETSC_TRUE;
8052     PetscCall((*mat->ops->restorecolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
8053     if (n)  *n = 0;
8054     if (ia) *ia = NULL;
8055     if (ja) *ja = NULL;
8056   }
8057   PetscFunctionReturn(0);
8058 }
8059 
8060 /*@C
8061     MatColoringPatch -Used inside matrix coloring routines that
8062     use MatGetRowIJ() and/or MatGetColumnIJ().
8063 
8064     Collective on Mat
8065 
8066     Input Parameters:
8067 +   mat - the matrix
8068 .   ncolors - max color value
8069 .   n   - number of entries in colorarray
8070 -   colorarray - array indicating color for each column
8071 
8072     Output Parameters:
8073 .   iscoloring - coloring generated using colorarray information
8074 
8075     Level: developer
8076 
8077 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
8078 
8079 @*/
8080 PetscErrorCode MatColoringPatch(Mat mat,PetscInt ncolors,PetscInt n,ISColoringValue colorarray[],ISColoring *iscoloring)
8081 {
8082   PetscFunctionBegin;
8083   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8084   PetscValidType(mat,1);
8085   PetscValidIntPointer(colorarray,4);
8086   PetscValidPointer(iscoloring,5);
8087   MatCheckPreallocated(mat,1);
8088 
8089   if (!mat->ops->coloringpatch) {
8090     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat),ncolors,n,colorarray,PETSC_OWN_POINTER,iscoloring));
8091   } else {
8092     PetscCall((*mat->ops->coloringpatch)(mat,ncolors,n,colorarray,iscoloring));
8093   }
8094   PetscFunctionReturn(0);
8095 }
8096 
8097 /*@
8098    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8099 
8100    Logically Collective on Mat
8101 
8102    Input Parameter:
8103 .  mat - the factored matrix to be reset
8104 
8105    Notes:
8106    This routine should be used only with factored matrices formed by in-place
8107    factorization via ILU(0) (or by in-place LU factorization for the MATSEQDENSE
8108    format).  This option can save memory, for example, when solving nonlinear
8109    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8110    ILU(0) preconditioner.
8111 
8112    Note that one can specify in-place ILU(0) factorization by calling
8113 .vb
8114      PCType(pc,PCILU);
8115      PCFactorSeUseInPlace(pc);
8116 .ve
8117    or by using the options -pc_type ilu -pc_factor_in_place
8118 
8119    In-place factorization ILU(0) can also be used as a local
8120    solver for the blocks within the block Jacobi or additive Schwarz
8121    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8122    for details on setting local solver options.
8123 
8124    Most users should employ the simplified KSP interface for linear solvers
8125    instead of working directly with matrix algebra routines such as this.
8126    See, e.g., KSPCreate().
8127 
8128    Level: developer
8129 
8130 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8131 
8132 @*/
8133 PetscErrorCode MatSetUnfactored(Mat mat)
8134 {
8135   PetscFunctionBegin;
8136   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8137   PetscValidType(mat,1);
8138   MatCheckPreallocated(mat,1);
8139   mat->factortype = MAT_FACTOR_NONE;
8140   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
8141   PetscCall((*mat->ops->setunfactored)(mat));
8142   PetscFunctionReturn(0);
8143 }
8144 
8145 /*MC
8146     MatDenseGetArrayF90 - Accesses a matrix array from Fortran90.
8147 
8148     Synopsis:
8149     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8150 
8151     Not collective
8152 
8153     Input Parameter:
8154 .   x - matrix
8155 
8156     Output Parameters:
8157 +   xx_v - the Fortran90 pointer to the array
8158 -   ierr - error code
8159 
8160     Example of Usage:
8161 .vb
8162       PetscScalar, pointer xx_v(:,:)
8163       ....
8164       call MatDenseGetArrayF90(x,xx_v,ierr)
8165       a = xx_v(3)
8166       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8167 .ve
8168 
8169     Level: advanced
8170 
8171 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8172 
8173 M*/
8174 
8175 /*MC
8176     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8177     accessed with MatDenseGetArrayF90().
8178 
8179     Synopsis:
8180     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8181 
8182     Not collective
8183 
8184     Input Parameters:
8185 +   x - matrix
8186 -   xx_v - the Fortran90 pointer to the array
8187 
8188     Output Parameter:
8189 .   ierr - error code
8190 
8191     Example of Usage:
8192 .vb
8193        PetscScalar, pointer xx_v(:,:)
8194        ....
8195        call MatDenseGetArrayF90(x,xx_v,ierr)
8196        a = xx_v(3)
8197        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8198 .ve
8199 
8200     Level: advanced
8201 
8202 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8203 
8204 M*/
8205 
8206 /*MC
8207     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran90.
8208 
8209     Synopsis:
8210     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8211 
8212     Not collective
8213 
8214     Input Parameter:
8215 .   x - matrix
8216 
8217     Output Parameters:
8218 +   xx_v - the Fortran90 pointer to the array
8219 -   ierr - error code
8220 
8221     Example of Usage:
8222 .vb
8223       PetscScalar, pointer xx_v(:)
8224       ....
8225       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8226       a = xx_v(3)
8227       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8228 .ve
8229 
8230     Level: advanced
8231 
8232 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8233 
8234 M*/
8235 
8236 /*MC
8237     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8238     accessed with MatSeqAIJGetArrayF90().
8239 
8240     Synopsis:
8241     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8242 
8243     Not collective
8244 
8245     Input Parameters:
8246 +   x - matrix
8247 -   xx_v - the Fortran90 pointer to the array
8248 
8249     Output Parameter:
8250 .   ierr - error code
8251 
8252     Example of Usage:
8253 .vb
8254        PetscScalar, pointer xx_v(:)
8255        ....
8256        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8257        a = xx_v(3)
8258        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8259 .ve
8260 
8261     Level: advanced
8262 
8263 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8264 
8265 M*/
8266 
8267 /*@
8268     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8269                       as the original matrix.
8270 
8271     Collective on Mat
8272 
8273     Input Parameters:
8274 +   mat - the original matrix
8275 .   isrow - parallel IS containing the rows this processor should obtain
8276 .   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.
8277 -   cll - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
8278 
8279     Output Parameter:
8280 .   newmat - the new submatrix, of the same type as the old
8281 
8282     Level: advanced
8283 
8284     Notes:
8285     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8286 
8287     Some matrix types place restrictions on the row and column indices, such
8288     as that they be sorted or that they be equal to each other.
8289 
8290     The index sets may not have duplicate entries.
8291 
8292       The first time this is called you should use a cll of MAT_INITIAL_MATRIX,
8293    the MatCreateSubMatrix() routine will create the newmat for you. Any additional calls
8294    to this routine with a mat of the same nonzero structure and with a call of MAT_REUSE_MATRIX
8295    will reuse the matrix generated the first time.  You should call MatDestroy() on newmat when
8296    you are finished using it.
8297 
8298     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8299     the input matrix.
8300 
8301     If iscol is NULL then all columns are obtained (not supported in Fortran).
8302 
8303    Example usage:
8304    Consider the following 8x8 matrix with 34 non-zero values, that is
8305    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8306    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8307    as follows:
8308 
8309 .vb
8310             1  2  0  |  0  3  0  |  0  4
8311     Proc0   0  5  6  |  7  0  0  |  8  0
8312             9  0 10  | 11  0  0  | 12  0
8313     -------------------------------------
8314            13  0 14  | 15 16 17  |  0  0
8315     Proc1   0 18  0  | 19 20 21  |  0  0
8316             0  0  0  | 22 23  0  | 24  0
8317     -------------------------------------
8318     Proc2  25 26 27  |  0  0 28  | 29  0
8319            30  0  0  | 31 32 33  |  0 34
8320 .ve
8321 
8322     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8323 
8324 .vb
8325             2  0  |  0  3  0  |  0
8326     Proc0   5  6  |  7  0  0  |  8
8327     -------------------------------
8328     Proc1  18  0  | 19 20 21  |  0
8329     -------------------------------
8330     Proc2  26 27  |  0  0 28  | 29
8331             0  0  | 31 32 33  |  0
8332 .ve
8333 
8334 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8335 @*/
8336 PetscErrorCode MatCreateSubMatrix(Mat mat,IS isrow,IS iscol,MatReuse cll,Mat *newmat)
8337 {
8338   PetscMPIInt    size;
8339   Mat            *local;
8340   IS             iscoltmp;
8341   PetscBool      flg;
8342 
8343   PetscFunctionBegin;
8344   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8345   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
8346   if (iscol) PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
8347   PetscValidPointer(newmat,5);
8348   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat,MAT_CLASSID,5);
8349   PetscValidType(mat,1);
8350   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8351   PetscCheck(cll != MAT_IGNORE_MATRIX,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Cannot use MAT_IGNORE_MATRIX");
8352 
8353   MatCheckPreallocated(mat,1);
8354   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8355 
8356   if (!iscol || isrow == iscol) {
8357     PetscBool   stride;
8358     PetscMPIInt grabentirematrix = 0,grab;
8359     PetscCall(PetscObjectTypeCompare((PetscObject)isrow,ISSTRIDE,&stride));
8360     if (stride) {
8361       PetscInt first,step,n,rstart,rend;
8362       PetscCall(ISStrideGetInfo(isrow,&first,&step));
8363       if (step == 1) {
8364         PetscCall(MatGetOwnershipRange(mat,&rstart,&rend));
8365         if (rstart == first) {
8366           PetscCall(ISGetLocalSize(isrow,&n));
8367           if (n == rend-rstart) {
8368             grabentirematrix = 1;
8369           }
8370         }
8371       }
8372     }
8373     PetscCall(MPIU_Allreduce(&grabentirematrix,&grab,1,MPI_INT,MPI_MIN,PetscObjectComm((PetscObject)mat)));
8374     if (grab) {
8375       PetscCall(PetscInfo(mat,"Getting entire matrix as submatrix\n"));
8376       if (cll == MAT_INITIAL_MATRIX) {
8377         *newmat = mat;
8378         PetscCall(PetscObjectReference((PetscObject)mat));
8379       }
8380       PetscFunctionReturn(0);
8381     }
8382   }
8383 
8384   if (!iscol) {
8385     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat),mat->cmap->n,mat->cmap->rstart,1,&iscoltmp));
8386   } else {
8387     iscoltmp = iscol;
8388   }
8389 
8390   /* if original matrix is on just one processor then use submatrix generated */
8391   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8392     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_REUSE_MATRIX,&newmat));
8393     goto setproperties;
8394   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8395     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_INITIAL_MATRIX,&local));
8396     *newmat = *local;
8397     PetscCall(PetscFree(local));
8398     goto setproperties;
8399   } else if (!mat->ops->createsubmatrix) {
8400     /* Create a new matrix type that implements the operation using the full matrix */
8401     PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8402     switch (cll) {
8403     case MAT_INITIAL_MATRIX:
8404       PetscCall(MatCreateSubMatrixVirtual(mat,isrow,iscoltmp,newmat));
8405       break;
8406     case MAT_REUSE_MATRIX:
8407       PetscCall(MatSubMatrixVirtualUpdate(*newmat,mat,isrow,iscoltmp));
8408       break;
8409     default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8410     }
8411     PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8412     goto setproperties;
8413   }
8414 
8415   PetscCheck(mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8416   PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8417   PetscCall((*mat->ops->createsubmatrix)(mat,isrow,iscoltmp,cll,newmat));
8418   PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8419 
8420 setproperties:
8421   PetscCall(ISEqualUnsorted(isrow,iscoltmp,&flg));
8422   if (flg) PetscCall(MatPropagateSymmetryOptions(mat,*newmat));
8423   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8424   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8425   PetscFunctionReturn(0);
8426 }
8427 
8428 /*@
8429    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8430 
8431    Not Collective
8432 
8433    Input Parameters:
8434 +  A - the matrix we wish to propagate options from
8435 -  B - the matrix we wish to propagate options to
8436 
8437    Level: beginner
8438 
8439    Notes:
8440    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8441 
8442 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8443 @*/
8444 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8445 {
8446   PetscFunctionBegin;
8447   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8448   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
8449   B->symmetry_eternal            = A->symmetry_eternal;
8450   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8451   B->symmetric                   = A->symmetric;
8452   B->structurally_symmetric      = A->structurally_symmetric;
8453   B->spd                         = A->spd;
8454   B->hermitian                   = A->hermitian;
8455   PetscFunctionReturn(0);
8456 }
8457 
8458 /*@
8459    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8460    used during the assembly process to store values that belong to
8461    other processors.
8462 
8463    Not Collective
8464 
8465    Input Parameters:
8466 +  mat   - the matrix
8467 .  size  - the initial size of the stash.
8468 -  bsize - the initial size of the block-stash(if used).
8469 
8470    Options Database Keys:
8471 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8472 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8473 
8474    Level: intermediate
8475 
8476    Notes:
8477      The block-stash is used for values set with MatSetValuesBlocked() while
8478      the stash is used for values set with MatSetValues()
8479 
8480      Run with the option -info and look for output of the form
8481      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8482      to determine the appropriate value, MM, to use for size and
8483      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8484      to determine the value, BMM to use for bsize
8485 
8486 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8487 
8488 @*/
8489 PetscErrorCode MatStashSetInitialSize(Mat mat,PetscInt size, PetscInt bsize)
8490 {
8491   PetscFunctionBegin;
8492   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8493   PetscValidType(mat,1);
8494   PetscCall(MatStashSetInitialSize_Private(&mat->stash,size));
8495   PetscCall(MatStashSetInitialSize_Private(&mat->bstash,bsize));
8496   PetscFunctionReturn(0);
8497 }
8498 
8499 /*@
8500    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8501      the matrix
8502 
8503    Neighbor-wise Collective on Mat
8504 
8505    Input Parameters:
8506 +  mat   - the matrix
8507 .  x,y - the vectors
8508 -  w - where the result is stored
8509 
8510    Level: intermediate
8511 
8512    Notes:
8513     w may be the same vector as y.
8514 
8515     This allows one to use either the restriction or interpolation (its transpose)
8516     matrix to do the interpolation
8517 
8518 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8519 
8520 @*/
8521 PetscErrorCode MatInterpolateAdd(Mat A,Vec x,Vec y,Vec w)
8522 {
8523   PetscInt       M,N,Ny;
8524 
8525   PetscFunctionBegin;
8526   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8527   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8528   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8529   PetscValidHeaderSpecific(w,VEC_CLASSID,4);
8530   PetscCall(MatGetSize(A,&M,&N));
8531   PetscCall(VecGetSize(y,&Ny));
8532   if (M == Ny) {
8533     PetscCall(MatMultAdd(A,x,y,w));
8534   } else {
8535     PetscCall(MatMultTransposeAdd(A,x,y,w));
8536   }
8537   PetscFunctionReturn(0);
8538 }
8539 
8540 /*@
8541    MatInterpolate - y = A*x or A'*x depending on the shape of
8542      the matrix
8543 
8544    Neighbor-wise Collective on Mat
8545 
8546    Input Parameters:
8547 +  mat   - the matrix
8548 -  x,y - the vectors
8549 
8550    Level: intermediate
8551 
8552    Notes:
8553     This allows one to use either the restriction or interpolation (its transpose)
8554     matrix to do the interpolation
8555 
8556 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8557 
8558 @*/
8559 PetscErrorCode MatInterpolate(Mat A,Vec x,Vec y)
8560 {
8561   PetscInt       M,N,Ny;
8562 
8563   PetscFunctionBegin;
8564   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8565   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8566   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8567   PetscCall(MatGetSize(A,&M,&N));
8568   PetscCall(VecGetSize(y,&Ny));
8569   if (M == Ny) {
8570     PetscCall(MatMult(A,x,y));
8571   } else {
8572     PetscCall(MatMultTranspose(A,x,y));
8573   }
8574   PetscFunctionReturn(0);
8575 }
8576 
8577 /*@
8578    MatRestrict - y = A*x or A'*x
8579 
8580    Neighbor-wise Collective on Mat
8581 
8582    Input Parameters:
8583 +  mat   - the matrix
8584 -  x,y - the vectors
8585 
8586    Level: intermediate
8587 
8588    Notes:
8589     This allows one to use either the restriction or interpolation (its transpose)
8590     matrix to do the restriction
8591 
8592 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`
8593 
8594 @*/
8595 PetscErrorCode MatRestrict(Mat A,Vec x,Vec y)
8596 {
8597   PetscInt       M,N,Ny;
8598 
8599   PetscFunctionBegin;
8600   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8601   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8602   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8603   PetscCall(MatGetSize(A,&M,&N));
8604   PetscCall(VecGetSize(y,&Ny));
8605   if (M == Ny) {
8606     PetscCall(MatMult(A,x,y));
8607   } else {
8608     PetscCall(MatMultTranspose(A,x,y));
8609   }
8610   PetscFunctionReturn(0);
8611 }
8612 
8613 /*@
8614    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8615 
8616    Neighbor-wise Collective on Mat
8617 
8618    Input Parameters:
8619 +  mat   - the matrix
8620 -  w, x - the input dense matrices
8621 
8622    Output Parameters:
8623 .  y - the output dense matrix
8624 
8625    Level: intermediate
8626 
8627    Notes:
8628     This allows one to use either the restriction or interpolation (its transpose)
8629     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8630     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8631 
8632 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`
8633 
8634 @*/
8635 PetscErrorCode MatMatInterpolateAdd(Mat A,Mat x,Mat w,Mat *y)
8636 {
8637   PetscInt       M,N,Mx,Nx,Mo,My = 0,Ny = 0;
8638   PetscBool      trans = PETSC_TRUE;
8639   MatReuse       reuse = MAT_INITIAL_MATRIX;
8640 
8641   PetscFunctionBegin;
8642   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8643   PetscValidHeaderSpecific(x,MAT_CLASSID,2);
8644   PetscValidType(x,2);
8645   if (w) PetscValidHeaderSpecific(w,MAT_CLASSID,3);
8646   if (*y) PetscValidHeaderSpecific(*y,MAT_CLASSID,4);
8647   PetscCall(MatGetSize(A,&M,&N));
8648   PetscCall(MatGetSize(x,&Mx,&Nx));
8649   if (N == Mx) trans = PETSC_FALSE;
8650   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);
8651   Mo = trans ? N : M;
8652   if (*y) {
8653     PetscCall(MatGetSize(*y,&My,&Ny));
8654     if (Mo == My && Nx == Ny) { reuse = MAT_REUSE_MATRIX; }
8655     else {
8656       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);
8657       PetscCall(MatDestroy(y));
8658     }
8659   }
8660 
8661   if (w && *y == w) { /* this is to minimize changes in PCMG */
8662     PetscBool flg;
8663 
8664     PetscCall(PetscObjectQuery((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject*)&w));
8665     if (w) {
8666       PetscInt My,Ny,Mw,Nw;
8667 
8668       PetscCall(PetscObjectTypeCompare((PetscObject)*y,((PetscObject)w)->type_name,&flg));
8669       PetscCall(MatGetSize(*y,&My,&Ny));
8670       PetscCall(MatGetSize(w,&Mw,&Nw));
8671       if (!flg || My != Mw || Ny != Nw) w = NULL;
8672     }
8673     if (!w) {
8674       PetscCall(MatDuplicate(*y,MAT_COPY_VALUES,&w));
8675       PetscCall(PetscObjectCompose((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject)w));
8676       PetscCall(PetscLogObjectParent((PetscObject)*y,(PetscObject)w));
8677       PetscCall(PetscObjectDereference((PetscObject)w));
8678     } else {
8679       PetscCall(MatCopy(*y,w,UNKNOWN_NONZERO_PATTERN));
8680     }
8681   }
8682   if (!trans) {
8683     PetscCall(MatMatMult(A,x,reuse,PETSC_DEFAULT,y));
8684   } else {
8685     PetscCall(MatTransposeMatMult(A,x,reuse,PETSC_DEFAULT,y));
8686   }
8687   if (w) PetscCall(MatAXPY(*y,1.0,w,UNKNOWN_NONZERO_PATTERN));
8688   PetscFunctionReturn(0);
8689 }
8690 
8691 /*@
8692    MatMatInterpolate - Y = A*X or A'*X
8693 
8694    Neighbor-wise Collective on Mat
8695 
8696    Input Parameters:
8697 +  mat   - the matrix
8698 -  x - the input dense matrix
8699 
8700    Output Parameters:
8701 .  y - the output dense matrix
8702 
8703    Level: intermediate
8704 
8705    Notes:
8706     This allows one to use either the restriction or interpolation (its transpose)
8707     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8708     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8709 
8710 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`
8711 
8712 @*/
8713 PetscErrorCode MatMatInterpolate(Mat A,Mat x,Mat *y)
8714 {
8715   PetscFunctionBegin;
8716   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8717   PetscFunctionReturn(0);
8718 }
8719 
8720 /*@
8721    MatMatRestrict - Y = A*X or A'*X
8722 
8723    Neighbor-wise Collective on Mat
8724 
8725    Input Parameters:
8726 +  mat   - the matrix
8727 -  x - the input dense matrix
8728 
8729    Output Parameters:
8730 .  y - the output dense matrix
8731 
8732    Level: intermediate
8733 
8734    Notes:
8735     This allows one to use either the restriction or interpolation (its transpose)
8736     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8737     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8738 
8739 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`
8740 @*/
8741 PetscErrorCode MatMatRestrict(Mat A,Mat x,Mat *y)
8742 {
8743   PetscFunctionBegin;
8744   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8745   PetscFunctionReturn(0);
8746 }
8747 
8748 /*@
8749    MatGetNullSpace - retrieves the null space of a matrix.
8750 
8751    Logically Collective on Mat
8752 
8753    Input Parameters:
8754 +  mat - the matrix
8755 -  nullsp - the null space object
8756 
8757    Level: developer
8758 
8759 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`
8760 @*/
8761 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8762 {
8763   PetscFunctionBegin;
8764   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8765   PetscValidPointer(nullsp,2);
8766   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8767   PetscFunctionReturn(0);
8768 }
8769 
8770 /*@
8771    MatSetNullSpace - attaches a null space to a matrix.
8772 
8773    Logically Collective on Mat
8774 
8775    Input Parameters:
8776 +  mat - the matrix
8777 -  nullsp - the null space object
8778 
8779    Level: advanced
8780 
8781    Notes:
8782       This null space is used by the KSP linear solvers to solve singular systems.
8783 
8784       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
8785 
8786       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
8787       to zero but the linear system will still be solved in a least squares sense.
8788 
8789       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8790    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).
8791    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
8792    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
8793    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).
8794    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8795 
8796     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
8797     routine also automatically calls MatSetTransposeNullSpace().
8798 
8799     The user should call `MatNullSpaceDestroy()`.
8800 
8801 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8802           `KSPSetPCSide()`
8803 @*/
8804 PetscErrorCode MatSetNullSpace(Mat mat,MatNullSpace nullsp)
8805 {
8806   PetscFunctionBegin;
8807   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8808   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8809   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8810   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8811   mat->nullsp = nullsp;
8812   if (mat->symmetric == PETSC_BOOL3_TRUE) {
8813     PetscCall(MatSetTransposeNullSpace(mat,nullsp));
8814   }
8815   PetscFunctionReturn(0);
8816 }
8817 
8818 /*@
8819    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8820 
8821    Logically Collective on Mat
8822 
8823    Input Parameters:
8824 +  mat - the matrix
8825 -  nullsp - the null space object
8826 
8827    Level: developer
8828 
8829 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8830 @*/
8831 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8832 {
8833   PetscFunctionBegin;
8834   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8835   PetscValidType(mat,1);
8836   PetscValidPointer(nullsp,2);
8837   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8838   PetscFunctionReturn(0);
8839 }
8840 
8841 /*@
8842    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8843 
8844    Logically Collective on Mat
8845 
8846    Input Parameters:
8847 +  mat - the matrix
8848 -  nullsp - the null space object
8849 
8850    Level: advanced
8851 
8852    Notes:
8853       This allows solving singular linear systems defined by the transpose of the matrix using KSP solvers with left preconditioning.
8854 
8855       See MatSetNullSpace()
8856 
8857 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8858 @*/
8859 PetscErrorCode MatSetTransposeNullSpace(Mat mat,MatNullSpace nullsp)
8860 {
8861   PetscFunctionBegin;
8862   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8863   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8864   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8865   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8866   mat->transnullsp = nullsp;
8867   PetscFunctionReturn(0);
8868 }
8869 
8870 /*@
8871    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8872         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8873 
8874    Logically Collective on Mat
8875 
8876    Input Parameters:
8877 +  mat - the matrix
8878 -  nullsp - the null space object
8879 
8880    Level: advanced
8881 
8882    Notes:
8883       Overwrites any previous near null space that may have been attached
8884 
8885       You can remove the null space by calling this routine with an nullsp of NULL
8886 
8887 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8888 @*/
8889 PetscErrorCode MatSetNearNullSpace(Mat mat,MatNullSpace nullsp)
8890 {
8891   PetscFunctionBegin;
8892   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8893   PetscValidType(mat,1);
8894   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8895   MatCheckPreallocated(mat,1);
8896   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8897   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8898   mat->nearnullsp = nullsp;
8899   PetscFunctionReturn(0);
8900 }
8901 
8902 /*@
8903    MatGetNearNullSpace - Get null space attached with MatSetNearNullSpace()
8904 
8905    Not Collective
8906 
8907    Input Parameter:
8908 .  mat - the matrix
8909 
8910    Output Parameter:
8911 .  nullsp - the null space object, NULL if not set
8912 
8913    Level: developer
8914 
8915 .seealso: `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8916 @*/
8917 PetscErrorCode MatGetNearNullSpace(Mat mat,MatNullSpace *nullsp)
8918 {
8919   PetscFunctionBegin;
8920   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8921   PetscValidType(mat,1);
8922   PetscValidPointer(nullsp,2);
8923   MatCheckPreallocated(mat,1);
8924   *nullsp = mat->nearnullsp;
8925   PetscFunctionReturn(0);
8926 }
8927 
8928 /*@C
8929    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8930 
8931    Collective on Mat
8932 
8933    Input Parameters:
8934 +  mat - the matrix
8935 .  row - row/column permutation
8936 .  fill - expected fill factor >= 1.0
8937 -  level - level of fill, for ICC(k)
8938 
8939    Notes:
8940    Probably really in-place only when level of fill is zero, otherwise allocates
8941    new space to store factored matrix and deletes previous memory.
8942 
8943    Most users should employ the simplified KSP interface for linear solvers
8944    instead of working directly with matrix algebra routines such as this.
8945    See, e.g., KSPCreate().
8946 
8947    Level: developer
8948 
8949 .seealso: `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8950 
8951     Developer Note: fortran interface is not autogenerated as the f90
8952     interface definition cannot be generated correctly [due to MatFactorInfo]
8953 
8954 @*/
8955 PetscErrorCode MatICCFactor(Mat mat,IS row,const MatFactorInfo *info)
8956 {
8957   PetscFunctionBegin;
8958   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8959   PetscValidType(mat,1);
8960   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
8961   PetscValidPointer(info,3);
8962   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
8963   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
8964   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8965   PetscCheck(mat->ops->iccfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8966   MatCheckPreallocated(mat,1);
8967   PetscCall((*mat->ops->iccfactor)(mat,row,info));
8968   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8969   PetscFunctionReturn(0);
8970 }
8971 
8972 /*@
8973    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8974          ghosted ones.
8975 
8976    Not Collective
8977 
8978    Input Parameters:
8979 +  mat - the matrix
8980 -  diag - the diagonal values, including ghost ones
8981 
8982    Level: developer
8983 
8984    Notes:
8985     Works only for MPIAIJ and MPIBAIJ matrices
8986 
8987 .seealso: `MatDiagonalScale()`
8988 @*/
8989 PetscErrorCode MatDiagonalScaleLocal(Mat mat,Vec diag)
8990 {
8991   PetscMPIInt    size;
8992 
8993   PetscFunctionBegin;
8994   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8995   PetscValidHeaderSpecific(diag,VEC_CLASSID,2);
8996   PetscValidType(mat,1);
8997 
8998   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be already assembled");
8999   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
9000   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
9001   if (size == 1) {
9002     PetscInt n,m;
9003     PetscCall(VecGetSize(diag,&n));
9004     PetscCall(MatGetSize(mat,NULL,&m));
9005     if (m == n) {
9006       PetscCall(MatDiagonalScale(mat,NULL,diag));
9007     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only supported for sequential matrices when no ghost points/periodic conditions");
9008   } else {
9009     PetscUseMethod(mat,"MatDiagonalScaleLocal_C",(Mat,Vec),(mat,diag));
9010   }
9011   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
9012   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9013   PetscFunctionReturn(0);
9014 }
9015 
9016 /*@
9017    MatGetInertia - Gets the inertia from a factored matrix
9018 
9019    Collective on Mat
9020 
9021    Input Parameter:
9022 .  mat - the matrix
9023 
9024    Output Parameters:
9025 +   nneg - number of negative eigenvalues
9026 .   nzero - number of zero eigenvalues
9027 -   npos - number of positive eigenvalues
9028 
9029    Level: advanced
9030 
9031    Notes:
9032     Matrix must have been factored by MatCholeskyFactor()
9033 
9034 @*/
9035 PetscErrorCode MatGetInertia(Mat mat,PetscInt *nneg,PetscInt *nzero,PetscInt *npos)
9036 {
9037   PetscFunctionBegin;
9038   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9039   PetscValidType(mat,1);
9040   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
9041   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Numeric factor mat is not assembled");
9042   PetscCheck(mat->ops->getinertia,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
9043   PetscCall((*mat->ops->getinertia)(mat,nneg,nzero,npos));
9044   PetscFunctionReturn(0);
9045 }
9046 
9047 /* ----------------------------------------------------------------*/
9048 /*@C
9049    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9050 
9051    Neighbor-wise Collective on Mats
9052 
9053    Input Parameters:
9054 +  mat - the factored matrix
9055 -  b - the right-hand-side vectors
9056 
9057    Output Parameter:
9058 .  x - the result vectors
9059 
9060    Notes:
9061    The vectors b and x cannot be the same.  I.e., one cannot
9062    call MatSolves(A,x,x).
9063 
9064    Notes:
9065    Most users should employ the simplified KSP interface for linear solvers
9066    instead of working directly with matrix algebra routines such as this.
9067    See, e.g., KSPCreate().
9068 
9069    Level: developer
9070 
9071 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9072 @*/
9073 PetscErrorCode MatSolves(Mat mat,Vecs b,Vecs x)
9074 {
9075   PetscFunctionBegin;
9076   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9077   PetscValidType(mat,1);
9078   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
9079   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
9080   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
9081 
9082   PetscCheck(mat->ops->solves,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
9083   MatCheckPreallocated(mat,1);
9084   PetscCall(PetscLogEventBegin(MAT_Solves,mat,0,0,0));
9085   PetscCall((*mat->ops->solves)(mat,b,x));
9086   PetscCall(PetscLogEventEnd(MAT_Solves,mat,0,0,0));
9087   PetscFunctionReturn(0);
9088 }
9089 
9090 /*@
9091    MatIsSymmetric - Test whether a matrix is symmetric
9092 
9093    Collective on Mat
9094 
9095    Input Parameters:
9096 +  A - the matrix to test
9097 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9098 
9099    Output Parameters:
9100 .  flg - the result
9101 
9102    Notes:
9103     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
9104 
9105     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9106 
9107    Level: intermediate
9108 
9109 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`
9110 @*/
9111 PetscErrorCode MatIsSymmetric(Mat A,PetscReal tol,PetscBool *flg)
9112 {
9113   PetscFunctionBegin;
9114   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9115   PetscValidBoolPointer(flg,3);
9116 
9117   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9118   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9119   else {
9120     if (!A->ops->issymmetric) {
9121       MatType mattype;
9122       PetscCall(MatGetType(A,&mattype));
9123       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for symmetric",mattype);
9124     }
9125     PetscCall((*A->ops->issymmetric)(A,tol,flg));
9126     if (!tol) PetscCall(MatSetOption(A,MAT_SYMMETRIC,*flg));
9127   }
9128   PetscFunctionReturn(0);
9129 }
9130 
9131 /*@
9132    MatIsHermitian - Test whether a matrix is Hermitian
9133 
9134    Collective on Mat
9135 
9136    Input Parameters:
9137 +  A - the matrix to test
9138 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9139 
9140    Output Parameters:
9141 .  flg - the result
9142 
9143    Level: intermediate
9144 
9145    Notes:
9146     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
9147 
9148     If the matrix does not yet know if it is hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9149 
9150 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9151           `MatIsSymmetricKnown()`, `MatIsSymmetric()`
9152 @*/
9153 PetscErrorCode MatIsHermitian(Mat A,PetscReal tol,PetscBool *flg)
9154 {
9155   PetscFunctionBegin;
9156   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9157   PetscValidBoolPointer(flg,3);
9158 
9159   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9160   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9161   else {
9162     if (!A->ops->ishermitian) {
9163       MatType mattype;
9164       PetscCall(MatGetType(A,&mattype));
9165       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for hermitian",mattype);
9166     }
9167     PetscCall((*A->ops->ishermitian)(A,tol,flg));
9168     if (!tol) PetscCall(MatSetOption(A,MAT_HERMITIAN,*flg));
9169   }
9170   PetscFunctionReturn(0);
9171 }
9172 
9173 /*@
9174    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9175 
9176    Not Collective
9177 
9178    Input Parameter:
9179 .  A - the matrix to check
9180 
9181    Output Parameters:
9182 +  set - PETSC_TRUE if the matrix knows its symmetry state (this tells you if the next flag is valid)
9183 -  flg - the result (only valid if set is PETSC_TRUE)
9184 
9185    Level: advanced
9186 
9187    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsSymmetric()
9188          if you want it explicitly checked
9189 
9190 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9191 @*/
9192 PetscErrorCode MatIsSymmetricKnown(Mat A,PetscBool *set,PetscBool *flg)
9193 {
9194   PetscFunctionBegin;
9195   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9196   PetscValidBoolPointer(set,2);
9197   PetscValidBoolPointer(flg,3);
9198   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9199     *set = PETSC_TRUE;
9200     *flg = PetscBool3ToBool(A->symmetric);
9201   } else {
9202     *set = PETSC_FALSE;
9203   }
9204   PetscFunctionReturn(0);
9205 }
9206 
9207 /*@
9208    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9209 
9210    Not Collective
9211 
9212    Input Parameter:
9213 .  A - the matrix to check
9214 
9215    Output Parameters:
9216 +  set - PETSC_TRUE if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9217 -  flg - the result (only valid if set is PETSC_TRUE)
9218 
9219    Level: advanced
9220 
9221    Note:
9222    Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE).
9223 
9224 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9225 @*/
9226 PetscErrorCode MatIsSPDKnown(Mat A,PetscBool *set,PetscBool *flg)
9227 {
9228   PetscFunctionBegin;
9229   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9230   PetscValidBoolPointer(set,2);
9231   PetscValidBoolPointer(flg,3);
9232   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9233     *set = PETSC_TRUE;
9234     *flg = PetscBool3ToBool(A->spd);
9235   } else {
9236     *set = PETSC_FALSE;
9237   }
9238   PetscFunctionReturn(0);
9239 }
9240 
9241 /*@
9242    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9243 
9244    Not Collective
9245 
9246    Input Parameter:
9247 .  A - the matrix to check
9248 
9249    Output Parameters:
9250 +  set - PETSC_TRUE if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9251 -  flg - the result (only valid if set is PETSC_TRUE)
9252 
9253    Level: advanced
9254 
9255    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsHermitian()
9256          if you want it explicitly checked
9257 
9258 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9259 @*/
9260 PetscErrorCode MatIsHermitianKnown(Mat A,PetscBool *set,PetscBool *flg)
9261 {
9262   PetscFunctionBegin;
9263   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9264   PetscValidBoolPointer(set,2);
9265   PetscValidBoolPointer(flg,3);
9266   if (A->hermitian  != PETSC_BOOL3_UNKNOWN) {
9267     *set = PETSC_TRUE;
9268     *flg = PetscBool3ToBool(A->hermitian);
9269   } else {
9270     *set = PETSC_FALSE;
9271   }
9272   PetscFunctionReturn(0);
9273 }
9274 
9275 /*@
9276    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9277 
9278    Collective on Mat
9279 
9280    Input Parameter:
9281 .  A - the matrix to test
9282 
9283    Output Parameters:
9284 .  flg - the result
9285 
9286    Notes:
9287       If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9288 
9289    Level: intermediate
9290 
9291 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9292 @*/
9293 PetscErrorCode MatIsStructurallySymmetric(Mat A,PetscBool *flg)
9294 {
9295   PetscFunctionBegin;
9296   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9297   PetscValidBoolPointer(flg,2);
9298   if (A->structurally_symmetric  != PETSC_BOOL3_UNKNOWN) {
9299     *flg = PetscBool3ToBool(A->structurally_symmetric);
9300   } else {
9301     PetscCheck(A->ops->isstructurallysymmetric,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Matrix of type %s does not support checking for structural symmetry",((PetscObject)A)->type_name);
9302     PetscCall((*A->ops->isstructurallysymmetric)(A,flg));
9303     PetscCall(MatSetOption(A,MAT_STRUCTURALLY_SYMMETRIC,*flg));
9304   }
9305   PetscFunctionReturn(0);
9306 }
9307 
9308 /*@
9309    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9310 
9311    Not Collective
9312 
9313    Input Parameter:
9314 .  A - the matrix to check
9315 
9316    Output Parameters:
9317 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9318 -  flg - the result (only valid if set is PETSC_TRUE)
9319 
9320    Level: advanced
9321 
9322 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9323 @*/
9324 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A,PetscBool *set,PetscBool *flg)
9325 {
9326   PetscFunctionBegin;
9327   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9328   PetscValidBoolPointer(set,2);
9329   PetscValidBoolPointer(flg,3);
9330   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9331     *set = PETSC_TRUE;
9332     *flg = PetscBool3ToBool(A->structurally_symmetric);
9333   } else {
9334     *set = PETSC_FALSE;
9335   }
9336   PetscFunctionReturn(0);
9337 }
9338 
9339 /*@
9340    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9341        to be communicated to other processors during the MatAssemblyBegin/End() process
9342 
9343     Not collective
9344 
9345    Input Parameter:
9346 .   vec - the vector
9347 
9348    Output Parameters:
9349 +   nstash   - the size of the stash
9350 .   reallocs - the number of additional mallocs incurred.
9351 .   bnstash   - the size of the block stash
9352 -   breallocs - the number of additional mallocs incurred.in the block stash
9353 
9354    Level: advanced
9355 
9356 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9357 
9358 @*/
9359 PetscErrorCode MatStashGetInfo(Mat mat,PetscInt *nstash,PetscInt *reallocs,PetscInt *bnstash,PetscInt *breallocs)
9360 {
9361   PetscFunctionBegin;
9362   PetscCall(MatStashGetInfo_Private(&mat->stash,nstash,reallocs));
9363   PetscCall(MatStashGetInfo_Private(&mat->bstash,bnstash,breallocs));
9364   PetscFunctionReturn(0);
9365 }
9366 
9367 /*@C
9368    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9369      parallel layout
9370 
9371    Collective on Mat
9372 
9373    Input Parameter:
9374 .  mat - the matrix
9375 
9376    Output Parameters:
9377 +   right - (optional) vector that the matrix can be multiplied against
9378 -   left - (optional) vector that the matrix vector product can be stored in
9379 
9380    Notes:
9381     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().
9382 
9383   Notes:
9384     These are new vectors which are not owned by the Mat, they should be destroyed in VecDestroy() when no longer needed
9385 
9386   Level: advanced
9387 
9388 .seealso: `MatCreate()`, `VecDestroy()`
9389 @*/
9390 PetscErrorCode MatCreateVecs(Mat mat,Vec *right,Vec *left)
9391 {
9392   PetscFunctionBegin;
9393   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9394   PetscValidType(mat,1);
9395   if (mat->ops->getvecs) {
9396     PetscCall((*mat->ops->getvecs)(mat,right,left));
9397   } else {
9398     PetscInt rbs,cbs;
9399     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
9400     if (right) {
9401       PetscCheck(mat->cmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for columns not yet setup");
9402       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),right));
9403       PetscCall(VecSetSizes(*right,mat->cmap->n,PETSC_DETERMINE));
9404       PetscCall(VecSetBlockSize(*right,cbs));
9405       PetscCall(VecSetType(*right,mat->defaultvectype));
9406 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9407       if (mat->boundtocpu && mat->bindingpropagates) {
9408         PetscCall(VecSetBindingPropagates(*right,PETSC_TRUE));
9409         PetscCall(VecBindToCPU(*right,PETSC_TRUE));
9410       }
9411 #endif
9412       PetscCall(PetscLayoutReference(mat->cmap,&(*right)->map));
9413     }
9414     if (left) {
9415       PetscCheck(mat->rmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for rows not yet setup");
9416       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),left));
9417       PetscCall(VecSetSizes(*left,mat->rmap->n,PETSC_DETERMINE));
9418       PetscCall(VecSetBlockSize(*left,rbs));
9419       PetscCall(VecSetType(*left,mat->defaultvectype));
9420 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9421       if (mat->boundtocpu && mat->bindingpropagates) {
9422         PetscCall(VecSetBindingPropagates(*left,PETSC_TRUE));
9423         PetscCall(VecBindToCPU(*left,PETSC_TRUE));
9424       }
9425 #endif
9426       PetscCall(PetscLayoutReference(mat->rmap,&(*left)->map));
9427     }
9428   }
9429   PetscFunctionReturn(0);
9430 }
9431 
9432 /*@C
9433    MatFactorInfoInitialize - Initializes a MatFactorInfo data structure
9434      with default values.
9435 
9436    Not Collective
9437 
9438    Input Parameters:
9439 .    info - the MatFactorInfo data structure
9440 
9441    Notes:
9442     The solvers are generally used through the KSP and PC objects, for example
9443           PCLU, PCILU, PCCHOLESKY, PCICC
9444 
9445    Level: developer
9446 
9447 .seealso: `MatFactorInfo`
9448 
9449     Developer Note: fortran interface is not autogenerated as the f90
9450     interface definition cannot be generated correctly [due to MatFactorInfo]
9451 
9452 @*/
9453 
9454 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9455 {
9456   PetscFunctionBegin;
9457   PetscCall(PetscMemzero(info,sizeof(MatFactorInfo)));
9458   PetscFunctionReturn(0);
9459 }
9460 
9461 /*@
9462    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9463 
9464    Collective on Mat
9465 
9466    Input Parameters:
9467 +  mat - the factored matrix
9468 -  is - the index set defining the Schur indices (0-based)
9469 
9470    Notes:
9471     Call MatFactorSolveSchurComplement() or MatFactorSolveSchurComplementTranspose() after this call to solve a Schur complement system.
9472 
9473    You can call MatFactorGetSchurComplement() or MatFactorCreateSchurComplement() after this call.
9474 
9475    Level: developer
9476 
9477 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9478           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`
9479 
9480 @*/
9481 PetscErrorCode MatFactorSetSchurIS(Mat mat,IS is)
9482 {
9483   PetscErrorCode (*f)(Mat,IS);
9484 
9485   PetscFunctionBegin;
9486   PetscValidType(mat,1);
9487   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9488   PetscValidType(is,2);
9489   PetscValidHeaderSpecific(is,IS_CLASSID,2);
9490   PetscCheckSameComm(mat,1,is,2);
9491   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
9492   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorSetSchurIS_C",&f));
9493   PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9494   PetscCall(MatDestroy(&mat->schur));
9495   PetscCall((*f)(mat,is));
9496   PetscCheck(mat->schur,PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Schur complement has not been created");
9497   PetscFunctionReturn(0);
9498 }
9499 
9500 /*@
9501   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9502 
9503    Logically Collective on Mat
9504 
9505    Input Parameters:
9506 +  F - the factored matrix obtained by calling MatGetFactor() from PETSc-MUMPS interface
9507 .  S - location where to return the Schur complement, can be NULL
9508 -  status - the status of the Schur complement matrix, can be NULL
9509 
9510    Notes:
9511    You must call MatFactorSetSchurIS() before calling this routine.
9512 
9513    The routine provides a copy of the Schur matrix stored within the solver data structures.
9514    The caller must destroy the object when it is no longer needed.
9515    If MatFactorInvertSchurComplement() has been called, the routine gets back the inverse.
9516 
9517    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)
9518 
9519    Developer Notes:
9520     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9521    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9522 
9523    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9524 
9525    Level: advanced
9526 
9527    References:
9528 
9529 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`
9530 @*/
9531 PetscErrorCode MatFactorCreateSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9532 {
9533   PetscFunctionBegin;
9534   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9535   if (S) PetscValidPointer(S,2);
9536   if (status) PetscValidPointer(status,3);
9537   if (S) {
9538     PetscErrorCode (*f)(Mat,Mat*);
9539 
9540     PetscCall(PetscObjectQueryFunction((PetscObject)F,"MatFactorCreateSchurComplement_C",&f));
9541     if (f) {
9542       PetscCall((*f)(F,S));
9543     } else {
9544       PetscCall(MatDuplicate(F->schur,MAT_COPY_VALUES,S));
9545     }
9546   }
9547   if (status) *status = F->schur_status;
9548   PetscFunctionReturn(0);
9549 }
9550 
9551 /*@
9552   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9553 
9554    Logically Collective on Mat
9555 
9556    Input Parameters:
9557 +  F - the factored matrix obtained by calling MatGetFactor()
9558 .  *S - location where to return the Schur complement, can be NULL
9559 -  status - the status of the Schur complement matrix, can be NULL
9560 
9561    Notes:
9562    You must call MatFactorSetSchurIS() before calling this routine.
9563 
9564    Schur complement mode is currently implemented for sequential matrices.
9565    The routine returns a the Schur Complement stored within the data strutures of the solver.
9566    If MatFactorInvertSchurComplement() has previously been called, the returned matrix is actually the inverse of the Schur complement.
9567    The returned matrix should not be destroyed; the caller should call MatFactorRestoreSchurComplement() when the object is no longer needed.
9568 
9569    Use MatFactorCreateSchurComplement() to create a copy of the Schur complement matrix that is within a factored matrix
9570 
9571    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9572 
9573    Level: advanced
9574 
9575    References:
9576 
9577 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9578 @*/
9579 PetscErrorCode MatFactorGetSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9580 {
9581   PetscFunctionBegin;
9582   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9583   if (S) PetscValidPointer(S,2);
9584   if (status) PetscValidPointer(status,3);
9585   if (S) *S = F->schur;
9586   if (status) *status = F->schur_status;
9587   PetscFunctionReturn(0);
9588 }
9589 
9590 /*@
9591   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to MatFactorGetSchurComplement
9592 
9593    Logically Collective on Mat
9594 
9595    Input Parameters:
9596 +  F - the factored matrix obtained by calling MatGetFactor()
9597 .  *S - location where the Schur complement is stored
9598 -  status - the status of the Schur complement matrix (see MatFactorSchurStatus)
9599 
9600    Notes:
9601 
9602    Level: advanced
9603 
9604    References:
9605 
9606 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9607 @*/
9608 PetscErrorCode MatFactorRestoreSchurComplement(Mat F,Mat* S,MatFactorSchurStatus status)
9609 {
9610   PetscFunctionBegin;
9611   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9612   if (S) {
9613     PetscValidHeaderSpecific(*S,MAT_CLASSID,2);
9614     *S = NULL;
9615   }
9616   F->schur_status = status;
9617   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9618   PetscFunctionReturn(0);
9619 }
9620 
9621 /*@
9622   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9623 
9624    Logically Collective on Mat
9625 
9626    Input Parameters:
9627 +  F - the factored matrix obtained by calling MatGetFactor()
9628 .  rhs - location where the right hand side of the Schur complement system is stored
9629 -  sol - location where the solution of the Schur complement system has to be returned
9630 
9631    Notes:
9632    The sizes of the vectors should match the size of the Schur complement
9633 
9634    Must be called after MatFactorSetSchurIS()
9635 
9636    Level: advanced
9637 
9638    References:
9639 
9640 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9641 @*/
9642 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9643 {
9644   PetscFunctionBegin;
9645   PetscValidType(F,1);
9646   PetscValidType(rhs,2);
9647   PetscValidType(sol,3);
9648   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9649   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9650   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9651   PetscCheckSameComm(F,1,rhs,2);
9652   PetscCheckSameComm(F,1,sol,3);
9653   PetscCall(MatFactorFactorizeSchurComplement(F));
9654   switch (F->schur_status) {
9655   case MAT_FACTOR_SCHUR_FACTORED:
9656     PetscCall(MatSolveTranspose(F->schur,rhs,sol));
9657     break;
9658   case MAT_FACTOR_SCHUR_INVERTED:
9659     PetscCall(MatMultTranspose(F->schur,rhs,sol));
9660     break;
9661   default:
9662     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9663   }
9664   PetscFunctionReturn(0);
9665 }
9666 
9667 /*@
9668   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9669 
9670    Logically Collective on Mat
9671 
9672    Input Parameters:
9673 +  F - the factored matrix obtained by calling MatGetFactor()
9674 .  rhs - location where the right hand side of the Schur complement system is stored
9675 -  sol - location where the solution of the Schur complement system has to be returned
9676 
9677    Notes:
9678    The sizes of the vectors should match the size of the Schur complement
9679 
9680    Must be called after MatFactorSetSchurIS()
9681 
9682    Level: advanced
9683 
9684    References:
9685 
9686 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9687 @*/
9688 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9689 {
9690   PetscFunctionBegin;
9691   PetscValidType(F,1);
9692   PetscValidType(rhs,2);
9693   PetscValidType(sol,3);
9694   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9695   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9696   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9697   PetscCheckSameComm(F,1,rhs,2);
9698   PetscCheckSameComm(F,1,sol,3);
9699   PetscCall(MatFactorFactorizeSchurComplement(F));
9700   switch (F->schur_status) {
9701   case MAT_FACTOR_SCHUR_FACTORED:
9702     PetscCall(MatSolve(F->schur,rhs,sol));
9703     break;
9704   case MAT_FACTOR_SCHUR_INVERTED:
9705     PetscCall(MatMult(F->schur,rhs,sol));
9706     break;
9707   default:
9708     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9709   }
9710   PetscFunctionReturn(0);
9711 }
9712 
9713 /*@
9714   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9715 
9716    Logically Collective on Mat
9717 
9718    Input Parameters:
9719 .  F - the factored matrix obtained by calling MatGetFactor()
9720 
9721    Notes:
9722     Must be called after MatFactorSetSchurIS().
9723 
9724    Call MatFactorGetSchurComplement() or  MatFactorCreateSchurComplement() AFTER this call to actually compute the inverse and get access to it.
9725 
9726    Level: advanced
9727 
9728    References:
9729 
9730 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9731 @*/
9732 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9733 {
9734   PetscFunctionBegin;
9735   PetscValidType(F,1);
9736   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9737   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9738   PetscCall(MatFactorFactorizeSchurComplement(F));
9739   PetscCall(MatFactorInvertSchurComplement_Private(F));
9740   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9741   PetscFunctionReturn(0);
9742 }
9743 
9744 /*@
9745   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9746 
9747    Logically Collective on Mat
9748 
9749    Input Parameters:
9750 .  F - the factored matrix obtained by calling MatGetFactor()
9751 
9752    Notes:
9753     Must be called after MatFactorSetSchurIS().
9754 
9755    Level: advanced
9756 
9757    References:
9758 
9759 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9760 @*/
9761 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9762 {
9763   PetscFunctionBegin;
9764   PetscValidType(F,1);
9765   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9766   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9767   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9768   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9769   PetscFunctionReturn(0);
9770 }
9771 
9772 /*@
9773    MatPtAP - Creates the matrix product C = P^T * A * P
9774 
9775    Neighbor-wise Collective on Mat
9776 
9777    Input Parameters:
9778 +  A - the matrix
9779 .  P - the projection matrix
9780 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9781 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use PETSC_DEFAULT if you do not have a good estimate
9782           if the result is a dense matrix this is irrelevant
9783 
9784    Output Parameters:
9785 .  C - the product matrix
9786 
9787    Notes:
9788    C will be created and must be destroyed by the user with MatDestroy().
9789 
9790    For matrix types without special implementation the function fallbacks to MatMatMult() followed by MatTransposeMatMult().
9791 
9792    Level: intermediate
9793 
9794 .seealso: `MatMatMult()`, `MatRARt()`
9795 @*/
9796 PetscErrorCode MatPtAP(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
9797 {
9798   PetscFunctionBegin;
9799   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9800   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9801 
9802   if (scall == MAT_INITIAL_MATRIX) {
9803     PetscCall(MatProductCreate(A,P,NULL,C));
9804     PetscCall(MatProductSetType(*C,MATPRODUCT_PtAP));
9805     PetscCall(MatProductSetAlgorithm(*C,"default"));
9806     PetscCall(MatProductSetFill(*C,fill));
9807 
9808     (*C)->product->api_user = PETSC_TRUE;
9809     PetscCall(MatProductSetFromOptions(*C));
9810     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);
9811     PetscCall(MatProductSymbolic(*C));
9812   } else { /* scall == MAT_REUSE_MATRIX */
9813     PetscCall(MatProductReplaceMats(A,P,NULL,*C));
9814   }
9815 
9816   PetscCall(MatProductNumeric(*C));
9817   (*C)->symmetric = A->symmetric;
9818   (*C)->spd       = A->spd;
9819   PetscFunctionReturn(0);
9820 }
9821 
9822 /*@
9823    MatRARt - Creates the matrix product C = R * A * R^T
9824 
9825    Neighbor-wise Collective on Mat
9826 
9827    Input Parameters:
9828 +  A - the matrix
9829 .  R - the projection matrix
9830 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9831 -  fill - expected fill as ratio of nnz(C)/nnz(A), use PETSC_DEFAULT if you do not have a good estimate
9832           if the result is a dense matrix this is irrelevant
9833 
9834    Output Parameters:
9835 .  C - the product matrix
9836 
9837    Notes:
9838    C will be created and must be destroyed by the user with MatDestroy().
9839 
9840    This routine is currently only implemented for pairs of AIJ matrices and classes
9841    which inherit from AIJ. Due to PETSc sparse matrix block row distribution among processes,
9842    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9843    We recommend using MatPtAP().
9844 
9845    Level: intermediate
9846 
9847 .seealso: `MatMatMult()`, `MatPtAP()`
9848 @*/
9849 PetscErrorCode MatRARt(Mat A,Mat R,MatReuse scall,PetscReal fill,Mat *C)
9850 {
9851   PetscFunctionBegin;
9852   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9853   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9854 
9855   if (scall == MAT_INITIAL_MATRIX) {
9856     PetscCall(MatProductCreate(A,R,NULL,C));
9857     PetscCall(MatProductSetType(*C,MATPRODUCT_RARt));
9858     PetscCall(MatProductSetAlgorithm(*C,"default"));
9859     PetscCall(MatProductSetFill(*C,fill));
9860 
9861     (*C)->product->api_user = PETSC_TRUE;
9862     PetscCall(MatProductSetFromOptions(*C));
9863     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);
9864     PetscCall(MatProductSymbolic(*C));
9865   } else { /* scall == MAT_REUSE_MATRIX */
9866     PetscCall(MatProductReplaceMats(A,R,NULL,*C));
9867   }
9868 
9869   PetscCall(MatProductNumeric(*C));
9870   if (A->symmetric == PETSC_BOOL3_TRUE) {
9871     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9872   }
9873   PetscFunctionReturn(0);
9874 }
9875 
9876 static PetscErrorCode MatProduct_Private(Mat A,Mat B,MatReuse scall,PetscReal fill,MatProductType ptype, Mat *C)
9877 {
9878   PetscFunctionBegin;
9879   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9880 
9881   if (scall == MAT_INITIAL_MATRIX) {
9882     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n",MatProductTypes[ptype]));
9883     PetscCall(MatProductCreate(A,B,NULL,C));
9884     PetscCall(MatProductSetType(*C,ptype));
9885     PetscCall(MatProductSetAlgorithm(*C,MATPRODUCTALGORITHMDEFAULT));
9886     PetscCall(MatProductSetFill(*C,fill));
9887 
9888     (*C)->product->api_user = PETSC_TRUE;
9889     PetscCall(MatProductSetFromOptions(*C));
9890     PetscCall(MatProductSymbolic(*C));
9891   } else { /* scall == MAT_REUSE_MATRIX */
9892     Mat_Product *product = (*C)->product;
9893     PetscBool isdense;
9894 
9895     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C),&isdense,MATSEQDENSE,MATMPIDENSE,""));
9896     if (isdense && product && product->type != ptype) {
9897       PetscCall(MatProductClear(*C));
9898       product = NULL;
9899     }
9900     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n",product ? "with" : "without",MatProductTypes[ptype]));
9901     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9902       if (isdense) {
9903         PetscCall(MatProductCreate_Private(A,B,NULL,*C));
9904         product = (*C)->product;
9905         product->fill     = fill;
9906         product->api_user = PETSC_TRUE;
9907         product->clear    = PETSC_TRUE;
9908 
9909         PetscCall(MatProductSetType(*C,ptype));
9910         PetscCall(MatProductSetFromOptions(*C));
9911         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);
9912         PetscCall(MatProductSymbolic(*C));
9913       } else SETERRQ(PetscObjectComm((PetscObject)(*C)),PETSC_ERR_SUP,"Call MatProductCreate() first");
9914     } else { /* user may change input matrices A or B when REUSE */
9915       PetscCall(MatProductReplaceMats(A,B,NULL,*C));
9916     }
9917   }
9918   PetscCall(MatProductNumeric(*C));
9919   PetscFunctionReturn(0);
9920 }
9921 
9922 /*@
9923    MatMatMult - Performs Matrix-Matrix Multiplication C=A*B.
9924 
9925    Neighbor-wise Collective on Mat
9926 
9927    Input Parameters:
9928 +  A - the left matrix
9929 .  B - the right matrix
9930 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9931 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if you do not have a good estimate
9932           if the result is a dense matrix this is irrelevant
9933 
9934    Output Parameters:
9935 .  C - the product matrix
9936 
9937    Notes:
9938    Unless scall is MAT_REUSE_MATRIX C will be created.
9939 
9940    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
9941    call to this function with MAT_INITIAL_MATRIX.
9942 
9943    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9944 
9945    If you have many matrices with the same non-zero structure to multiply, you should use MatProductCreate()/MatProductSymbolic()/MatProductReplaceMats(), and call MatProductNumeric() repeatedly.
9946 
9947    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.
9948 
9949    Example of Usage:
9950 .vb
9951      MatProductCreate(A,B,NULL,&C);
9952      MatProductSetType(C,MATPRODUCT_AB);
9953      MatProductSymbolic(C);
9954      MatProductNumeric(C); // compute C=A * B
9955      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9956      MatProductNumeric(C);
9957      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9958      MatProductNumeric(C);
9959 .ve
9960 
9961    Level: intermediate
9962 
9963 .seealso: `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9964 @*/
9965 PetscErrorCode MatMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9966 {
9967   PetscFunctionBegin;
9968   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AB,C));
9969   PetscFunctionReturn(0);
9970 }
9971 
9972 /*@
9973    MatMatTransposeMult - Performs Matrix-Matrix Multiplication C=A*B^T.
9974 
9975    Neighbor-wise Collective on Mat
9976 
9977    Input Parameters:
9978 +  A - the left matrix
9979 .  B - the right matrix
9980 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9981 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9982 
9983    Output Parameters:
9984 .  C - the product matrix
9985 
9986    Notes:
9987    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9988 
9989    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9990 
9991   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9992    actually needed.
9993 
9994    This routine is currently only implemented for pairs of SeqAIJ matrices, for the SeqDense class,
9995    and for pairs of MPIDense matrices.
9996 
9997    Options Database Keys:
9998 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for MPIDense matrices: the
9999               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10000               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10001 
10002    Level: intermediate
10003 
10004 .seealso: `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`
10005 @*/
10006 PetscErrorCode MatMatTransposeMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
10007 {
10008   PetscFunctionBegin;
10009   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_ABt,C));
10010   if (A == B) {
10011     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
10012   }
10013   PetscFunctionReturn(0);
10014 }
10015 
10016 /*@
10017    MatTransposeMatMult - Performs Matrix-Matrix Multiplication C=A^T*B.
10018 
10019    Neighbor-wise Collective on Mat
10020 
10021    Input Parameters:
10022 +  A - the left matrix
10023 .  B - the right matrix
10024 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10025 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
10026 
10027    Output Parameters:
10028 .  C - the product matrix
10029 
10030    Notes:
10031    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
10032 
10033    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10034 
10035   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10036    actually needed.
10037 
10038    This routine is currently implemented for pairs of AIJ matrices and pairs of SeqDense matrices and classes
10039    which inherit from SeqAIJ.  C will be of the same type as the input matrices.
10040 
10041    Level: intermediate
10042 
10043 .seealso: `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10044 @*/
10045 PetscErrorCode MatTransposeMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
10046 {
10047   PetscFunctionBegin;
10048   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AtB,C));
10049   PetscFunctionReturn(0);
10050 }
10051 
10052 /*@
10053    MatMatMatMult - Performs Matrix-Matrix-Matrix Multiplication D=A*B*C.
10054 
10055    Neighbor-wise Collective on Mat
10056 
10057    Input Parameters:
10058 +  A - the left matrix
10059 .  B - the middle matrix
10060 .  C - the right matrix
10061 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10062 -  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
10063           if the result is a dense matrix this is irrelevant
10064 
10065    Output Parameters:
10066 .  D - the product matrix
10067 
10068    Notes:
10069    Unless scall is MAT_REUSE_MATRIX D will be created.
10070 
10071    MAT_REUSE_MATRIX can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10072 
10073    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10074    actually needed.
10075 
10076    If you have many matrices with the same non-zero structure to multiply, you
10077    should use MAT_REUSE_MATRIX in all calls but the first
10078 
10079    Level: intermediate
10080 
10081 .seealso: `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10082 @*/
10083 PetscErrorCode MatMatMatMult(Mat A,Mat B,Mat C,MatReuse scall,PetscReal fill,Mat *D)
10084 {
10085   PetscFunctionBegin;
10086   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D,6);
10087   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
10088 
10089   if (scall == MAT_INITIAL_MATRIX) {
10090     PetscCall(MatProductCreate(A,B,C,D));
10091     PetscCall(MatProductSetType(*D,MATPRODUCT_ABC));
10092     PetscCall(MatProductSetAlgorithm(*D,"default"));
10093     PetscCall(MatProductSetFill(*D,fill));
10094 
10095     (*D)->product->api_user = PETSC_TRUE;
10096     PetscCall(MatProductSetFromOptions(*D));
10097     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);
10098     PetscCall(MatProductSymbolic(*D));
10099   } else { /* user may change input matrices when REUSE */
10100     PetscCall(MatProductReplaceMats(A,B,C,*D));
10101   }
10102   PetscCall(MatProductNumeric(*D));
10103   PetscFunctionReturn(0);
10104 }
10105 
10106 /*@
10107    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10108 
10109    Collective on Mat
10110 
10111    Input Parameters:
10112 +  mat - the matrix
10113 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10114 .  subcomm - MPI communicator split from the communicator where mat resides in (or MPI_COMM_NULL if nsubcomm is used)
10115 -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10116 
10117    Output Parameter:
10118 .  matredundant - redundant matrix
10119 
10120    Notes:
10121    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
10122    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10123 
10124    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10125    calling it.
10126 
10127    Level: advanced
10128 
10129 .seealso: `MatDestroy()`
10130 @*/
10131 PetscErrorCode MatCreateRedundantMatrix(Mat mat,PetscInt nsubcomm,MPI_Comm subcomm,MatReuse reuse,Mat *matredundant)
10132 {
10133   MPI_Comm       comm;
10134   PetscMPIInt    size;
10135   PetscInt       mloc_sub,nloc_sub,rstart,rend,M=mat->rmap->N,N=mat->cmap->N,bs=mat->rmap->bs;
10136   Mat_Redundant  *redund=NULL;
10137   PetscSubcomm   psubcomm=NULL;
10138   MPI_Comm       subcomm_in=subcomm;
10139   Mat            *matseq;
10140   IS             isrow,iscol;
10141   PetscBool      newsubcomm=PETSC_FALSE;
10142 
10143   PetscFunctionBegin;
10144   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10145   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10146     PetscValidPointer(*matredundant,5);
10147     PetscValidHeaderSpecific(*matredundant,MAT_CLASSID,5);
10148   }
10149 
10150   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10151   if (size == 1 || nsubcomm == 1) {
10152     if (reuse == MAT_INITIAL_MATRIX) {
10153       PetscCall(MatDuplicate(mat,MAT_COPY_VALUES,matredundant));
10154     } else {
10155       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");
10156       PetscCall(MatCopy(mat,*matredundant,SAME_NONZERO_PATTERN));
10157     }
10158     PetscFunctionReturn(0);
10159   }
10160 
10161   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10162   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10163   MatCheckPreallocated(mat,1);
10164 
10165   PetscCall(PetscLogEventBegin(MAT_RedundantMat,mat,0,0,0));
10166   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10167     /* create psubcomm, then get subcomm */
10168     PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10169     PetscCallMPI(MPI_Comm_size(comm,&size));
10170     PetscCheck(nsubcomm >= 1 && nsubcomm <= size,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"nsubcomm must between 1 and %d",size);
10171 
10172     PetscCall(PetscSubcommCreate(comm,&psubcomm));
10173     PetscCall(PetscSubcommSetNumber(psubcomm,nsubcomm));
10174     PetscCall(PetscSubcommSetType(psubcomm,PETSC_SUBCOMM_CONTIGUOUS));
10175     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10176     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm),&subcomm,NULL));
10177     newsubcomm = PETSC_TRUE;
10178     PetscCall(PetscSubcommDestroy(&psubcomm));
10179   }
10180 
10181   /* get isrow, iscol and a local sequential matrix matseq[0] */
10182   if (reuse == MAT_INITIAL_MATRIX) {
10183     mloc_sub = PETSC_DECIDE;
10184     nloc_sub = PETSC_DECIDE;
10185     if (bs < 1) {
10186       PetscCall(PetscSplitOwnership(subcomm,&mloc_sub,&M));
10187       PetscCall(PetscSplitOwnership(subcomm,&nloc_sub,&N));
10188     } else {
10189       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&mloc_sub,&M));
10190       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&nloc_sub,&N));
10191     }
10192     PetscCallMPI(MPI_Scan(&mloc_sub,&rend,1,MPIU_INT,MPI_SUM,subcomm));
10193     rstart = rend - mloc_sub;
10194     PetscCall(ISCreateStride(PETSC_COMM_SELF,mloc_sub,rstart,1,&isrow));
10195     PetscCall(ISCreateStride(PETSC_COMM_SELF,N,0,1,&iscol));
10196   } else { /* reuse == MAT_REUSE_MATRIX */
10197     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");
10198     /* retrieve subcomm */
10199     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant),&subcomm));
10200     redund = (*matredundant)->redundant;
10201     isrow  = redund->isrow;
10202     iscol  = redund->iscol;
10203     matseq = redund->matseq;
10204   }
10205   PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscol,reuse,&matseq));
10206 
10207   /* get matredundant over subcomm */
10208   if (reuse == MAT_INITIAL_MATRIX) {
10209     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],nloc_sub,reuse,matredundant));
10210 
10211     /* create a supporting struct and attach it to C for reuse */
10212     PetscCall(PetscNewLog(*matredundant,&redund));
10213     (*matredundant)->redundant = redund;
10214     redund->isrow              = isrow;
10215     redund->iscol              = iscol;
10216     redund->matseq             = matseq;
10217     if (newsubcomm) {
10218       redund->subcomm          = subcomm;
10219     } else {
10220       redund->subcomm          = MPI_COMM_NULL;
10221     }
10222   } else {
10223     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],PETSC_DECIDE,reuse,matredundant));
10224   }
10225 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
10226   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10227     PetscCall(MatBindToCPU(*matredundant,PETSC_TRUE));
10228     PetscCall(MatSetBindingPropagates(*matredundant,PETSC_TRUE));
10229   }
10230 #endif
10231   PetscCall(PetscLogEventEnd(MAT_RedundantMat,mat,0,0,0));
10232   PetscFunctionReturn(0);
10233 }
10234 
10235 /*@C
10236    MatGetMultiProcBlock - Create multiple [bjacobi] 'parallel submatrices' from
10237    a given 'mat' object. Each submatrix can span multiple procs.
10238 
10239    Collective on Mat
10240 
10241    Input Parameters:
10242 +  mat - the matrix
10243 .  subcomm - the subcommunicator obtained by com_split(comm)
10244 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10245 
10246    Output Parameter:
10247 .  subMat - 'parallel submatrices each spans a given subcomm
10248 
10249   Notes:
10250   The submatrix partition across processors is dictated by 'subComm' a
10251   communicator obtained by MPI_comm_split(). The subComm
10252   is not restriced to be grouped with consecutive original ranks.
10253 
10254   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10255   map directly to the layout of the original matrix [wrt the local
10256   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10257   into the 'DiagonalMat' of the subMat, hence it is used directly from
10258   the subMat. However the offDiagMat looses some columns - and this is
10259   reconstructed with MatSetValues()
10260 
10261   Level: advanced
10262 
10263 .seealso: `MatCreateSubMatrices()`
10264 @*/
10265 PetscErrorCode   MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall,Mat *subMat)
10266 {
10267   PetscMPIInt    commsize,subCommSize;
10268 
10269   PetscFunctionBegin;
10270   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&commsize));
10271   PetscCallMPI(MPI_Comm_size(subComm,&subCommSize));
10272   PetscCheck(subCommSize <= commsize,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"CommSize %d < SubCommZize %d",commsize,subCommSize);
10273 
10274   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");
10275   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock,mat,0,0,0));
10276   PetscCall((*mat->ops->getmultiprocblock)(mat,subComm,scall,subMat));
10277   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock,mat,0,0,0));
10278   PetscFunctionReturn(0);
10279 }
10280 
10281 /*@
10282    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10283 
10284    Not Collective
10285 
10286    Input Parameters:
10287 +  mat - matrix to extract local submatrix from
10288 .  isrow - local row indices for submatrix
10289 -  iscol - local column indices for submatrix
10290 
10291    Output Parameter:
10292 .  submat - the submatrix
10293 
10294    Level: intermediate
10295 
10296    Notes:
10297    The submat should be returned with MatRestoreLocalSubMatrix().
10298 
10299    Depending on the format of mat, the returned submat may not implement MatMult().  Its communicator may be
10300    the same as mat, it may be PETSC_COMM_SELF, or some other subcomm of mat's.
10301 
10302    The submat always implements MatSetValuesLocal().  If isrow and iscol have the same block size, then
10303    MatSetValuesBlockedLocal() will also be implemented.
10304 
10305    The mat must have had a ISLocalToGlobalMapping provided to it with MatSetLocalToGlobalMapping(). Note that
10306    matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10307 
10308 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10309 @*/
10310 PetscErrorCode MatGetLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10311 {
10312   PetscFunctionBegin;
10313   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10314   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10315   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10316   PetscCheckSameComm(isrow,2,iscol,3);
10317   PetscValidPointer(submat,4);
10318   PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must have local to global mapping provided before this call");
10319 
10320   if (mat->ops->getlocalsubmatrix) {
10321     PetscCall((*mat->ops->getlocalsubmatrix)(mat,isrow,iscol,submat));
10322   } else {
10323     PetscCall(MatCreateLocalRef(mat,isrow,iscol,submat));
10324   }
10325   PetscFunctionReturn(0);
10326 }
10327 
10328 /*@
10329    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering
10330 
10331    Not Collective
10332 
10333    Input Parameters:
10334 +  mat - matrix to extract local submatrix from
10335 .  isrow - local row indices for submatrix
10336 .  iscol - local column indices for submatrix
10337 -  submat - the submatrix
10338 
10339    Level: intermediate
10340 
10341 .seealso: `MatGetLocalSubMatrix()`
10342 @*/
10343 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10344 {
10345   PetscFunctionBegin;
10346   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10347   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10348   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10349   PetscCheckSameComm(isrow,2,iscol,3);
10350   PetscValidPointer(submat,4);
10351   if (*submat) {
10352     PetscValidHeaderSpecific(*submat,MAT_CLASSID,4);
10353   }
10354 
10355   if (mat->ops->restorelocalsubmatrix) {
10356     PetscCall((*mat->ops->restorelocalsubmatrix)(mat,isrow,iscol,submat));
10357   } else {
10358     PetscCall(MatDestroy(submat));
10359   }
10360   *submat = NULL;
10361   PetscFunctionReturn(0);
10362 }
10363 
10364 /* --------------------------------------------------------*/
10365 /*@
10366    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10367 
10368    Collective on Mat
10369 
10370    Input Parameter:
10371 .  mat - the matrix
10372 
10373    Output Parameter:
10374 .  is - if any rows have zero diagonals this contains the list of them
10375 
10376    Level: developer
10377 
10378 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10379 @*/
10380 PetscErrorCode MatFindZeroDiagonals(Mat mat,IS *is)
10381 {
10382   PetscFunctionBegin;
10383   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10384   PetscValidType(mat,1);
10385   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10386   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10387 
10388   if (!mat->ops->findzerodiagonals) {
10389     Vec                diag;
10390     const PetscScalar *a;
10391     PetscInt          *rows;
10392     PetscInt           rStart, rEnd, r, nrow = 0;
10393 
10394     PetscCall(MatCreateVecs(mat, &diag, NULL));
10395     PetscCall(MatGetDiagonal(mat, diag));
10396     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10397     PetscCall(VecGetArrayRead(diag, &a));
10398     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) ++nrow;
10399     PetscCall(PetscMalloc1(nrow, &rows));
10400     nrow = 0;
10401     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) rows[nrow++] = r+rStart;
10402     PetscCall(VecRestoreArrayRead(diag, &a));
10403     PetscCall(VecDestroy(&diag));
10404     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) mat), nrow, rows, PETSC_OWN_POINTER, is));
10405   } else {
10406     PetscCall((*mat->ops->findzerodiagonals)(mat, is));
10407   }
10408   PetscFunctionReturn(0);
10409 }
10410 
10411 /*@
10412    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10413 
10414    Collective on Mat
10415 
10416    Input Parameter:
10417 .  mat - the matrix
10418 
10419    Output Parameter:
10420 .  is - contains the list of rows with off block diagonal entries
10421 
10422    Level: developer
10423 
10424 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10425 @*/
10426 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat,IS *is)
10427 {
10428   PetscFunctionBegin;
10429   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10430   PetscValidType(mat,1);
10431   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10432   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10433 
10434   PetscCheck(mat->ops->findoffblockdiagonalentries,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a find off block diagonal entries defined",((PetscObject)mat)->type_name);
10435   PetscCall((*mat->ops->findoffblockdiagonalentries)(mat,is));
10436   PetscFunctionReturn(0);
10437 }
10438 
10439 /*@C
10440   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10441 
10442   Collective on Mat
10443 
10444   Input Parameters:
10445 . mat - the matrix
10446 
10447   Output Parameters:
10448 . values - the block inverses in column major order (FORTRAN-like)
10449 
10450    Note:
10451      The size of the blocks is determined by the block size of the matrix.
10452 
10453    Fortran Note:
10454      This routine is not available from Fortran.
10455 
10456   Level: advanced
10457 
10458 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10459 @*/
10460 PetscErrorCode MatInvertBlockDiagonal(Mat mat,const PetscScalar **values)
10461 {
10462   PetscFunctionBegin;
10463   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10464   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10465   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10466   PetscCheck(mat->ops->invertblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10467   PetscCall((*mat->ops->invertblockdiagonal)(mat,values));
10468   PetscFunctionReturn(0);
10469 }
10470 
10471 /*@C
10472   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10473 
10474   Collective on Mat
10475 
10476   Input Parameters:
10477 + mat - the matrix
10478 . nblocks - the number of blocks on the process, set with MatSetVariableBlockSizes()
10479 - bsizes - the size of each block on the process, set with MatSetVariableBlockSizes()
10480 
10481   Output Parameters:
10482 . values - the block inverses in column major order (FORTRAN-like)
10483 
10484    Note:
10485    This routine is not available from Fortran.
10486 
10487   Level: advanced
10488 
10489 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10490 @*/
10491 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *values)
10492 {
10493   PetscFunctionBegin;
10494   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10495   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10496   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10497   PetscCheck(mat->ops->invertvariableblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10498   PetscCall((*mat->ops->invertvariableblockdiagonal)(mat,nblocks,bsizes,values));
10499   PetscFunctionReturn(0);
10500 }
10501 
10502 /*@
10503   MatInvertBlockDiagonalMat - set matrix C to be the inverted block diagonal of matrix A
10504 
10505   Collective on Mat
10506 
10507   Input Parameters:
10508 . A - the matrix
10509 
10510   Output Parameters:
10511 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10512 
10513   Notes: the blocksize of the matrix is used to determine the blocks on the diagonal of C
10514 
10515   Level: advanced
10516 
10517 .seealso: `MatInvertBlockDiagonal()`
10518 @*/
10519 PetscErrorCode MatInvertBlockDiagonalMat(Mat A,Mat C)
10520 {
10521   const PetscScalar *vals;
10522   PetscInt          *dnnz;
10523   PetscInt           m,rstart,rend,bs,i,j;
10524 
10525   PetscFunctionBegin;
10526   PetscCall(MatInvertBlockDiagonal(A,&vals));
10527   PetscCall(MatGetBlockSize(A,&bs));
10528   PetscCall(MatGetLocalSize(A,&m,NULL));
10529   PetscCall(MatSetLayouts(C,A->rmap,A->cmap));
10530   PetscCall(PetscMalloc1(m/bs,&dnnz));
10531   for (j = 0; j < m/bs; j++) dnnz[j] = 1;
10532   PetscCall(MatXAIJSetPreallocation(C,bs,dnnz,NULL,NULL,NULL));
10533   PetscCall(PetscFree(dnnz));
10534   PetscCall(MatGetOwnershipRange(C,&rstart,&rend));
10535   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_FALSE));
10536   for (i = rstart/bs; i < rend/bs; i++) {
10537     PetscCall(MatSetValuesBlocked(C,1,&i,1,&i,&vals[(i-rstart/bs)*bs*bs],INSERT_VALUES));
10538   }
10539   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
10540   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
10541   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_TRUE));
10542   PetscFunctionReturn(0);
10543 }
10544 
10545 /*@C
10546     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10547     via MatTransposeColoringCreate().
10548 
10549     Collective on MatTransposeColoring
10550 
10551     Input Parameter:
10552 .   c - coloring context
10553 
10554     Level: intermediate
10555 
10556 .seealso: `MatTransposeColoringCreate()`
10557 @*/
10558 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10559 {
10560   MatTransposeColoring matcolor=*c;
10561 
10562   PetscFunctionBegin;
10563   if (!matcolor) PetscFunctionReturn(0);
10564   if (--((PetscObject)matcolor)->refct > 0) {matcolor = NULL; PetscFunctionReturn(0);}
10565 
10566   PetscCall(PetscFree3(matcolor->ncolumns,matcolor->nrows,matcolor->colorforrow));
10567   PetscCall(PetscFree(matcolor->rows));
10568   PetscCall(PetscFree(matcolor->den2sp));
10569   PetscCall(PetscFree(matcolor->colorforcol));
10570   PetscCall(PetscFree(matcolor->columns));
10571   if (matcolor->brows>0) PetscCall(PetscFree(matcolor->lstart));
10572   PetscCall(PetscHeaderDestroy(c));
10573   PetscFunctionReturn(0);
10574 }
10575 
10576 /*@C
10577     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10578     a MatTransposeColoring context has been created, computes a dense B^T by Apply
10579     MatTransposeColoring to sparse B.
10580 
10581     Collective on MatTransposeColoring
10582 
10583     Input Parameters:
10584 +   B - sparse matrix B
10585 .   Btdense - symbolic dense matrix B^T
10586 -   coloring - coloring context created with MatTransposeColoringCreate()
10587 
10588     Output Parameter:
10589 .   Btdense - dense matrix B^T
10590 
10591     Level: advanced
10592 
10593      Notes:
10594     These are used internally for some implementations of MatRARt()
10595 
10596 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10597 
10598 @*/
10599 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring,Mat B,Mat Btdense)
10600 {
10601   PetscFunctionBegin;
10602   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10603   PetscValidHeaderSpecific(Btdense,MAT_CLASSID,3);
10604   PetscValidHeaderSpecific(coloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10605 
10606   PetscCheck(B->ops->transcoloringapplysptoden,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)B)->type_name);
10607   PetscCall((B->ops->transcoloringapplysptoden)(coloring,B,Btdense));
10608   PetscFunctionReturn(0);
10609 }
10610 
10611 /*@C
10612     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10613     a MatTransposeColoring context has been created and a dense matrix Cden=A*Btdense
10614     in which Btdens is obtained from MatTransColoringApplySpToDen(), recover sparse matrix
10615     Csp from Cden.
10616 
10617     Collective on MatTransposeColoring
10618 
10619     Input Parameters:
10620 +   coloring - coloring context created with MatTransposeColoringCreate()
10621 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10622 
10623     Output Parameter:
10624 .   Csp - sparse matrix
10625 
10626     Level: advanced
10627 
10628      Notes:
10629     These are used internally for some implementations of MatRARt()
10630 
10631 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10632 
10633 @*/
10634 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring,Mat Cden,Mat Csp)
10635 {
10636   PetscFunctionBegin;
10637   PetscValidHeaderSpecific(matcoloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10638   PetscValidHeaderSpecific(Cden,MAT_CLASSID,2);
10639   PetscValidHeaderSpecific(Csp,MAT_CLASSID,3);
10640 
10641   PetscCheck(Csp->ops->transcoloringapplydentosp,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)Csp)->type_name);
10642   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring,Cden,Csp));
10643   PetscCall(MatAssemblyBegin(Csp,MAT_FINAL_ASSEMBLY));
10644   PetscCall(MatAssemblyEnd(Csp,MAT_FINAL_ASSEMBLY));
10645   PetscFunctionReturn(0);
10646 }
10647 
10648 /*@C
10649    MatTransposeColoringCreate - Creates a matrix coloring context for matrix product C=A*B^T.
10650 
10651    Collective on Mat
10652 
10653    Input Parameters:
10654 +  mat - the matrix product C
10655 -  iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring()
10656 
10657     Output Parameter:
10658 .   color - the new coloring context
10659 
10660     Level: intermediate
10661 
10662 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10663           `MatTransColoringApplyDenToSp()`
10664 @*/
10665 PetscErrorCode MatTransposeColoringCreate(Mat mat,ISColoring iscoloring,MatTransposeColoring *color)
10666 {
10667   MatTransposeColoring c;
10668   MPI_Comm             comm;
10669 
10670   PetscFunctionBegin;
10671   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate,mat,0,0,0));
10672   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10673   PetscCall(PetscHeaderCreate(c,MAT_TRANSPOSECOLORING_CLASSID,"MatTransposeColoring","Matrix product C=A*B^T via coloring","Mat",comm,MatTransposeColoringDestroy,NULL));
10674 
10675   c->ctype = iscoloring->ctype;
10676   if (mat->ops->transposecoloringcreate) {
10677     PetscCall((*mat->ops->transposecoloringcreate)(mat,iscoloring,c));
10678   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);
10679 
10680   *color = c;
10681   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate,mat,0,0,0));
10682   PetscFunctionReturn(0);
10683 }
10684 
10685 /*@
10686       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10687         matrix has had no new nonzero locations added to the matrix since the previous call then the value will be the
10688         same, otherwise it will be larger
10689 
10690      Not Collective
10691 
10692   Input Parameter:
10693 .    A  - the matrix
10694 
10695   Output Parameter:
10696 .    state - the current state
10697 
10698   Notes:
10699     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10700          different matrices
10701 
10702   Level: intermediate
10703 
10704 .seealso: `PetscObjectStateGet()`
10705 @*/
10706 PetscErrorCode MatGetNonzeroState(Mat mat,PetscObjectState *state)
10707 {
10708   PetscFunctionBegin;
10709   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10710   *state = mat->nonzerostate;
10711   PetscFunctionReturn(0);
10712 }
10713 
10714 /*@
10715       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10716                  matrices from each processor
10717 
10718     Collective
10719 
10720    Input Parameters:
10721 +    comm - the communicators the parallel matrix will live on
10722 .    seqmat - the input sequential matrices
10723 .    n - number of local columns (or PETSC_DECIDE)
10724 -    reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10725 
10726    Output Parameter:
10727 .    mpimat - the parallel matrix generated
10728 
10729     Level: advanced
10730 
10731    Notes:
10732     The number of columns of the matrix in EACH processor MUST be the same.
10733 
10734 @*/
10735 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm,Mat seqmat,PetscInt n,MatReuse reuse,Mat *mpimat)
10736 {
10737   PetscMPIInt size;
10738 
10739   PetscFunctionBegin;
10740   PetscCallMPI(MPI_Comm_size(comm,&size));
10741   if (size == 1) {
10742     if (reuse == MAT_INITIAL_MATRIX) {
10743       PetscCall(MatDuplicate(seqmat,MAT_COPY_VALUES,mpimat));
10744     } else {
10745       PetscCall(MatCopy(seqmat,*mpimat,SAME_NONZERO_PATTERN));
10746     }
10747     PetscFunctionReturn(0);
10748   }
10749 
10750   PetscCheck(seqmat->ops->creatempimatconcatenateseqmat,PetscObjectComm((PetscObject)seqmat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)seqmat)->type_name);
10751   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");
10752 
10753   PetscCall(PetscLogEventBegin(MAT_Merge,seqmat,0,0,0));
10754   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm,seqmat,n,reuse,mpimat));
10755   PetscCall(PetscLogEventEnd(MAT_Merge,seqmat,0,0,0));
10756   PetscFunctionReturn(0);
10757 }
10758 
10759 /*@
10760      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent
10761                  ranks' ownership ranges.
10762 
10763     Collective on A
10764 
10765    Input Parameters:
10766 +    A   - the matrix to create subdomains from
10767 -    N   - requested number of subdomains
10768 
10769    Output Parameters:
10770 +    n   - number of subdomains resulting on this rank
10771 -    iss - IS list with indices of subdomains on this rank
10772 
10773     Level: advanced
10774 
10775     Notes:
10776     number of subdomains must be smaller than the communicator size
10777 @*/
10778 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A,PetscInt N,PetscInt *n,IS *iss[])
10779 {
10780   MPI_Comm        comm,subcomm;
10781   PetscMPIInt     size,rank,color;
10782   PetscInt        rstart,rend,k;
10783 
10784   PetscFunctionBegin;
10785   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
10786   PetscCallMPI(MPI_Comm_size(comm,&size));
10787   PetscCallMPI(MPI_Comm_rank(comm,&rank));
10788   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);
10789   *n = 1;
10790   k = ((PetscInt)size)/N + ((PetscInt)size%N>0); /* There are up to k ranks to a color */
10791   color = rank/k;
10792   PetscCallMPI(MPI_Comm_split(comm,color,rank,&subcomm));
10793   PetscCall(PetscMalloc1(1,iss));
10794   PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
10795   PetscCall(ISCreateStride(subcomm,rend-rstart,rstart,1,iss[0]));
10796   PetscCallMPI(MPI_Comm_free(&subcomm));
10797   PetscFunctionReturn(0);
10798 }
10799 
10800 /*@
10801    MatGalerkin - Constructs the coarse grid problem via Galerkin projection.
10802 
10803    If the interpolation and restriction operators are the same, uses MatPtAP.
10804    If they are not the same, use MatMatMatMult.
10805 
10806    Once the coarse grid problem is constructed, correct for interpolation operators
10807    that are not of full rank, which can legitimately happen in the case of non-nested
10808    geometric multigrid.
10809 
10810    Input Parameters:
10811 +  restrct - restriction operator
10812 .  dA - fine grid matrix
10813 .  interpolate - interpolation operator
10814 .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10815 -  fill - expected fill, use PETSC_DEFAULT if you do not have a good estimate
10816 
10817    Output Parameters:
10818 .  A - the Galerkin coarse matrix
10819 
10820    Options Database Key:
10821 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10822 
10823    Level: developer
10824 
10825 .seealso: `MatPtAP()`, `MatMatMatMult()`
10826 @*/
10827 PetscErrorCode  MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10828 {
10829   IS             zerorows;
10830   Vec            diag;
10831 
10832   PetscFunctionBegin;
10833   PetscCheck(reuse != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
10834   /* Construct the coarse grid matrix */
10835   if (interpolate == restrct) {
10836     PetscCall(MatPtAP(dA,interpolate,reuse,fill,A));
10837   } else {
10838     PetscCall(MatMatMatMult(restrct,dA,interpolate,reuse,fill,A));
10839   }
10840 
10841   /* If the interpolation matrix is not of full rank, A will have zero rows.
10842      This can legitimately happen in the case of non-nested geometric multigrid.
10843      In that event, we set the rows of the matrix to the rows of the identity,
10844      ignoring the equations (as the RHS will also be zero). */
10845 
10846   PetscCall(MatFindZeroRows(*A, &zerorows));
10847 
10848   if (zerorows != NULL) { /* if there are any zero rows */
10849     PetscCall(MatCreateVecs(*A, &diag, NULL));
10850     PetscCall(MatGetDiagonal(*A, diag));
10851     PetscCall(VecISSet(diag, zerorows, 1.0));
10852     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10853     PetscCall(VecDestroy(&diag));
10854     PetscCall(ISDestroy(&zerorows));
10855   }
10856   PetscFunctionReturn(0);
10857 }
10858 
10859 /*@C
10860     MatSetOperation - Allows user to set a matrix operation for any matrix type
10861 
10862    Logically Collective on Mat
10863 
10864     Input Parameters:
10865 +   mat - the matrix
10866 .   op - the name of the operation
10867 -   f - the function that provides the operation
10868 
10869    Level: developer
10870 
10871     Usage:
10872 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10873 $      PetscCall(MatCreateXXX(comm,...&A);
10874 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10875 
10876     Notes:
10877     See the file include/petscmat.h for a complete list of matrix
10878     operations, which all have the form MATOP_<OPERATION>, where
10879     <OPERATION> is the name (in all capital letters) of the
10880     user interface routine (e.g., MatMult() -> MATOP_MULT).
10881 
10882     All user-provided functions (except for MATOP_DESTROY) should have the same calling
10883     sequence as the usual matrix interface routines, since they
10884     are intended to be accessed via the usual matrix interface
10885     routines, e.g.,
10886 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10887 
10888     In particular each function MUST return an error code of 0 on success and
10889     nonzero on failure.
10890 
10891     This routine is distinct from MatShellSetOperation() in that it can be called on any matrix type.
10892 
10893 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10894 @*/
10895 PetscErrorCode MatSetOperation(Mat mat,MatOperation op,void (*f)(void))
10896 {
10897   PetscFunctionBegin;
10898   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10899   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) {
10900     mat->ops->viewnative = mat->ops->view;
10901   }
10902   (((void(**)(void))mat->ops)[op]) = f;
10903   PetscFunctionReturn(0);
10904 }
10905 
10906 /*@C
10907     MatGetOperation - Gets a matrix operation for any matrix type.
10908 
10909     Not Collective
10910 
10911     Input Parameters:
10912 +   mat - the matrix
10913 -   op - the name of the operation
10914 
10915     Output Parameter:
10916 .   f - the function that provides the operation
10917 
10918     Level: developer
10919 
10920     Usage:
10921 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10922 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10923 
10924     Notes:
10925     See the file include/petscmat.h for a complete list of matrix
10926     operations, which all have the form MATOP_<OPERATION>, where
10927     <OPERATION> is the name (in all capital letters) of the
10928     user interface routine (e.g., MatMult() -> MATOP_MULT).
10929 
10930     This routine is distinct from MatShellGetOperation() in that it can be called on any matrix type.
10931 
10932 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10933 @*/
10934 PetscErrorCode MatGetOperation(Mat mat,MatOperation op,void(**f)(void))
10935 {
10936   PetscFunctionBegin;
10937   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10938   *f = (((void (**)(void))mat->ops)[op]);
10939   PetscFunctionReturn(0);
10940 }
10941 
10942 /*@
10943     MatHasOperation - Determines whether the given matrix supports the particular
10944     operation.
10945 
10946    Not Collective
10947 
10948    Input Parameters:
10949 +  mat - the matrix
10950 -  op - the operation, for example, MATOP_GET_DIAGONAL
10951 
10952    Output Parameter:
10953 .  has - either PETSC_TRUE or PETSC_FALSE
10954 
10955    Level: advanced
10956 
10957    Notes:
10958    See the file include/petscmat.h for a complete list of matrix
10959    operations, which all have the form MATOP_<OPERATION>, where
10960    <OPERATION> is the name (in all capital letters) of the
10961    user-level routine.  E.g., MatNorm() -> MATOP_NORM.
10962 
10963 .seealso: `MatCreateShell()`
10964 @*/
10965 PetscErrorCode MatHasOperation(Mat mat,MatOperation op,PetscBool *has)
10966 {
10967   PetscFunctionBegin;
10968   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10969   PetscValidBoolPointer(has,3);
10970   if (mat->ops->hasoperation) {
10971     PetscCall((*mat->ops->hasoperation)(mat,op,has));
10972   } else {
10973     if (((void**)mat->ops)[op]) *has = PETSC_TRUE;
10974     else {
10975       *has = PETSC_FALSE;
10976       if (op == MATOP_CREATE_SUBMATRIX) {
10977         PetscMPIInt size;
10978 
10979         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10980         if (size == 1) {
10981           PetscCall(MatHasOperation(mat,MATOP_CREATE_SUBMATRICES,has));
10982         }
10983       }
10984     }
10985   }
10986   PetscFunctionReturn(0);
10987 }
10988 
10989 /*@
10990     MatHasCongruentLayouts - Determines whether the rows and columns layouts
10991     of the matrix are congruent
10992 
10993    Collective on mat
10994 
10995    Input Parameters:
10996 .  mat - the matrix
10997 
10998    Output Parameter:
10999 .  cong - either PETSC_TRUE or PETSC_FALSE
11000 
11001    Level: beginner
11002 
11003    Notes:
11004 
11005 .seealso: `MatCreate()`, `MatSetSizes()`
11006 @*/
11007 PetscErrorCode MatHasCongruentLayouts(Mat mat,PetscBool *cong)
11008 {
11009   PetscFunctionBegin;
11010   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
11011   PetscValidType(mat,1);
11012   PetscValidBoolPointer(cong,2);
11013   if (!mat->rmap || !mat->cmap) {
11014     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11015     PetscFunctionReturn(0);
11016   }
11017   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11018     PetscCall(PetscLayoutSetUp(mat->rmap));
11019     PetscCall(PetscLayoutSetUp(mat->cmap));
11020     PetscCall(PetscLayoutCompare(mat->rmap,mat->cmap,cong));
11021     if (*cong) mat->congruentlayouts = 1;
11022     else       mat->congruentlayouts = 0;
11023   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11024   PetscFunctionReturn(0);
11025 }
11026 
11027 PetscErrorCode MatSetInf(Mat A)
11028 {
11029   PetscFunctionBegin;
11030   PetscCheck(A->ops->setinf,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for this operation for this matrix type");
11031   PetscCall((*A->ops->setinf)(A));
11032   PetscFunctionReturn(0);
11033 }
11034 
11035 /*C
11036    MatCreateGraph - create a scalar matrix, for use in graph algorithms
11037 
11038    Collective on mat
11039 
11040    Input Parameters:
11041 +  A - the matrix
11042 -  sym - PETSC_TRUE indicates that the graph will be symmetrized
11043 .  scale - PETSC_TRUE indicates that the graph will be scaled with the diagonal
11044 
11045    Output Parameter:
11046 .  graph - the resulting graph
11047 
11048    Level: advanced
11049 
11050    Notes:
11051 
11052 .seealso: `MatCreate()`, `MatFilter()`
11053 */
11054 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, Mat *graph)
11055 {
11056   PetscFunctionBegin;
11057   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
11058   PetscValidType(A,1);
11059   PetscValidPointer(graph,3);
11060   PetscCheck(A->ops->creategraph,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for this operation for this matrix type");
11061   PetscCall((*A->ops->creategraph)(A,sym,scale,graph));
11062   PetscFunctionReturn(0);
11063 }
11064 
11065 /*C
11066    MatFilter - filters a Mat values with an absolut value equal to or below a give threshold
11067 
11068    Collective on mat
11069 
11070    Input Parameter:
11071 .  value - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries <= value
11072 
11073    Input/Output Parameter:
11074 .  A - the Mat to filter in place
11075 
11076    Level: advanced
11077 
11078    Notes:
11079 
11080 .seealso: `MatCreate()`, `MatCreateGraph()`
11081 */
11082 PETSC_EXTERN PetscErrorCode MatFilter(Mat G,PetscReal value,Mat *F)
11083 {
11084   PetscFunctionBegin;
11085   PetscValidHeaderSpecific(G,MAT_CLASSID,1);
11086   PetscValidType(G,1);
11087   PetscValidPointer(F,3);
11088   if (value >= 0.0) {
11089     PetscCheck(G->ops->filter,PetscObjectComm((PetscObject)G),PETSC_ERR_SUP,"No support for this operation for this matrix type");
11090     PetscCall((G->ops->filter)(G,value,F));
11091   }
11092   PetscFunctionReturn(0);
11093 }
11094