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