xref: /petsc/src/mat/interface/matrix.c (revision fdf6c4e30aafdbc795e4f76379caa977fd5cdf5a)
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 causes the B matrix from a previous call to this function with MAT_INITIAL_MATRIX to be used
5144 
5145      Consider using MatCreateTranspose() instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5146 
5147    Level: intermediate
5148 
5149 .seealso: `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5150 @*/
5151 PetscErrorCode MatTranspose(Mat mat,MatReuse reuse,Mat *B)
5152 {
5153   PetscFunctionBegin;
5154   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5155   PetscValidType(mat,1);
5156   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5157   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5158   PetscCheck(mat->ops->transpose,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5159   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires last matrix to match first");
5160   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Perhaps you mean MAT_INPLACE_MATRIX");
5161   MatCheckPreallocated(mat,1);
5162 
5163   PetscCall(PetscLogEventBegin(MAT_Transpose,mat,0,0,0));
5164   PetscCall((*mat->ops->transpose)(mat,reuse,B));
5165   PetscCall(PetscLogEventEnd(MAT_Transpose,mat,0,0,0));
5166   if (B) PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5167   PetscFunctionReturn(0);
5168 }
5169 
5170 /*@
5171    MatIsTranspose - Test whether a matrix is another one's transpose,
5172         or its own, in which case it tests symmetry.
5173 
5174    Collective on Mat
5175 
5176    Input Parameters:
5177 +  A - the matrix to test
5178 -  B - the matrix to test against, this can equal the first parameter
5179 
5180    Output Parameters:
5181 .  flg - the result
5182 
5183    Notes:
5184    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5185    has a running time of the order of the number of nonzeros; the parallel
5186    test involves parallel copies of the block-offdiagonal parts of the matrix.
5187 
5188    Level: intermediate
5189 
5190 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5191 @*/
5192 PetscErrorCode MatIsTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5193 {
5194   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5195 
5196   PetscFunctionBegin;
5197   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5198   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5199   PetscValidBoolPointer(flg,4);
5200   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsTranspose_C",&f));
5201   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsTranspose_C",&g));
5202   *flg = PETSC_FALSE;
5203   if (f && g) {
5204     PetscCheck(f == g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for symmetry test");
5205     PetscCall((*f)(A,B,tol,flg));
5206   } else {
5207     MatType mattype;
5208 
5209     PetscCall(MatGetType(f ? B : A,&mattype));
5210     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for transpose",mattype);
5211   }
5212   PetscFunctionReturn(0);
5213 }
5214 
5215 /*@
5216    MatHermitianTranspose - Computes an in-place or out-of-place transpose of a matrix in complex conjugate.
5217 
5218    Collective on Mat
5219 
5220    Input Parameters:
5221 +  mat - the matrix to transpose and complex conjugate
5222 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5223 
5224    Output Parameter:
5225 .  B - the Hermitian
5226 
5227    Level: intermediate
5228 
5229 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5230 @*/
5231 PetscErrorCode MatHermitianTranspose(Mat mat,MatReuse reuse,Mat *B)
5232 {
5233   PetscFunctionBegin;
5234   PetscCall(MatTranspose(mat,reuse,B));
5235 #if defined(PETSC_USE_COMPLEX)
5236   PetscCall(MatConjugate(*B));
5237 #endif
5238   PetscFunctionReturn(0);
5239 }
5240 
5241 /*@
5242    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5243 
5244    Collective on Mat
5245 
5246    Input Parameters:
5247 +  A - the matrix to test
5248 -  B - the matrix to test against, this can equal the first parameter
5249 
5250    Output Parameters:
5251 .  flg - the result
5252 
5253    Notes:
5254    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5255    has a running time of the order of the number of nonzeros; the parallel
5256    test involves parallel copies of the block-offdiagonal parts of the matrix.
5257 
5258    Level: intermediate
5259 
5260 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5261 @*/
5262 PetscErrorCode MatIsHermitianTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5263 {
5264   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5265 
5266   PetscFunctionBegin;
5267   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5268   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5269   PetscValidBoolPointer(flg,4);
5270   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsHermitianTranspose_C",&f));
5271   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsHermitianTranspose_C",&g));
5272   if (f && g) {
5273     PetscCheck(f != g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for Hermitian test");
5274     PetscCall((*f)(A,B,tol,flg));
5275   }
5276   PetscFunctionReturn(0);
5277 }
5278 
5279 /*@
5280    MatPermute - Creates a new matrix with rows and columns permuted from the
5281    original.
5282 
5283    Collective on Mat
5284 
5285    Input Parameters:
5286 +  mat - the matrix to permute
5287 .  row - row permutation, each processor supplies only the permutation for its rows
5288 -  col - column permutation, each processor supplies only the permutation for its columns
5289 
5290    Output Parameters:
5291 .  B - the permuted matrix
5292 
5293    Level: advanced
5294 
5295    Note:
5296    The index sets map from row/col of permuted matrix to row/col of original matrix.
5297    The index sets should be on the same communicator as Mat and have the same local sizes.
5298 
5299    Developer Note:
5300      If you want to implement MatPermute for a matrix type, and your approach doesn't
5301      exploit the fact that row and col are permutations, consider implementing the
5302      more general MatCreateSubMatrix() instead.
5303 
5304 .seealso: `MatGetOrdering()`, `ISAllGather()`
5305 
5306 @*/
5307 PetscErrorCode MatPermute(Mat mat,IS row,IS col,Mat *B)
5308 {
5309   PetscFunctionBegin;
5310   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5311   PetscValidType(mat,1);
5312   PetscValidHeaderSpecific(row,IS_CLASSID,2);
5313   PetscValidHeaderSpecific(col,IS_CLASSID,3);
5314   PetscValidPointer(B,4);
5315   PetscCheckSameComm(mat,1,row,2);
5316   if (row != col) PetscCheckSameComm(row,2,col,3);
5317   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5318   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5319   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatPermute not available for Mat type %s",((PetscObject)mat)->type_name);
5320   MatCheckPreallocated(mat,1);
5321 
5322   if (mat->ops->permute) {
5323     PetscCall((*mat->ops->permute)(mat,row,col,B));
5324     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5325   } else {
5326     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5327   }
5328   PetscFunctionReturn(0);
5329 }
5330 
5331 /*@
5332    MatEqual - Compares two matrices.
5333 
5334    Collective on Mat
5335 
5336    Input Parameters:
5337 +  A - the first matrix
5338 -  B - the second matrix
5339 
5340    Output Parameter:
5341 .  flg - PETSC_TRUE if the matrices are equal; PETSC_FALSE otherwise.
5342 
5343    Level: intermediate
5344 
5345 @*/
5346 PetscErrorCode MatEqual(Mat A,Mat B,PetscBool *flg)
5347 {
5348   PetscFunctionBegin;
5349   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5350   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5351   PetscValidType(A,1);
5352   PetscValidType(B,2);
5353   PetscValidBoolPointer(flg,3);
5354   PetscCheckSameComm(A,1,B,2);
5355   MatCheckPreallocated(A,1);
5356   MatCheckPreallocated(B,2);
5357   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5358   PetscCheck(B->assembled,PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5359   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);
5360   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5361     PetscCall((*A->ops->equal)(A,B,flg));
5362   } else {
5363     PetscCall(MatMultEqual(A,B,10,flg));
5364   }
5365   PetscFunctionReturn(0);
5366 }
5367 
5368 /*@
5369    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5370    matrices that are stored as vectors.  Either of the two scaling
5371    matrices can be NULL.
5372 
5373    Collective on Mat
5374 
5375    Input Parameters:
5376 +  mat - the matrix to be scaled
5377 .  l - the left scaling vector (or NULL)
5378 -  r - the right scaling vector (or NULL)
5379 
5380    Notes:
5381    MatDiagonalScale() computes A = LAR, where
5382    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5383    The L scales the rows of the matrix, the R scales the columns of the matrix.
5384 
5385    Level: intermediate
5386 
5387 .seealso: `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5388 @*/
5389 PetscErrorCode MatDiagonalScale(Mat mat,Vec l,Vec r)
5390 {
5391   PetscFunctionBegin;
5392   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5393   PetscValidType(mat,1);
5394   if (l) {PetscValidHeaderSpecific(l,VEC_CLASSID,2);PetscCheckSameComm(mat,1,l,2);}
5395   if (r) {PetscValidHeaderSpecific(r,VEC_CLASSID,3);PetscCheckSameComm(mat,1,r,3);}
5396   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5397   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5398   MatCheckPreallocated(mat,1);
5399   if (!l && !r) PetscFunctionReturn(0);
5400 
5401   PetscCheck(mat->ops->diagonalscale,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5402   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5403   PetscCall((*mat->ops->diagonalscale)(mat,l,r));
5404   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5405   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5406   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5407   PetscFunctionReturn(0);
5408 }
5409 
5410 /*@
5411     MatScale - Scales all elements of a matrix by a given number.
5412 
5413     Logically Collective on Mat
5414 
5415     Input Parameters:
5416 +   mat - the matrix to be scaled
5417 -   a  - the scaling value
5418 
5419     Output Parameter:
5420 .   mat - the scaled matrix
5421 
5422     Level: intermediate
5423 
5424 .seealso: `MatDiagonalScale()`
5425 @*/
5426 PetscErrorCode MatScale(Mat mat,PetscScalar a)
5427 {
5428   PetscFunctionBegin;
5429   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5430   PetscValidType(mat,1);
5431   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5432   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5433   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5434   PetscValidLogicalCollectiveScalar(mat,a,2);
5435   MatCheckPreallocated(mat,1);
5436 
5437   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5438   if (a != (PetscScalar)1.0) {
5439     PetscCall((*mat->ops->scale)(mat,a));
5440     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5441   }
5442   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5443   PetscFunctionReturn(0);
5444 }
5445 
5446 /*@
5447    MatNorm - Calculates various norms of a matrix.
5448 
5449    Collective on Mat
5450 
5451    Input Parameters:
5452 +  mat - the matrix
5453 -  type - the type of norm, NORM_1, NORM_FROBENIUS, NORM_INFINITY
5454 
5455    Output Parameter:
5456 .  nrm - the resulting norm
5457 
5458    Level: intermediate
5459 
5460 @*/
5461 PetscErrorCode MatNorm(Mat mat,NormType type,PetscReal *nrm)
5462 {
5463   PetscFunctionBegin;
5464   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5465   PetscValidType(mat,1);
5466   PetscValidRealPointer(nrm,3);
5467 
5468   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5469   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5470   PetscCheck(mat->ops->norm,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5471   MatCheckPreallocated(mat,1);
5472 
5473   PetscCall((*mat->ops->norm)(mat,type,nrm));
5474   PetscFunctionReturn(0);
5475 }
5476 
5477 /*
5478      This variable is used to prevent counting of MatAssemblyBegin() that
5479    are called from within a MatAssemblyEnd().
5480 */
5481 static PetscInt MatAssemblyEnd_InUse = 0;
5482 /*@
5483    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5484    be called after completing all calls to MatSetValues().
5485 
5486    Collective on Mat
5487 
5488    Input Parameters:
5489 +  mat - the matrix
5490 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5491 
5492    Notes:
5493    MatSetValues() generally caches the values.  The matrix is ready to
5494    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5495    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5496    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5497    using the matrix.
5498 
5499    ALL processes that share a matrix MUST call MatAssemblyBegin() and MatAssemblyEnd() the SAME NUMBER of times, and each time with the
5500    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
5501    a global collective operation requring all processes that share the matrix.
5502 
5503    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5504    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5505    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5506 
5507    Level: beginner
5508 
5509 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5510 @*/
5511 PetscErrorCode MatAssemblyBegin(Mat mat,MatAssemblyType type)
5512 {
5513   PetscFunctionBegin;
5514   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5515   PetscValidType(mat,1);
5516   MatCheckPreallocated(mat,1);
5517   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5518   if (mat->assembled) {
5519     mat->was_assembled = PETSC_TRUE;
5520     mat->assembled     = PETSC_FALSE;
5521   }
5522 
5523   if (!MatAssemblyEnd_InUse) {
5524     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin,mat,0,0,0));
5525     if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5526     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin,mat,0,0,0));
5527   } else if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5528   PetscFunctionReturn(0);
5529 }
5530 
5531 /*@
5532    MatAssembled - Indicates if a matrix has been assembled and is ready for
5533      use; for example, in matrix-vector product.
5534 
5535    Not Collective
5536 
5537    Input Parameter:
5538 .  mat - the matrix
5539 
5540    Output Parameter:
5541 .  assembled - PETSC_TRUE or PETSC_FALSE
5542 
5543    Level: advanced
5544 
5545 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5546 @*/
5547 PetscErrorCode MatAssembled(Mat mat,PetscBool *assembled)
5548 {
5549   PetscFunctionBegin;
5550   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5551   PetscValidBoolPointer(assembled,2);
5552   *assembled = mat->assembled;
5553   PetscFunctionReturn(0);
5554 }
5555 
5556 /*@
5557    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5558    be called after MatAssemblyBegin().
5559 
5560    Collective on Mat
5561 
5562    Input Parameters:
5563 +  mat - the matrix
5564 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5565 
5566    Options Database Keys:
5567 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatEndAssembly()
5568 .  -mat_view ::ascii_info_detail - Prints more detailed info
5569 .  -mat_view - Prints matrix in ASCII format
5570 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5571 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
5572 .  -display <name> - Sets display name (default is host)
5573 .  -draw_pause <sec> - Sets number of seconds to pause after display
5574 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab)
5575 .  -viewer_socket_machine <machine> - Machine to use for socket
5576 .  -viewer_socket_port <port> - Port number to use for socket
5577 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5578 
5579    Notes:
5580    MatSetValues() generally caches the values.  The matrix is ready to
5581    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5582    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5583    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5584    using the matrix.
5585 
5586    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5587    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5588    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5589 
5590    Level: beginner
5591 
5592 .seealso: `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5593 @*/
5594 PetscErrorCode MatAssemblyEnd(Mat mat,MatAssemblyType type)
5595 {
5596   static PetscInt inassm = 0;
5597   PetscBool       flg    = PETSC_FALSE;
5598 
5599   PetscFunctionBegin;
5600   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5601   PetscValidType(mat,1);
5602 
5603   inassm++;
5604   MatAssemblyEnd_InUse++;
5605   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5606     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd,mat,0,0,0));
5607     if (mat->ops->assemblyend) PetscCall((*mat->ops->assemblyend)(mat,type));
5608     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd,mat,0,0,0));
5609   } else if (mat->ops->assemblyend) PetscCall((*mat->ops->assemblyend)(mat,type));
5610 
5611   /* Flush assembly is not a true assembly */
5612   if (type != MAT_FLUSH_ASSEMBLY) {
5613     if (mat->num_ass) {
5614       if (!mat->symmetry_eternal) {
5615         mat->symmetric              = PETSC_BOOL3_UNKNOWN;
5616         mat->hermitian              = PETSC_BOOL3_UNKNOWN;
5617       }
5618       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) {
5619         mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5620       }
5621       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5622     }
5623     mat->num_ass++;
5624     mat->assembled        = PETSC_TRUE;
5625     mat->ass_nonzerostate = mat->nonzerostate;
5626   }
5627 
5628   mat->insertmode = NOT_SET_VALUES;
5629   MatAssemblyEnd_InUse--;
5630   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5631   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5632     PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5633 
5634     if (mat->checksymmetryonassembly) {
5635       PetscCall(MatIsSymmetric(mat,mat->checksymmetrytol,&flg));
5636       if (flg) {
5637         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5638       } else {
5639         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is not symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5640       }
5641     }
5642     if (mat->nullsp && mat->checknullspaceonassembly) {
5643       PetscCall(MatNullSpaceTest(mat->nullsp,mat,NULL));
5644     }
5645   }
5646   inassm--;
5647   PetscFunctionReturn(0);
5648 }
5649 
5650 /*@
5651    MatSetOption - Sets a parameter option for a matrix. Some options
5652    may be specific to certain storage formats.  Some options
5653    determine how values will be inserted (or added). Sorted,
5654    row-oriented input will generally assemble the fastest. The default
5655    is row-oriented.
5656 
5657    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5658 
5659    Input Parameters:
5660 +  mat - the matrix
5661 .  option - the option, one of those listed below (and possibly others),
5662 -  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5663 
5664   Options Describing Matrix Structure:
5665 +    MAT_SPD - symmetric positive definite
5666 .    MAT_SYMMETRIC - symmetric in terms of both structure and value
5667 .    MAT_HERMITIAN - transpose is the complex conjugation
5668 .    MAT_STRUCTURALLY_SYMMETRIC - symmetric nonzero structure
5669 -    MAT_SYMMETRY_ETERNAL - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5670 -    MAT_STRUCTURAL_SYMMETRY_ETERNAL - indicates the structural symmetry or its absence will persist through any changes to the matrix
5671 
5672    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5673    do not need to be computed (usually at a high cost)
5674 
5675    Options For Use with MatSetValues():
5676    Insert a logically dense subblock, which can be
5677 .    MAT_ROW_ORIENTED - row-oriented (default)
5678 
5679    Note these options reflect the data you pass in with MatSetValues(); it has
5680    nothing to do with how the data is stored internally in the matrix
5681    data structure.
5682 
5683    When (re)assembling a matrix, we can restrict the input for
5684    efficiency/debugging purposes.  These options include
5685 +    MAT_NEW_NONZERO_LOCATIONS - additional insertions will be allowed if they generate a new nonzero (slow)
5686 .    MAT_FORCE_DIAGONAL_ENTRIES - forces diagonal entries to be allocated
5687 .    MAT_IGNORE_OFF_PROC_ENTRIES - drops off-processor entries
5688 .    MAT_NEW_NONZERO_LOCATION_ERR - generates an error for new matrix entry
5689 .    MAT_USE_HASH_TABLE - uses a hash table to speed up matrix assembly
5690 .    MAT_NO_OFF_PROC_ENTRIES - you know each process will only set values for its own rows, will generate an error if
5691         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5692         performance for very large process counts.
5693 -    MAT_SUBSET_OFF_PROC_ENTRIES - you know that the first assembly after setting this flag will set a superset
5694         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5695         functions, instead sending only neighbor messages.
5696 
5697    Notes:
5698    Except for MAT_UNUSED_NONZERO_LOCATION_ERR and  MAT_ROW_ORIENTED all processes that share the matrix must pass the same value in flg!
5699 
5700    Some options are relevant only for particular matrix types and
5701    are thus ignored by others.  Other options are not supported by
5702    certain matrix types and will generate an error message if set.
5703 
5704    If using a Fortran 77 module to compute a matrix, one may need to
5705    use the column-oriented option (or convert to the row-oriented
5706    format).
5707 
5708    MAT_NEW_NONZERO_LOCATIONS set to PETSC_FALSE indicates that any add or insertion
5709    that would generate a new entry in the nonzero structure is instead
5710    ignored.  Thus, if memory has not alredy been allocated for this particular
5711    data, then the insertion is ignored. For dense matrices, in which
5712    the entire array is allocated, no entries are ever ignored.
5713    Set after the first MatAssemblyEnd(). If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5714 
5715    MAT_NEW_NONZERO_LOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5716    that would generate a new entry in the nonzero structure instead produces
5717    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
5718 
5719    MAT_NEW_NONZERO_ALLOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5720    that would generate a new entry that has not been preallocated will
5721    instead produce an error. (Currently supported for AIJ and BAIJ formats
5722    only.) This is a useful flag when debugging matrix memory preallocation.
5723    If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5724 
5725    MAT_IGNORE_OFF_PROC_ENTRIES set to PETSC_TRUE indicates entries destined for
5726    other processors should be dropped, rather than stashed.
5727    This is useful if you know that the "owning" processor is also
5728    always generating the correct matrix entries, so that PETSc need
5729    not transfer duplicate entries generated on another processor.
5730 
5731    MAT_USE_HASH_TABLE indicates that a hash table be used to improve the
5732    searches during matrix assembly. When this flag is set, the hash table
5733    is created during the first Matrix Assembly. This hash table is
5734    used the next time through, during MatSetVaules()/MatSetVaulesBlocked()
5735    to improve the searching of indices. MAT_NEW_NONZERO_LOCATIONS flag
5736    should be used with MAT_USE_HASH_TABLE flag. This option is currently
5737    supported by MATMPIBAIJ format only.
5738 
5739    MAT_KEEP_NONZERO_PATTERN indicates when MatZeroRows() is called the zeroed entries
5740    are kept in the nonzero structure
5741 
5742    MAT_IGNORE_ZERO_ENTRIES - for AIJ/IS matrices this will stop zero values from creating
5743    a zero location in the matrix
5744 
5745    MAT_USE_INODES - indicates using inode version of the code - works with AIJ matrix types
5746 
5747    MAT_NO_OFF_PROC_ZERO_ROWS - you know each process will only zero its own rows. This avoids all reductions in the
5748         zero row routines and thus improves performance for very large process counts.
5749 
5750    MAT_IGNORE_LOWER_TRIANGULAR - For SBAIJ matrices will ignore any insertions you make in the lower triangular
5751         part of the matrix (since they should match the upper triangular part).
5752 
5753    MAT_SORTED_FULL - each process provides exactly its local rows; all column indices for a given row are passed in a
5754                      single call to MatSetValues(), preallocation is perfect, row oriented, INSERT_VALUES is used. Common
5755                      with finite difference schemes with non-periodic boundary conditions.
5756 
5757    Level: intermediate
5758 
5759 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5760 
5761 @*/
5762 PetscErrorCode MatSetOption(Mat mat,MatOption op,PetscBool flg)
5763 {
5764   PetscFunctionBegin;
5765   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5766   if (op > 0) {
5767     PetscValidLogicalCollectiveEnum(mat,op,2);
5768     PetscValidLogicalCollectiveBool(mat,flg,3);
5769   }
5770 
5771   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);
5772 
5773   switch (op) {
5774   case MAT_FORCE_DIAGONAL_ENTRIES:
5775     mat->force_diagonals = flg;
5776     PetscFunctionReturn(0);
5777   case MAT_NO_OFF_PROC_ENTRIES:
5778     mat->nooffprocentries = flg;
5779     PetscFunctionReturn(0);
5780   case MAT_SUBSET_OFF_PROC_ENTRIES:
5781     mat->assembly_subset = flg;
5782     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5783 #if !defined(PETSC_HAVE_MPIUNI)
5784       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5785 #endif
5786       mat->stash.first_assembly_done = PETSC_FALSE;
5787     }
5788     PetscFunctionReturn(0);
5789   case MAT_NO_OFF_PROC_ZERO_ROWS:
5790     mat->nooffproczerorows = flg;
5791     PetscFunctionReturn(0);
5792   case MAT_SPD:
5793     if (flg) {
5794       mat->spd                     = PETSC_BOOL3_TRUE;
5795       mat->symmetric               = PETSC_BOOL3_TRUE;
5796       mat->structurally_symmetric  = PETSC_BOOL3_TRUE;
5797     } else {
5798       mat->spd = PETSC_BOOL3_FALSE;
5799     }
5800     break;
5801   case MAT_SYMMETRIC:
5802     mat->symmetric                       = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5803     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5804 #if !defined(PETSC_USE_COMPLEX)
5805     mat->hermitian                       = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5806 #endif
5807     break;
5808   case MAT_HERMITIAN:
5809     mat->hermitian                       = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5810     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5811 #if !defined(PETSC_USE_COMPLEX)
5812     mat->symmetric                       = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5813 #endif
5814     break;
5815   case MAT_STRUCTURALLY_SYMMETRIC:
5816     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5817     break;
5818   case MAT_SYMMETRY_ETERNAL:
5819     mat->symmetry_eternal = flg ? PETSC_TRUE : PETSC_FALSE;
5820     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5821     break;
5822   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5823     mat->structural_symmetry_eternal = flg;
5824     break;
5825   case MAT_SPD_ETERNAL:
5826     mat->spd_eternal = flg;
5827     if (flg) {
5828       mat->structural_symmetry_eternal = PETSC_TRUE;
5829       mat->symmetry_eternal            = PETSC_TRUE;
5830     }
5831     break;
5832   case MAT_STRUCTURE_ONLY:
5833     mat->structure_only = flg;
5834     break;
5835   case MAT_SORTED_FULL:
5836     mat->sortedfull = flg;
5837     break;
5838   default:
5839     break;
5840   }
5841   if (mat->ops->setoption) PetscCall((*mat->ops->setoption)(mat,op,flg));
5842   PetscFunctionReturn(0);
5843 }
5844 
5845 /*@
5846    MatGetOption - Gets a parameter option that has been set for a matrix.
5847 
5848    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5849 
5850    Input Parameters:
5851 +  mat - the matrix
5852 -  option - the option, this only responds to certain options, check the code for which ones
5853 
5854    Output Parameter:
5855 .  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5856 
5857     Notes:
5858     Can only be called after MatSetSizes() and MatSetType() have been set.
5859 
5860     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`, or
5861     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5862 
5863    Level: intermediate
5864 
5865 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`,
5866     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5867 
5868 @*/
5869 PetscErrorCode MatGetOption(Mat mat,MatOption op,PetscBool *flg)
5870 {
5871   PetscFunctionBegin;
5872   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5873   PetscValidType(mat,1);
5874 
5875   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);
5876   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()");
5877 
5878   switch (op) {
5879   case MAT_NO_OFF_PROC_ENTRIES:
5880     *flg = mat->nooffprocentries;
5881     break;
5882   case MAT_NO_OFF_PROC_ZERO_ROWS:
5883     *flg = mat->nooffproczerorows;
5884     break;
5885   case MAT_SYMMETRIC:
5886     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Use MatIsSymmetric() or MatIsSymmetricKnown()");
5887     break;
5888   case MAT_HERMITIAN:
5889     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Use MatIsHermitian() or MatIsHermitianKnown()");
5890     break;
5891   case MAT_STRUCTURALLY_SYMMETRIC:
5892     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5893     break;
5894   case MAT_SPD:
5895     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Use MatIsSPDKnown()");
5896     break;
5897   case MAT_SYMMETRY_ETERNAL:
5898     *flg = mat->symmetry_eternal;
5899     break;
5900   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5901     *flg = mat->symmetry_eternal;
5902     break;
5903   default:
5904     break;
5905   }
5906   PetscFunctionReturn(0);
5907 }
5908 
5909 /*@
5910    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5911    this routine retains the old nonzero structure.
5912 
5913    Logically Collective on Mat
5914 
5915    Input Parameters:
5916 .  mat - the matrix
5917 
5918    Level: intermediate
5919 
5920    Notes:
5921     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.
5922    See the Performance chapter of the users manual for information on preallocating matrices.
5923 
5924 .seealso: `MatZeroRows()`
5925 @*/
5926 PetscErrorCode MatZeroEntries(Mat mat)
5927 {
5928   PetscFunctionBegin;
5929   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5930   PetscValidType(mat,1);
5931   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5932   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");
5933   PetscCheck(mat->ops->zeroentries,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5934   MatCheckPreallocated(mat,1);
5935 
5936   PetscCall(PetscLogEventBegin(MAT_ZeroEntries,mat,0,0,0));
5937   PetscCall((*mat->ops->zeroentries)(mat));
5938   PetscCall(PetscLogEventEnd(MAT_ZeroEntries,mat,0,0,0));
5939   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5940   PetscFunctionReturn(0);
5941 }
5942 
5943 /*@
5944    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5945    of a set of rows and columns of a matrix.
5946 
5947    Collective on Mat
5948 
5949    Input Parameters:
5950 +  mat - the matrix
5951 .  numRows - the number of rows to remove
5952 .  rows - the global row indices
5953 .  diag - value put in the diagonal of the eliminated rows
5954 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5955 -  b - optional vector of right hand side, that will be adjusted by provided solution
5956 
5957    Notes:
5958    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5959 
5960    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5961    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
5962 
5963    If the resulting linear system is to be solved with KSP then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5964    Krylov method to take advantage of the known solution on the zeroed rows.
5965 
5966    For the parallel case, all processes that share the matrix (i.e.,
5967    those in the communicator used for matrix creation) MUST call this
5968    routine, regardless of whether any rows being zeroed are owned by
5969    them.
5970 
5971    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5972 
5973    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5974    list only rows local to itself).
5975 
5976    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
5977 
5978    Level: intermediate
5979 
5980 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5981           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5982 @*/
5983 PetscErrorCode MatZeroRowsColumns(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
5984 {
5985   PetscFunctionBegin;
5986   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5987   PetscValidType(mat,1);
5988   if (numRows) PetscValidIntPointer(rows,3);
5989   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5990   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5991   PetscCheck(mat->ops->zerorowscolumns,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5992   MatCheckPreallocated(mat,1);
5993 
5994   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,rows,diag,x,b));
5995   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5996   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5997   PetscFunctionReturn(0);
5998 }
5999 
6000 /*@
6001    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6002    of a set of rows and columns of a matrix.
6003 
6004    Collective on Mat
6005 
6006    Input Parameters:
6007 +  mat - the matrix
6008 .  is - the rows to zero
6009 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6010 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6011 -  b - optional vector of right hand side, that will be adjusted by provided solution
6012 
6013    Note:
6014    See `MatZeroRowsColumns()` for details on how this routine operates.
6015 
6016    Level: intermediate
6017 
6018 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6019           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6020 @*/
6021 PetscErrorCode MatZeroRowsColumnsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6022 {
6023   PetscInt       numRows;
6024   const PetscInt *rows;
6025 
6026   PetscFunctionBegin;
6027   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6028   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6029   PetscValidType(mat,1);
6030   PetscValidType(is,2);
6031   PetscCall(ISGetLocalSize(is,&numRows));
6032   PetscCall(ISGetIndices(is,&rows));
6033   PetscCall(MatZeroRowsColumns(mat,numRows,rows,diag,x,b));
6034   PetscCall(ISRestoreIndices(is,&rows));
6035   PetscFunctionReturn(0);
6036 }
6037 
6038 /*@
6039    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6040    of a set of rows of a matrix.
6041 
6042    Collective on Mat
6043 
6044    Input Parameters:
6045 +  mat - the matrix
6046 .  numRows - the number of rows to remove
6047 .  rows - the global row indices
6048 .  diag - value put in the diagonal of the eliminated rows
6049 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6050 -  b - optional vector of right hand side, that will be adjusted by provided solution
6051 
6052    Notes:
6053    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6054 
6055    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6056 
6057    If the resulting linear system is to be solved with KSP then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6058    Krylov method to take advantage of the known solution on the zeroed rows.
6059 
6060    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)
6061    from the matrix.
6062 
6063    Unlike `MatZeroRowsColumns()` for the AIJ and BAIJ matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6064    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
6065    formats this does not alter the nonzero structure.
6066 
6067    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6068    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6069    merely zeroed.
6070 
6071    The user can set a value in the diagonal entry (or for the AIJ and
6072    row formats can optionally remove the main diagonal entry from the
6073    nonzero structure as well, by passing 0.0 as the final argument).
6074 
6075    For the parallel case, all processes that share the matrix (i.e.,
6076    those in the communicator used for matrix creation) MUST call this
6077    routine, regardless of whether any rows being zeroed are owned by
6078    them.
6079 
6080    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6081    list only rows local to itself).
6082 
6083    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6084    owns that are to be zeroed. This saves a global synchronization in the implementation.
6085 
6086    Level: intermediate
6087 
6088 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6089           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6090 @*/
6091 PetscErrorCode MatZeroRows(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6092 {
6093   PetscFunctionBegin;
6094   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6095   PetscValidType(mat,1);
6096   if (numRows) PetscValidIntPointer(rows,3);
6097   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6098   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6099   PetscCheck(mat->ops->zerorows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6100   MatCheckPreallocated(mat,1);
6101 
6102   PetscCall((*mat->ops->zerorows)(mat,numRows,rows,diag,x,b));
6103   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
6104   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6105   PetscFunctionReturn(0);
6106 }
6107 
6108 /*@
6109    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6110    of a set of rows of a matrix.
6111 
6112    Collective on Mat
6113 
6114    Input Parameters:
6115 +  mat - the matrix
6116 .  is - index set of rows to remove (if NULL then no row is removed)
6117 .  diag - value put in all diagonals of eliminated rows
6118 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6119 -  b - optional vector of right hand side, that will be adjusted by provided solution
6120 
6121    Note:
6122    See `MatZeroRows()` for details on how this routine operates.
6123 
6124    Level: intermediate
6125 
6126 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6127           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6128 @*/
6129 PetscErrorCode MatZeroRowsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6130 {
6131   PetscInt       numRows = 0;
6132   const PetscInt *rows = NULL;
6133 
6134   PetscFunctionBegin;
6135   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6136   PetscValidType(mat,1);
6137   if (is) {
6138     PetscValidHeaderSpecific(is,IS_CLASSID,2);
6139     PetscCall(ISGetLocalSize(is,&numRows));
6140     PetscCall(ISGetIndices(is,&rows));
6141   }
6142   PetscCall(MatZeroRows(mat,numRows,rows,diag,x,b));
6143   if (is) {
6144     PetscCall(ISRestoreIndices(is,&rows));
6145   }
6146   PetscFunctionReturn(0);
6147 }
6148 
6149 /*@
6150    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6151    of a set of rows of a matrix. These rows must be local to the process.
6152 
6153    Collective on Mat
6154 
6155    Input Parameters:
6156 +  mat - the matrix
6157 .  numRows - the number of rows to remove
6158 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6159 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6160 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6161 -  b - optional vector of right hand side, that will be adjusted by provided solution
6162 
6163    Notes:
6164    See `MatZeroRows()` for details on how this routine operates.
6165 
6166    The grid coordinates are across the entire grid, not just the local portion
6167 
6168    In Fortran idxm and idxn should be declared as
6169 $     MatStencil idxm(4,m)
6170    and the values inserted using
6171 $    idxm(MatStencil_i,1) = i
6172 $    idxm(MatStencil_j,1) = j
6173 $    idxm(MatStencil_k,1) = k
6174 $    idxm(MatStencil_c,1) = c
6175    etc
6176 
6177    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6178    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6179    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6180    DM_BOUNDARY_PERIODIC boundary type.
6181 
6182    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
6183    a single value per point) you can skip filling those indices.
6184 
6185    Level: intermediate
6186 
6187 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6188           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6189 @*/
6190 PetscErrorCode MatZeroRowsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6191 {
6192   PetscInt       dim     = mat->stencil.dim;
6193   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6194   PetscInt       *dims   = mat->stencil.dims+1;
6195   PetscInt       *starts = mat->stencil.starts;
6196   PetscInt       *dxm    = (PetscInt*) rows;
6197   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6198 
6199   PetscFunctionBegin;
6200   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6201   PetscValidType(mat,1);
6202   if (numRows) PetscValidPointer(rows,3);
6203 
6204   PetscCall(PetscMalloc1(numRows, &jdxm));
6205   for (i = 0; i < numRows; ++i) {
6206     /* Skip unused dimensions (they are ordered k, j, i, c) */
6207     for (j = 0; j < 3-sdim; ++j) dxm++;
6208     /* Local index in X dir */
6209     tmp = *dxm++ - starts[0];
6210     /* Loop over remaining dimensions */
6211     for (j = 0; j < dim-1; ++j) {
6212       /* If nonlocal, set index to be negative */
6213       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6214       /* Update local index */
6215       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6216     }
6217     /* Skip component slot if necessary */
6218     if (mat->stencil.noc) dxm++;
6219     /* Local row number */
6220     if (tmp >= 0) {
6221       jdxm[numNewRows++] = tmp;
6222     }
6223   }
6224   PetscCall(MatZeroRowsLocal(mat,numNewRows,jdxm,diag,x,b));
6225   PetscCall(PetscFree(jdxm));
6226   PetscFunctionReturn(0);
6227 }
6228 
6229 /*@
6230    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6231    of a set of rows and columns of a matrix.
6232 
6233    Collective on Mat
6234 
6235    Input Parameters:
6236 +  mat - the matrix
6237 .  numRows - the number of rows/columns to remove
6238 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6239 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6240 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6241 -  b - optional vector of right hand side, that will be adjusted by provided solution
6242 
6243    Notes:
6244    See `MatZeroRowsColumns()` for details on how this routine operates.
6245 
6246    The grid coordinates are across the entire grid, not just the local portion
6247 
6248    In Fortran idxm and idxn should be declared as
6249 $     MatStencil idxm(4,m)
6250    and the values inserted using
6251 $    idxm(MatStencil_i,1) = i
6252 $    idxm(MatStencil_j,1) = j
6253 $    idxm(MatStencil_k,1) = k
6254 $    idxm(MatStencil_c,1) = c
6255    etc
6256 
6257    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6258    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6259    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6260    DM_BOUNDARY_PERIODIC boundary type.
6261 
6262    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
6263    a single value per point) you can skip filling those indices.
6264 
6265    Level: intermediate
6266 
6267 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6268           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6269 @*/
6270 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6271 {
6272   PetscInt       dim     = mat->stencil.dim;
6273   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6274   PetscInt       *dims   = mat->stencil.dims+1;
6275   PetscInt       *starts = mat->stencil.starts;
6276   PetscInt       *dxm    = (PetscInt*) rows;
6277   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6278 
6279   PetscFunctionBegin;
6280   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6281   PetscValidType(mat,1);
6282   if (numRows) PetscValidPointer(rows,3);
6283 
6284   PetscCall(PetscMalloc1(numRows, &jdxm));
6285   for (i = 0; i < numRows; ++i) {
6286     /* Skip unused dimensions (they are ordered k, j, i, c) */
6287     for (j = 0; j < 3-sdim; ++j) dxm++;
6288     /* Local index in X dir */
6289     tmp = *dxm++ - starts[0];
6290     /* Loop over remaining dimensions */
6291     for (j = 0; j < dim-1; ++j) {
6292       /* If nonlocal, set index to be negative */
6293       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6294       /* Update local index */
6295       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6296     }
6297     /* Skip component slot if necessary */
6298     if (mat->stencil.noc) dxm++;
6299     /* Local row number */
6300     if (tmp >= 0) {
6301       jdxm[numNewRows++] = tmp;
6302     }
6303   }
6304   PetscCall(MatZeroRowsColumnsLocal(mat,numNewRows,jdxm,diag,x,b));
6305   PetscCall(PetscFree(jdxm));
6306   PetscFunctionReturn(0);
6307 }
6308 
6309 /*@C
6310    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6311    of a set of rows of a matrix; using local numbering of rows.
6312 
6313    Collective on Mat
6314 
6315    Input Parameters:
6316 +  mat - the matrix
6317 .  numRows - the number of rows to remove
6318 .  rows - the local row indices
6319 .  diag - value put in all diagonals of eliminated rows
6320 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6321 -  b - optional vector of right hand side, that will be adjusted by provided solution
6322 
6323    Notes:
6324    Before calling `MatZeroRowsLocal()`, the user must first set the
6325    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6326 
6327    See `MatZeroRows()` for details on how this routine operates.
6328 
6329    Level: intermediate
6330 
6331 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6332           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6333 @*/
6334 PetscErrorCode MatZeroRowsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6335 {
6336   PetscFunctionBegin;
6337   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6338   PetscValidType(mat,1);
6339   if (numRows) PetscValidIntPointer(rows,3);
6340   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6341   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6342   MatCheckPreallocated(mat,1);
6343 
6344   if (mat->ops->zerorowslocal) {
6345     PetscCall((*mat->ops->zerorowslocal)(mat,numRows,rows,diag,x,b));
6346   } else {
6347     IS             is, newis;
6348     const PetscInt *newRows;
6349 
6350     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6351     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6352     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping,is,&newis));
6353     PetscCall(ISGetIndices(newis,&newRows));
6354     PetscCall((*mat->ops->zerorows)(mat,numRows,newRows,diag,x,b));
6355     PetscCall(ISRestoreIndices(newis,&newRows));
6356     PetscCall(ISDestroy(&newis));
6357     PetscCall(ISDestroy(&is));
6358   }
6359   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6360   PetscFunctionReturn(0);
6361 }
6362 
6363 /*@
6364    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6365    of a set of rows of a matrix; using local numbering of rows.
6366 
6367    Collective on Mat
6368 
6369    Input Parameters:
6370 +  mat - the matrix
6371 .  is - index set of rows to remove
6372 .  diag - value put in all diagonals of eliminated rows
6373 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6374 -  b - optional vector of right hand side, that will be adjusted by provided solution
6375 
6376    Notes:
6377    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6378    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`.
6379 
6380    See `MatZeroRows()` for details on how this routine operates.
6381 
6382    Level: intermediate
6383 
6384 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6385           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6386 @*/
6387 PetscErrorCode MatZeroRowsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6388 {
6389   PetscInt       numRows;
6390   const PetscInt *rows;
6391 
6392   PetscFunctionBegin;
6393   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6394   PetscValidType(mat,1);
6395   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6396   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6397   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6398   MatCheckPreallocated(mat,1);
6399 
6400   PetscCall(ISGetLocalSize(is,&numRows));
6401   PetscCall(ISGetIndices(is,&rows));
6402   PetscCall(MatZeroRowsLocal(mat,numRows,rows,diag,x,b));
6403   PetscCall(ISRestoreIndices(is,&rows));
6404   PetscFunctionReturn(0);
6405 }
6406 
6407 /*@
6408    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6409    of a set of rows and columns of a matrix; using local numbering of rows.
6410 
6411    Collective on Mat
6412 
6413    Input Parameters:
6414 +  mat - the matrix
6415 .  numRows - the number of rows to remove
6416 .  rows - the global row indices
6417 .  diag - value put in all diagonals of eliminated rows
6418 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6419 -  b - optional vector of right hand side, that will be adjusted by provided solution
6420 
6421    Notes:
6422    Before calling MatZeroRowsColumnsLocal(), the user must first set the
6423    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6424 
6425    See `MatZeroRowsColumns()` for details on how this routine operates.
6426 
6427    Level: intermediate
6428 
6429 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6430           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6431 @*/
6432 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6433 {
6434   IS             is, newis;
6435   const PetscInt *newRows;
6436 
6437   PetscFunctionBegin;
6438   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6439   PetscValidType(mat,1);
6440   if (numRows) PetscValidIntPointer(rows,3);
6441   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6442   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6443   MatCheckPreallocated(mat,1);
6444 
6445   PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6446   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6447   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping,is,&newis));
6448   PetscCall(ISGetIndices(newis,&newRows));
6449   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,newRows,diag,x,b));
6450   PetscCall(ISRestoreIndices(newis,&newRows));
6451   PetscCall(ISDestroy(&newis));
6452   PetscCall(ISDestroy(&is));
6453   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6454   PetscFunctionReturn(0);
6455 }
6456 
6457 /*@
6458    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6459    of a set of rows and columns of a matrix; using local numbering of rows.
6460 
6461    Collective on Mat
6462 
6463    Input Parameters:
6464 +  mat - the matrix
6465 .  is - index set of rows to remove
6466 .  diag - value put in all diagonals of eliminated rows
6467 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6468 -  b - optional vector of right hand side, that will be adjusted by provided solution
6469 
6470    Notes:
6471    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6472    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`.
6473 
6474    See `MatZeroRowsColumns()` for details on how this routine operates.
6475 
6476    Level: intermediate
6477 
6478 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6479           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6480 @*/
6481 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6482 {
6483   PetscInt       numRows;
6484   const PetscInt *rows;
6485 
6486   PetscFunctionBegin;
6487   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6488   PetscValidType(mat,1);
6489   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6490   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6491   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6492   MatCheckPreallocated(mat,1);
6493 
6494   PetscCall(ISGetLocalSize(is,&numRows));
6495   PetscCall(ISGetIndices(is,&rows));
6496   PetscCall(MatZeroRowsColumnsLocal(mat,numRows,rows,diag,x,b));
6497   PetscCall(ISRestoreIndices(is,&rows));
6498   PetscFunctionReturn(0);
6499 }
6500 
6501 /*@C
6502    MatGetSize - Returns the numbers of rows and columns in a matrix.
6503 
6504    Not Collective
6505 
6506    Input Parameter:
6507 .  mat - the matrix
6508 
6509    Output Parameters:
6510 +  m - the number of global rows
6511 -  n - the number of global columns
6512 
6513    Note: both output parameters can be NULL on input.
6514 
6515    Level: beginner
6516 
6517 .seealso: `MatGetLocalSize()`
6518 @*/
6519 PetscErrorCode MatGetSize(Mat mat,PetscInt *m,PetscInt *n)
6520 {
6521   PetscFunctionBegin;
6522   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6523   if (m) *m = mat->rmap->N;
6524   if (n) *n = mat->cmap->N;
6525   PetscFunctionReturn(0);
6526 }
6527 
6528 /*@C
6529    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6530    of a matrix. For all matrices this is the local size of the left and right vectors as returned by MatCreateVecs().
6531 
6532    Not Collective
6533 
6534    Input Parameter:
6535 .  mat - the matrix
6536 
6537    Output Parameters:
6538 +  m - the number of local rows, use `NULL` to not obtain this value
6539 -  n - the number of local columns, use `NULL` to not obtain this value
6540 
6541    Level: beginner
6542 
6543 .seealso: `MatGetSize()`
6544 @*/
6545 PetscErrorCode MatGetLocalSize(Mat mat,PetscInt *m,PetscInt *n)
6546 {
6547   PetscFunctionBegin;
6548   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6549   if (m) PetscValidIntPointer(m,2);
6550   if (n) PetscValidIntPointer(n,3);
6551   if (m) *m = mat->rmap->n;
6552   if (n) *n = mat->cmap->n;
6553   PetscFunctionReturn(0);
6554 }
6555 
6556 /*@C
6557    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6558    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6559 
6560    Not Collective, unless matrix has not been allocated, then collective on Mat
6561 
6562    Input Parameter:
6563 .  mat - the matrix
6564 
6565    Output Parameters:
6566 +  m - the global index of the first local column, use `NULL` to not obtain this value
6567 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6568 
6569    Level: developer
6570 
6571 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6572 
6573 @*/
6574 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat,PetscInt *m,PetscInt *n)
6575 {
6576   PetscFunctionBegin;
6577   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6578   PetscValidType(mat,1);
6579   if (m) PetscValidIntPointer(m,2);
6580   if (n) PetscValidIntPointer(n,3);
6581   MatCheckPreallocated(mat,1);
6582   if (m) *m = mat->cmap->rstart;
6583   if (n) *n = mat->cmap->rend;
6584   PetscFunctionReturn(0);
6585 }
6586 
6587 /*@C
6588    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6589    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
6590    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6591 
6592    Not Collective
6593 
6594    Input Parameter:
6595 .  mat - the matrix
6596 
6597    Output Parameters:
6598 +  m - the global index of the first local row, use `NULL` to not obtain this value
6599 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6600 
6601    Note:
6602   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6603   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6604   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6605 
6606    Level: beginner
6607 
6608 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6609           `PetscLayout`
6610 
6611 @*/
6612 PetscErrorCode MatGetOwnershipRange(Mat mat,PetscInt *m,PetscInt *n)
6613 {
6614   PetscFunctionBegin;
6615   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6616   PetscValidType(mat,1);
6617   if (m) PetscValidIntPointer(m,2);
6618   if (n) PetscValidIntPointer(n,3);
6619   MatCheckPreallocated(mat,1);
6620   if (m) *m = mat->rmap->rstart;
6621   if (n) *n = mat->rmap->rend;
6622   PetscFunctionReturn(0);
6623 }
6624 
6625 /*@C
6626    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6627    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
6628    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6629 
6630    Not Collective, unless matrix has not been allocated, then collective on Mat
6631 
6632    Input Parameters:
6633 .  mat - the matrix
6634 
6635    Output Parameters:
6636 .  ranges - start of each processors portion plus one more than the total length at the end
6637 
6638    Level: beginner
6639 
6640 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6641 
6642 @*/
6643 PetscErrorCode MatGetOwnershipRanges(Mat mat,const PetscInt **ranges)
6644 {
6645   PetscFunctionBegin;
6646   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6647   PetscValidType(mat,1);
6648   MatCheckPreallocated(mat,1);
6649   PetscCall(PetscLayoutGetRanges(mat->rmap,ranges));
6650   PetscFunctionReturn(0);
6651 }
6652 
6653 /*@C
6654    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6655    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6656 
6657    Not Collective, unless matrix has not been allocated, then collective on Mat
6658 
6659    Input Parameters:
6660 .  mat - the matrix
6661 
6662    Output Parameters:
6663 .  ranges - start of each processors portion plus one more then the total length at the end
6664 
6665    Level: beginner
6666 
6667 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6668 
6669 @*/
6670 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat,const PetscInt **ranges)
6671 {
6672   PetscFunctionBegin;
6673   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6674   PetscValidType(mat,1);
6675   MatCheckPreallocated(mat,1);
6676   PetscCall(PetscLayoutGetRanges(mat->cmap,ranges));
6677   PetscFunctionReturn(0);
6678 }
6679 
6680 /*@C
6681    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6682    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6683    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6684 
6685    Not Collective
6686 
6687    Input Parameter:
6688 .  A - matrix
6689 
6690    Output Parameters:
6691 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6692 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6693 
6694    Level: intermediate
6695 
6696 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6697 @*/
6698 PetscErrorCode MatGetOwnershipIS(Mat A,IS *rows,IS *cols)
6699 {
6700   PetscErrorCode (*f)(Mat,IS*,IS*);
6701 
6702   PetscFunctionBegin;
6703   MatCheckPreallocated(A,1);
6704   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatGetOwnershipIS_C",&f));
6705   if (f) {
6706     PetscCall((*f)(A,rows,cols));
6707   } else {   /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6708     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->rmap->n,A->rmap->rstart,1,rows));
6709     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->cmap->N,0,1,cols));
6710   }
6711   PetscFunctionReturn(0);
6712 }
6713 
6714 /*@C
6715    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix.
6716    Uses levels of fill only, not drop tolerance. Use MatLUFactorNumeric()
6717    to complete the factorization.
6718 
6719    Collective on Mat
6720 
6721    Input Parameters:
6722 +  mat - the matrix
6723 .  row - row permutation
6724 .  column - column permutation
6725 -  info - structure containing
6726 $      levels - number of levels of fill.
6727 $      expected fill - as ratio of original fill.
6728 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6729                 missing diagonal entries)
6730 
6731    Output Parameters:
6732 .  fact - new matrix that has been symbolically factored
6733 
6734    Notes:
6735     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
6736 
6737    Most users should employ the simplified KSP interface for linear solvers
6738    instead of working directly with matrix algebra routines such as this.
6739    See, e.g., KSPCreate().
6740 
6741    Level: developer
6742 
6743 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6744           `MatGetOrdering()`, `MatFactorInfo`
6745 
6746     Note: this uses the definition of level of fill as in Y. Saad, 2003
6747 
6748     Developer Note: fortran interface is not autogenerated as the f90
6749     interface definition cannot be generated correctly [due to MatFactorInfo]
6750 
6751    References:
6752 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6753 @*/
6754 PetscErrorCode MatILUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
6755 {
6756   PetscFunctionBegin;
6757   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6758   PetscValidType(mat,2);
6759   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
6760   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
6761   PetscValidPointer(info,5);
6762   PetscValidPointer(fact,1);
6763   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels of fill negative %" PetscInt_FMT,(PetscInt)info->levels);
6764   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6765   if (!fact->ops->ilufactorsymbolic) {
6766     MatSolverType stype;
6767     PetscCall(MatFactorGetSolverType(fact,&stype));
6768     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ILU using solver type %s",((PetscObject)mat)->type_name,stype);
6769   }
6770   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6771   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6772   MatCheckPreallocated(mat,2);
6773 
6774   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic,mat,row,col,0));
6775   PetscCall((fact->ops->ilufactorsymbolic)(fact,mat,row,col,info));
6776   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic,mat,row,col,0));
6777   PetscFunctionReturn(0);
6778 }
6779 
6780 /*@C
6781    MatICCFactorSymbolic - Performs symbolic incomplete
6782    Cholesky factorization for a symmetric matrix.  Use
6783    MatCholeskyFactorNumeric() to complete the factorization.
6784 
6785    Collective on Mat
6786 
6787    Input Parameters:
6788 +  mat - the matrix
6789 .  perm - row and column permutation
6790 -  info - structure containing
6791 $      levels - number of levels of fill.
6792 $      expected fill - as ratio of original fill.
6793 
6794    Output Parameter:
6795 .  fact - the factored matrix
6796 
6797    Notes:
6798    Most users should employ the KSP interface for linear solvers
6799    instead of working directly with matrix algebra routines such as this.
6800    See, e.g., KSPCreate().
6801 
6802    Level: developer
6803 
6804 .seealso: `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6805 
6806     Note: this uses the definition of level of fill as in Y. Saad, 2003
6807 
6808     Developer Note: fortran interface is not autogenerated as the f90
6809     interface definition cannot be generated correctly [due to MatFactorInfo]
6810 
6811    References:
6812 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6813 @*/
6814 PetscErrorCode MatICCFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
6815 {
6816   PetscFunctionBegin;
6817   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6818   PetscValidType(mat,2);
6819   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
6820   PetscValidPointer(info,4);
6821   PetscValidPointer(fact,1);
6822   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6823   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels negative %" PetscInt_FMT,(PetscInt) info->levels);
6824   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6825   if (!(fact)->ops->iccfactorsymbolic) {
6826     MatSolverType stype;
6827     PetscCall(MatFactorGetSolverType(fact,&stype));
6828     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ICC using solver type %s",((PetscObject)mat)->type_name,stype);
6829   }
6830   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6831   MatCheckPreallocated(mat,2);
6832 
6833   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic,mat,perm,0,0));
6834   PetscCall((fact->ops->iccfactorsymbolic)(fact,mat,perm,info));
6835   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic,mat,perm,0,0));
6836   PetscFunctionReturn(0);
6837 }
6838 
6839 /*@C
6840    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6841    points to an array of valid matrices, they may be reused to store the new
6842    submatrices.
6843 
6844    Collective on Mat
6845 
6846    Input Parameters:
6847 +  mat - the matrix
6848 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6849 .  irow, icol - index sets of rows and columns to extract
6850 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6851 
6852    Output Parameter:
6853 .  submat - the array of submatrices
6854 
6855    Notes:
6856    MatCreateSubMatrices() can extract ONLY sequential submatrices
6857    (from both sequential and parallel matrices). Use MatCreateSubMatrix()
6858    to extract a parallel submatrix.
6859 
6860    Some matrix types place restrictions on the row and column
6861    indices, such as that they be sorted or that they be equal to each other.
6862 
6863    The index sets may not have duplicate entries.
6864 
6865    When extracting submatrices from a parallel matrix, each processor can
6866    form a different submatrix by setting the rows and columns of its
6867    individual index sets according to the local submatrix desired.
6868 
6869    When finished using the submatrices, the user should destroy
6870    them with MatDestroySubMatrices().
6871 
6872    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
6873    original matrix has not changed from that last call to MatCreateSubMatrices().
6874 
6875    This routine creates the matrices in submat; you should NOT create them before
6876    calling it. It also allocates the array of matrix pointers submat.
6877 
6878    For BAIJ matrices the index sets must respect the block structure, that is if they
6879    request one row/column in a block, they must request all rows/columns that are in
6880    that block. For example, if the block size is 2 you cannot request just row 0 and
6881    column 0.
6882 
6883    Fortran Note:
6884    The Fortran interface is slightly different from that given below; it
6885    requires one to pass in  as submat a Mat (integer) array of size at least n+1.
6886 
6887    Level: advanced
6888 
6889 .seealso: `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6890 @*/
6891 PetscErrorCode MatCreateSubMatrices(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
6892 {
6893   PetscInt       i;
6894   PetscBool      eq;
6895 
6896   PetscFunctionBegin;
6897   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6898   PetscValidType(mat,1);
6899   if (n) {
6900     PetscValidPointer(irow,3);
6901     for (i=0; i<n; i++) PetscValidHeaderSpecific(irow[i],IS_CLASSID,3);
6902     PetscValidPointer(icol,4);
6903     for (i=0; i<n; i++) PetscValidHeaderSpecific(icol[i],IS_CLASSID,4);
6904   }
6905   PetscValidPointer(submat,6);
6906   if (n && scall == MAT_REUSE_MATRIX) {
6907     PetscValidPointer(*submat,6);
6908     for (i=0; i<n; i++) PetscValidHeaderSpecific((*submat)[i],MAT_CLASSID,6);
6909   }
6910   PetscCheck(mat->ops->createsubmatrices,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6911   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6912   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6913   MatCheckPreallocated(mat,1);
6914   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
6915   PetscCall((*mat->ops->createsubmatrices)(mat,n,irow,icol,scall,submat));
6916   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
6917   for (i=0; i<n; i++) {
6918     (*submat)[i]->factortype = MAT_FACTOR_NONE;  /* in case in place factorization was previously done on submatrix */
6919     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
6920     if (eq) {
6921       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
6922     }
6923 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6924     if (mat->boundtocpu && mat->bindingpropagates) {
6925       PetscCall(MatBindToCPU((*submat)[i],PETSC_TRUE));
6926       PetscCall(MatSetBindingPropagates((*submat)[i],PETSC_TRUE));
6927     }
6928 #endif
6929   }
6930   PetscFunctionReturn(0);
6931 }
6932 
6933 /*@C
6934    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of IS that may live on subcomms).
6935 
6936    Collective on Mat
6937 
6938    Input Parameters:
6939 +  mat - the matrix
6940 .  n   - the number of submatrixes to be extracted
6941 .  irow, icol - index sets of rows and columns to extract
6942 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6943 
6944    Output Parameter:
6945 .  submat - the array of submatrices
6946 
6947    Level: advanced
6948 
6949 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6950 @*/
6951 PetscErrorCode MatCreateSubMatricesMPI(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
6952 {
6953   PetscInt       i;
6954   PetscBool      eq;
6955 
6956   PetscFunctionBegin;
6957   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6958   PetscValidType(mat,1);
6959   if (n) {
6960     PetscValidPointer(irow,3);
6961     PetscValidHeaderSpecific(*irow,IS_CLASSID,3);
6962     PetscValidPointer(icol,4);
6963     PetscValidHeaderSpecific(*icol,IS_CLASSID,4);
6964   }
6965   PetscValidPointer(submat,6);
6966   if (n && scall == MAT_REUSE_MATRIX) {
6967     PetscValidPointer(*submat,6);
6968     PetscValidHeaderSpecific(**submat,MAT_CLASSID,6);
6969   }
6970   PetscCheck(mat->ops->createsubmatricesmpi,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6971   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6972   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6973   MatCheckPreallocated(mat,1);
6974 
6975   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
6976   PetscCall((*mat->ops->createsubmatricesmpi)(mat,n,irow,icol,scall,submat));
6977   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
6978   for (i=0; i<n; i++) {
6979     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
6980     if (eq) {
6981       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
6982     }
6983   }
6984   PetscFunctionReturn(0);
6985 }
6986 
6987 /*@C
6988    MatDestroyMatrices - Destroys an array of matrices.
6989 
6990    Collective on Mat
6991 
6992    Input Parameters:
6993 +  n - the number of local matrices
6994 -  mat - the matrices (note that this is a pointer to the array of matrices)
6995 
6996    Level: advanced
6997 
6998     Notes:
6999     Frees not only the matrices, but also the array that contains the matrices
7000            In Fortran will not free the array.
7001 
7002 .seealso: `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7003 @*/
7004 PetscErrorCode MatDestroyMatrices(PetscInt n,Mat *mat[])
7005 {
7006   PetscInt       i;
7007 
7008   PetscFunctionBegin;
7009   if (!*mat) PetscFunctionReturn(0);
7010   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7011   PetscValidPointer(mat,2);
7012 
7013   for (i=0; i<n; i++) {
7014     PetscCall(MatDestroy(&(*mat)[i]));
7015   }
7016 
7017   /* memory is allocated even if n = 0 */
7018   PetscCall(PetscFree(*mat));
7019   PetscFunctionReturn(0);
7020 }
7021 
7022 /*@C
7023    MatDestroySubMatrices - Destroys a set of matrices obtained with MatCreateSubMatrices().
7024 
7025    Collective on Mat
7026 
7027    Input Parameters:
7028 +  n - the number of local matrices
7029 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7030                        sequence of MatCreateSubMatrices())
7031 
7032    Level: advanced
7033 
7034     Notes:
7035     Frees not only the matrices, but also the array that contains the matrices
7036            In Fortran will not free the array.
7037 
7038 .seealso: `MatCreateSubMatrices()`
7039 @*/
7040 PetscErrorCode MatDestroySubMatrices(PetscInt n,Mat *mat[])
7041 {
7042   Mat            mat0;
7043 
7044   PetscFunctionBegin;
7045   if (!*mat) PetscFunctionReturn(0);
7046   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7047   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7048   PetscValidPointer(mat,2);
7049 
7050   mat0 = (*mat)[0];
7051   if (mat0 && mat0->ops->destroysubmatrices) {
7052     PetscCall((mat0->ops->destroysubmatrices)(n,mat));
7053   } else {
7054     PetscCall(MatDestroyMatrices(n,mat));
7055   }
7056   PetscFunctionReturn(0);
7057 }
7058 
7059 /*@C
7060    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7061 
7062    Collective on Mat
7063 
7064    Input Parameters:
7065 .  mat - the matrix
7066 
7067    Output Parameter:
7068 .  matstruct - the sequential matrix with the nonzero structure of mat
7069 
7070   Level: intermediate
7071 
7072 .seealso: `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7073 @*/
7074 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat,Mat *matstruct)
7075 {
7076   PetscFunctionBegin;
7077   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7078   PetscValidPointer(matstruct,2);
7079 
7080   PetscValidType(mat,1);
7081   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7082   MatCheckPreallocated(mat,1);
7083 
7084   PetscCheck(mat->ops->getseqnonzerostructure,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)mat)->type_name);
7085   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7086   PetscCall((*mat->ops->getseqnonzerostructure)(mat,matstruct));
7087   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7088   PetscFunctionReturn(0);
7089 }
7090 
7091 /*@C
7092    MatDestroySeqNonzeroStructure - Destroys matrix obtained with MatGetSeqNonzeroStructure().
7093 
7094    Collective on Mat
7095 
7096    Input Parameters:
7097 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7098                        sequence of MatGetSequentialNonzeroStructure())
7099 
7100    Level: advanced
7101 
7102     Notes:
7103     Frees not only the matrices, but also the array that contains the matrices
7104 
7105 .seealso: `MatGetSeqNonzeroStructure()`
7106 @*/
7107 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7108 {
7109   PetscFunctionBegin;
7110   PetscValidPointer(mat,1);
7111   PetscCall(MatDestroy(mat));
7112   PetscFunctionReturn(0);
7113 }
7114 
7115 /*@
7116    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7117    replaces the index sets by larger ones that represent submatrices with
7118    additional overlap.
7119 
7120    Collective on Mat
7121 
7122    Input Parameters:
7123 +  mat - the matrix
7124 .  n   - the number of index sets
7125 .  is  - the array of index sets (these index sets will changed during the call)
7126 -  ov  - the additional overlap requested
7127 
7128    Options Database:
7129 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7130 
7131    Level: developer
7132 
7133    Developer Note:
7134    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.
7135 
7136 .seealso: `MatCreateSubMatrices()`
7137 @*/
7138 PetscErrorCode MatIncreaseOverlap(Mat mat,PetscInt n,IS is[],PetscInt ov)
7139 {
7140   PetscInt       i,bs,cbs;
7141 
7142   PetscFunctionBegin;
7143   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7144   PetscValidType(mat,1);
7145   PetscValidLogicalCollectiveInt(mat,n,2);
7146   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7147   if (n) {
7148     PetscValidPointer(is,3);
7149     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i],IS_CLASSID,3);
7150   }
7151   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7152   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7153   MatCheckPreallocated(mat,1);
7154 
7155   if (!ov || !n) PetscFunctionReturn(0);
7156   PetscCheck(mat->ops->increaseoverlap,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7157   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7158   PetscCall((*mat->ops->increaseoverlap)(mat,n,is,ov));
7159   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7160   PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
7161   if (bs == cbs) {
7162     for (i=0; i<n; i++) {
7163       PetscCall(ISSetBlockSize(is[i],bs));
7164     }
7165   }
7166   PetscFunctionReturn(0);
7167 }
7168 
7169 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat,IS*,PetscInt);
7170 
7171 /*@
7172    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7173    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7174    additional overlap.
7175 
7176    Collective on Mat
7177 
7178    Input Parameters:
7179 +  mat - the matrix
7180 .  n   - the number of index sets
7181 .  is  - the array of index sets (these index sets will changed during the call)
7182 -  ov  - the additional overlap requested
7183 
7184    Options Database:
7185 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7186 
7187    Level: developer
7188 
7189 .seealso: `MatCreateSubMatrices()`
7190 @*/
7191 PetscErrorCode MatIncreaseOverlapSplit(Mat mat,PetscInt n,IS is[],PetscInt ov)
7192 {
7193   PetscInt       i;
7194 
7195   PetscFunctionBegin;
7196   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7197   PetscValidType(mat,1);
7198   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7199   if (n) {
7200     PetscValidPointer(is,3);
7201     PetscValidHeaderSpecific(*is,IS_CLASSID,3);
7202   }
7203   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7204   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7205   MatCheckPreallocated(mat,1);
7206   if (!ov) PetscFunctionReturn(0);
7207   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7208   for (i=0; i<n; i++) {
7209     PetscCall(MatIncreaseOverlapSplit_Single(mat,&is[i],ov));
7210   }
7211   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7212   PetscFunctionReturn(0);
7213 }
7214 
7215 /*@
7216    MatGetBlockSize - Returns the matrix block size.
7217 
7218    Not Collective
7219 
7220    Input Parameter:
7221 .  mat - the matrix
7222 
7223    Output Parameter:
7224 .  bs - block size
7225 
7226    Notes:
7227     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7228 
7229    If the block size has not been set yet this routine returns 1.
7230 
7231    Level: intermediate
7232 
7233 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7234 @*/
7235 PetscErrorCode MatGetBlockSize(Mat mat,PetscInt *bs)
7236 {
7237   PetscFunctionBegin;
7238   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7239   PetscValidIntPointer(bs,2);
7240   *bs = PetscAbs(mat->rmap->bs);
7241   PetscFunctionReturn(0);
7242 }
7243 
7244 /*@
7245    MatGetBlockSizes - Returns the matrix block row and column sizes.
7246 
7247    Not Collective
7248 
7249    Input Parameter:
7250 .  mat - the matrix
7251 
7252    Output Parameters:
7253 +  rbs - row block size
7254 -  cbs - column block size
7255 
7256    Notes:
7257     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7258     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7259 
7260    If a block size has not been set yet this routine returns 1.
7261 
7262    Level: intermediate
7263 
7264 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7265 @*/
7266 PetscErrorCode MatGetBlockSizes(Mat mat,PetscInt *rbs, PetscInt *cbs)
7267 {
7268   PetscFunctionBegin;
7269   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7270   if (rbs) PetscValidIntPointer(rbs,2);
7271   if (cbs) PetscValidIntPointer(cbs,3);
7272   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7273   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7274   PetscFunctionReturn(0);
7275 }
7276 
7277 /*@
7278    MatSetBlockSize - Sets the matrix block size.
7279 
7280    Logically Collective on Mat
7281 
7282    Input Parameters:
7283 +  mat - the matrix
7284 -  bs - block size
7285 
7286    Notes:
7287     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7288     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7289 
7290     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block size
7291     is compatible with the matrix local sizes.
7292 
7293    Level: intermediate
7294 
7295 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7296 @*/
7297 PetscErrorCode MatSetBlockSize(Mat mat,PetscInt bs)
7298 {
7299   PetscFunctionBegin;
7300   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7301   PetscValidLogicalCollectiveInt(mat,bs,2);
7302   PetscCall(MatSetBlockSizes(mat,bs,bs));
7303   PetscFunctionReturn(0);
7304 }
7305 
7306 typedef struct {
7307   PetscInt         n;
7308   IS               *is;
7309   Mat              *mat;
7310   PetscObjectState nonzerostate;
7311   Mat              C;
7312 } EnvelopeData;
7313 
7314 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7315 {
7316   for (PetscInt i=0; i<edata->n; i++) {
7317     PetscCall(ISDestroy(&edata->is[i]));
7318   }
7319   PetscCall(PetscFree(edata->is));
7320   PetscCall(PetscFree(edata));
7321   return 0;
7322 }
7323 
7324 /*
7325    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7326          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7327 
7328    Collective on mat
7329 
7330    Input Parameter:
7331 .  mat - the matrix
7332 
7333    Notes:
7334      There can be zeros within the blocks
7335 
7336      The blocks can overlap between processes, including laying on more than two processes
7337 
7338 */
7339 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7340 {
7341   PetscInt                    n,*sizes,*starts,i = 0,env = 0, tbs = 0, lblocks = 0,rstart,II,ln = 0,cnt = 0,cstart,cend;
7342   PetscInt                    *diag,*odiag,sc;
7343   VecScatter                  scatter;
7344   PetscScalar                 *seqv;
7345   const PetscScalar           *parv;
7346   const PetscInt              *ia,*ja;
7347   PetscBool                   set,flag,done;
7348   Mat                         AA = mat,A;
7349   MPI_Comm                    comm;
7350   PetscMPIInt                 rank,size,tag;
7351   MPI_Status                  status;
7352   PetscContainer              container;
7353   EnvelopeData                *edata;
7354   Vec                         seq,par;
7355   IS                          isglobal;
7356 
7357   PetscFunctionBegin;
7358   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7359   PetscCall(MatIsSymmetricKnown(mat,&set,&flag));
7360   if (!set || !flag) {
7361     /* TOO: only needs nonzero structure of transpose */
7362     PetscCall(MatTranspose(mat,MAT_INITIAL_MATRIX,&AA));
7363     PetscCall(MatAXPY(AA,1.0,mat,DIFFERENT_NONZERO_PATTERN));
7364   }
7365   PetscCall(MatAIJGetLocalMat(AA,&A));
7366   PetscCall(MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7367   PetscCheck(done,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unable to get IJ structure from matrix");
7368 
7369   PetscCall(MatGetLocalSize(mat,&n,NULL));
7370   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag));
7371   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
7372   PetscCallMPI(MPI_Comm_size(comm,&size));
7373   PetscCallMPI(MPI_Comm_rank(comm,&rank));
7374 
7375   PetscCall(PetscMalloc2(n,&sizes,n,&starts));
7376 
7377   if (rank > 0) {
7378     PetscCallMPI(MPI_Recv(&env,1,MPIU_INT,rank-1,tag,comm,&status));
7379     PetscCallMPI(MPI_Recv(&tbs,1,MPIU_INT,rank-1,tag,comm,&status));
7380   }
7381   PetscCall(MatGetOwnershipRange(mat,&rstart,NULL));
7382   for (i=0; i<n; i++) {
7383     env = PetscMax(env,ja[ia[i+1]-1]);
7384     II = rstart + i;
7385     if (env == II) {
7386       starts[lblocks]  = tbs;
7387       sizes[lblocks++] = 1 + II - tbs;
7388       tbs = 1 + II;
7389     }
7390   }
7391   if (rank < size-1) {
7392     PetscCallMPI(MPI_Send(&env,1,MPIU_INT,rank+1,tag,comm));
7393     PetscCallMPI(MPI_Send(&tbs,1,MPIU_INT,rank+1,tag,comm));
7394   }
7395 
7396   PetscCall(MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7397   if (!set || !flag) {
7398     PetscCall(MatDestroy(&AA));
7399   }
7400   PetscCall(MatDestroy(&A));
7401 
7402   PetscCall(PetscNew(&edata));
7403   PetscCall(MatGetNonzeroState(mat,&edata->nonzerostate));
7404   edata->n = lblocks;
7405   /* create IS needed for extracting blocks from the original matrix */
7406   PetscCall(PetscMalloc1(lblocks,&edata->is));
7407   for (PetscInt i=0; i<lblocks; i++) {
7408     PetscCall(ISCreateStride(PETSC_COMM_SELF,sizes[i],starts[i],1,&edata->is[i]));
7409   }
7410 
7411   /* Create the resulting inverse matrix structure with preallocation information */
7412   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&edata->C));
7413   PetscCall(MatSetSizes(edata->C,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
7414   PetscCall(MatSetBlockSizesFromMats(edata->C,mat,mat));
7415   PetscCall(MatSetType(edata->C,MATAIJ));
7416 
7417   /* Communicate the start and end of each row, from each block to the correct rank */
7418   /* TODO: Use PetscSF instead of VecScatter */
7419   for (PetscInt i=0; i<lblocks; i++) ln += sizes[i];
7420   PetscCall(VecCreateSeq(PETSC_COMM_SELF,2*ln,&seq));
7421   PetscCall(VecGetArrayWrite(seq,&seqv));
7422   for (PetscInt i=0; i<lblocks; i++) {
7423     for (PetscInt j=0; j<sizes[i]; j++) {
7424       seqv[cnt]   = starts[i];
7425       seqv[cnt+1] = starts[i] + sizes[i];
7426       cnt += 2;
7427     }
7428   }
7429   PetscCall(VecRestoreArrayWrite(seq,&seqv));
7430   PetscCallMPI(MPI_Scan(&cnt,&sc,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
7431   sc -= cnt;
7432   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat),2*mat->rmap->n,2*mat->rmap->N,&par));
7433   PetscCall(ISCreateStride(PETSC_COMM_SELF,cnt,sc,1,&isglobal));
7434   PetscCall(VecScatterCreate(seq, NULL  ,par, isglobal,&scatter));
7435   PetscCall(ISDestroy(&isglobal));
7436   PetscCall(VecScatterBegin(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7437   PetscCall(VecScatterEnd(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7438   PetscCall(VecScatterDestroy(&scatter));
7439   PetscCall(VecDestroy(&seq));
7440   PetscCall(MatGetOwnershipRangeColumn(mat,&cstart,&cend));
7441   PetscCall(PetscMalloc2(mat->rmap->n,&diag,mat->rmap->n,&odiag));
7442   PetscCall(VecGetArrayRead(par,&parv));
7443   cnt = 0;
7444   PetscCall(MatGetSize(mat,NULL,&n));
7445   for (PetscInt i=0; i<mat->rmap->n; i++) {
7446     PetscInt start,end,d = 0,od = 0;
7447 
7448     start = (PetscInt)PetscRealPart(parv[cnt]);
7449     end   = (PetscInt)PetscRealPart(parv[cnt+1]);
7450     cnt  += 2;
7451 
7452     if (start < cstart) {od += cstart - start + n - cend; d += cend - cstart;}
7453     else if (start < cend) {od += n - cend; d += cend - start;}
7454     else od += n - start;
7455     if (end <= cstart) {od -= cstart - end + n - cend; d -= cend - cstart;}
7456     else if (end < cend) {od -= n - cend; d -= cend - end;}
7457     else od -= n - end;
7458 
7459     odiag[i] = od;
7460     diag[i]  = d;
7461   }
7462   PetscCall(VecRestoreArrayRead(par,&parv));
7463   PetscCall(VecDestroy(&par));
7464   PetscCall(MatXAIJSetPreallocation(edata->C,mat->rmap->bs,diag,odiag,NULL,NULL));
7465   PetscCall(PetscFree2(diag,odiag));
7466   PetscCall(PetscFree2(sizes,starts));
7467 
7468   PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&container));
7469   PetscCall(PetscContainerSetPointer(container,edata));
7470   PetscCall(PetscContainerSetUserDestroy(container,(PetscErrorCode (*)(void*))EnvelopeDataDestroy));
7471   PetscCall(PetscObjectCompose((PetscObject)mat,"EnvelopeData",(PetscObject)container));
7472   PetscCall(PetscObjectDereference((PetscObject)container));
7473   PetscFunctionReturn(0);
7474 }
7475 
7476 /*@
7477   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7478 
7479   Collective on Mat
7480 
7481   Input Parameters:
7482 . A - the matrix
7483 
7484   Output Parameters:
7485 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7486 
7487   Notes:
7488      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7489 
7490   Level: advanced
7491 
7492 .seealso: MatInvertBlockDiagonal(), MatComputeBlockDiagonal()
7493 @*/
7494 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A,MatReuse reuse, Mat *C)
7495 {
7496   PetscContainer    container;
7497   EnvelopeData      *edata;
7498   PetscObjectState  nonzerostate;
7499 
7500   PetscFunctionBegin;
7501   PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7502   if (!container) {
7503     PetscCall(MatComputeVariableBlockEnvelope(A));
7504     PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7505   }
7506   PetscCall(PetscContainerGetPointer(container,(void**)&edata));
7507   PetscCall(MatGetNonzeroState(A,&nonzerostate));
7508   PetscCheck(nonzerostate <= edata->nonzerostate,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Cannot handle changes to matrix nonzero structure");
7509   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"C matrix must be the same as previously output");
7510 
7511   PetscCall(MatCreateSubMatrices(A,edata->n,edata->is,edata->is,MAT_INITIAL_MATRIX,&edata->mat));
7512   *C   = edata->C;
7513 
7514   for (PetscInt i=0; i<edata->n; i++) {
7515     Mat         D;
7516     PetscScalar *dvalues;
7517 
7518     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE,MAT_INITIAL_MATRIX,&D));
7519     PetscCall(MatSetOption(*C,MAT_ROW_ORIENTED,PETSC_FALSE));
7520     PetscCall(MatSeqDenseInvert(D));
7521     PetscCall(MatDenseGetArray(D,&dvalues));
7522     PetscCall(MatSetValuesIS(*C,edata->is[i],edata->is[i],dvalues,INSERT_VALUES));
7523     PetscCall(MatDestroy(&D));
7524   }
7525   PetscCall(MatDestroySubMatrices(edata->n,&edata->mat));
7526   PetscCall(MatAssemblyBegin(*C,MAT_FINAL_ASSEMBLY));
7527   PetscCall(MatAssemblyEnd(*C,MAT_FINAL_ASSEMBLY));
7528   PetscFunctionReturn(0);
7529 }
7530 
7531 /*@
7532    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7533 
7534    Logically Collective on Mat
7535 
7536    Input Parameters:
7537 +  mat - the matrix
7538 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7539 -  bsizes - the block sizes
7540 
7541    Notes:
7542     Currently used by PCVPBJACOBI for AIJ matrices
7543 
7544     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.
7545 
7546    Level: intermediate
7547 
7548 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7549 @*/
7550 PetscErrorCode MatSetVariableBlockSizes(Mat mat,PetscInt nblocks,PetscInt *bsizes)
7551 {
7552   PetscInt       i,ncnt = 0, nlocal;
7553 
7554   PetscFunctionBegin;
7555   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7556   PetscCheck(nblocks >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Number of local blocks must be great than or equal to zero");
7557   PetscCall(MatGetLocalSize(mat,&nlocal,NULL));
7558   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
7559   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);
7560   PetscCall(PetscFree(mat->bsizes));
7561   mat->nblocks = nblocks;
7562   PetscCall(PetscMalloc1(nblocks,&mat->bsizes));
7563   PetscCall(PetscArraycpy(mat->bsizes,bsizes,nblocks));
7564   PetscFunctionReturn(0);
7565 }
7566 
7567 /*@C
7568    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7569 
7570    Logically Collective on Mat
7571 
7572    Input Parameter:
7573 .  mat - the matrix
7574 
7575    Output Parameters:
7576 +  nblocks - the number of blocks on this process
7577 -  bsizes - the block sizes
7578 
7579    Notes: Currently not supported from Fortran
7580 
7581    Level: intermediate
7582 
7583 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7584 @*/
7585 PetscErrorCode MatGetVariableBlockSizes(Mat mat,PetscInt *nblocks,const PetscInt **bsizes)
7586 {
7587   PetscFunctionBegin;
7588   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7589   *nblocks = mat->nblocks;
7590   *bsizes  = mat->bsizes;
7591   PetscFunctionReturn(0);
7592 }
7593 
7594 /*@
7595    MatSetBlockSizes - Sets the matrix block row and column sizes.
7596 
7597    Logically Collective on Mat
7598 
7599    Input Parameters:
7600 +  mat - the matrix
7601 .  rbs - row block size
7602 -  cbs - column block size
7603 
7604    Notes:
7605     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7606     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7607     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7608 
7609     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block sizes
7610     are compatible with the matrix local sizes.
7611 
7612     The row and column block size determine the blocksize of the "row" and "column" vectors returned by MatCreateVecs().
7613 
7614    Level: intermediate
7615 
7616 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7617 @*/
7618 PetscErrorCode MatSetBlockSizes(Mat mat,PetscInt rbs,PetscInt cbs)
7619 {
7620   PetscFunctionBegin;
7621   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7622   PetscValidLogicalCollectiveInt(mat,rbs,2);
7623   PetscValidLogicalCollectiveInt(mat,cbs,3);
7624   if (mat->ops->setblocksizes) PetscCall((*mat->ops->setblocksizes)(mat,rbs,cbs));
7625   if (mat->rmap->refcnt) {
7626     ISLocalToGlobalMapping l2g = NULL;
7627     PetscLayout            nmap = NULL;
7628 
7629     PetscCall(PetscLayoutDuplicate(mat->rmap,&nmap));
7630     if (mat->rmap->mapping) {
7631       PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping,&l2g));
7632     }
7633     PetscCall(PetscLayoutDestroy(&mat->rmap));
7634     mat->rmap = nmap;
7635     mat->rmap->mapping = l2g;
7636   }
7637   if (mat->cmap->refcnt) {
7638     ISLocalToGlobalMapping l2g = NULL;
7639     PetscLayout            nmap = NULL;
7640 
7641     PetscCall(PetscLayoutDuplicate(mat->cmap,&nmap));
7642     if (mat->cmap->mapping) {
7643       PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping,&l2g));
7644     }
7645     PetscCall(PetscLayoutDestroy(&mat->cmap));
7646     mat->cmap = nmap;
7647     mat->cmap->mapping = l2g;
7648   }
7649   PetscCall(PetscLayoutSetBlockSize(mat->rmap,rbs));
7650   PetscCall(PetscLayoutSetBlockSize(mat->cmap,cbs));
7651   PetscFunctionReturn(0);
7652 }
7653 
7654 /*@
7655    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7656 
7657    Logically Collective on Mat
7658 
7659    Input Parameters:
7660 +  mat - the matrix
7661 .  fromRow - matrix from which to copy row block size
7662 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7663 
7664    Level: developer
7665 
7666 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7667 @*/
7668 PetscErrorCode MatSetBlockSizesFromMats(Mat mat,Mat fromRow,Mat fromCol)
7669 {
7670   PetscFunctionBegin;
7671   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7672   PetscValidHeaderSpecific(fromRow,MAT_CLASSID,2);
7673   PetscValidHeaderSpecific(fromCol,MAT_CLASSID,3);
7674   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap,fromRow->rmap->bs));
7675   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap,fromCol->cmap->bs));
7676   PetscFunctionReturn(0);
7677 }
7678 
7679 /*@
7680    MatResidual - Default routine to calculate the residual.
7681 
7682    Collective on Mat
7683 
7684    Input Parameters:
7685 +  mat - the matrix
7686 .  b   - the right-hand-side
7687 -  x   - the approximate solution
7688 
7689    Output Parameter:
7690 .  r - location to store the residual
7691 
7692    Level: developer
7693 
7694 .seealso: `PCMGSetResidual()`
7695 @*/
7696 PetscErrorCode MatResidual(Mat mat,Vec b,Vec x,Vec r)
7697 {
7698   PetscFunctionBegin;
7699   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7700   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
7701   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
7702   PetscValidHeaderSpecific(r,VEC_CLASSID,4);
7703   PetscValidType(mat,1);
7704   MatCheckPreallocated(mat,1);
7705   PetscCall(PetscLogEventBegin(MAT_Residual,mat,0,0,0));
7706   if (!mat->ops->residual) {
7707     PetscCall(MatMult(mat,x,r));
7708     PetscCall(VecAYPX(r,-1.0,b));
7709   } else {
7710     PetscCall((*mat->ops->residual)(mat,b,x,r));
7711   }
7712   PetscCall(PetscLogEventEnd(MAT_Residual,mat,0,0,0));
7713   PetscFunctionReturn(0);
7714 }
7715 
7716 /*@C
7717     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7718 
7719    Collective on Mat
7720 
7721     Input Parameters:
7722 +   mat - the matrix
7723 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7724 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be   symmetrized
7725 -   inodecompressed - PETSC_TRUE or PETSC_FALSE  indicating if the nonzero structure of the
7726                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7727                  always used.
7728 
7729     Output Parameters:
7730 +   n - number of local rows in the (possibly compressed) matrix
7731 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7732 .   ja - the column indices
7733 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7734            are responsible for handling the case when done == PETSC_FALSE and ia and ja are not set
7735 
7736     Level: developer
7737 
7738     Notes:
7739     You CANNOT change any of the ia[] or ja[] values.
7740 
7741     Use MatRestoreRowIJ() when you are finished accessing the ia[] and ja[] values.
7742 
7743     Fortran Notes:
7744     In Fortran use
7745 $
7746 $      PetscInt ia(1), ja(1)
7747 $      PetscOffset iia, jja
7748 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7749 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7750 
7751      or
7752 $
7753 $    PetscInt, pointer :: ia(:),ja(:)
7754 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7755 $    ! Access the ith and jth entries via ia(i) and ja(j)
7756 
7757 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7758 @*/
7759 PetscErrorCode MatGetRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7760 {
7761   PetscFunctionBegin;
7762   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7763   PetscValidType(mat,1);
7764   if (n) PetscValidIntPointer(n,5);
7765   if (ia) PetscValidPointer(ia,6);
7766   if (ja) PetscValidPointer(ja,7);
7767   if (done) PetscValidBoolPointer(done,8);
7768   MatCheckPreallocated(mat,1);
7769   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7770   else {
7771     if (done) *done = PETSC_TRUE;
7772     PetscCall(PetscLogEventBegin(MAT_GetRowIJ,mat,0,0,0));
7773     PetscCall((*mat->ops->getrowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7774     PetscCall(PetscLogEventEnd(MAT_GetRowIJ,mat,0,0,0));
7775   }
7776   PetscFunctionReturn(0);
7777 }
7778 
7779 /*@C
7780     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7781 
7782     Collective on Mat
7783 
7784     Input Parameters:
7785 +   mat - the matrix
7786 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7787 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7788                 symmetrized
7789 .   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7790                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7791                  always used.
7792 .   n - number of columns in the (possibly compressed) matrix
7793 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7794 -   ja - the row indices
7795 
7796     Output Parameters:
7797 .   done - PETSC_TRUE or PETSC_FALSE, indicating whether the values have been returned
7798 
7799     Level: developer
7800 
7801 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7802 @*/
7803 PetscErrorCode MatGetColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7804 {
7805   PetscFunctionBegin;
7806   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7807   PetscValidType(mat,1);
7808   PetscValidIntPointer(n,5);
7809   if (ia) PetscValidPointer(ia,6);
7810   if (ja) PetscValidPointer(ja,7);
7811   PetscValidBoolPointer(done,8);
7812   MatCheckPreallocated(mat,1);
7813   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7814   else {
7815     *done = PETSC_TRUE;
7816     PetscCall((*mat->ops->getcolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7817   }
7818   PetscFunctionReturn(0);
7819 }
7820 
7821 /*@C
7822     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with
7823     MatGetRowIJ().
7824 
7825     Collective on Mat
7826 
7827     Input Parameters:
7828 +   mat - the matrix
7829 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7830 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7831                 symmetrized
7832 .   inodecompressed -  PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7833                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7834                  always used.
7835 .   n - size of (possibly compressed) matrix
7836 .   ia - the row pointers
7837 -   ja - the column indices
7838 
7839     Output Parameters:
7840 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7841 
7842     Note:
7843     This routine zeros out n, ia, and ja. This is to prevent accidental
7844     us of the array after it has been restored. If you pass NULL, it will
7845     not zero the pointers.  Use of ia or ja after MatRestoreRowIJ() is invalid.
7846 
7847     Level: developer
7848 
7849 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7850 @*/
7851 PetscErrorCode MatRestoreRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7852 {
7853   PetscFunctionBegin;
7854   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7855   PetscValidType(mat,1);
7856   if (ia) PetscValidPointer(ia,6);
7857   if (ja) PetscValidPointer(ja,7);
7858   if (done) PetscValidBoolPointer(done,8);
7859   MatCheckPreallocated(mat,1);
7860 
7861   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7862   else {
7863     if (done) *done = PETSC_TRUE;
7864     PetscCall((*mat->ops->restorerowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7865     if (n)  *n = 0;
7866     if (ia) *ia = NULL;
7867     if (ja) *ja = NULL;
7868   }
7869   PetscFunctionReturn(0);
7870 }
7871 
7872 /*@C
7873     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with
7874     MatGetColumnIJ().
7875 
7876     Collective on Mat
7877 
7878     Input Parameters:
7879 +   mat - the matrix
7880 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7881 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7882                 symmetrized
7883 -   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7884                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7885                  always used.
7886 
7887     Output Parameters:
7888 +   n - size of (possibly compressed) matrix
7889 .   ia - the column pointers
7890 .   ja - the row indices
7891 -   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7892 
7893     Level: developer
7894 
7895 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7896 @*/
7897 PetscErrorCode MatRestoreColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7898 {
7899   PetscFunctionBegin;
7900   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7901   PetscValidType(mat,1);
7902   if (ia) PetscValidPointer(ia,6);
7903   if (ja) PetscValidPointer(ja,7);
7904   PetscValidBoolPointer(done,8);
7905   MatCheckPreallocated(mat,1);
7906 
7907   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7908   else {
7909     *done = PETSC_TRUE;
7910     PetscCall((*mat->ops->restorecolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7911     if (n)  *n = 0;
7912     if (ia) *ia = NULL;
7913     if (ja) *ja = NULL;
7914   }
7915   PetscFunctionReturn(0);
7916 }
7917 
7918 /*@C
7919     MatColoringPatch -Used inside matrix coloring routines that
7920     use MatGetRowIJ() and/or MatGetColumnIJ().
7921 
7922     Collective on Mat
7923 
7924     Input Parameters:
7925 +   mat - the matrix
7926 .   ncolors - max color value
7927 .   n   - number of entries in colorarray
7928 -   colorarray - array indicating color for each column
7929 
7930     Output Parameters:
7931 .   iscoloring - coloring generated using colorarray information
7932 
7933     Level: developer
7934 
7935 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7936 
7937 @*/
7938 PetscErrorCode MatColoringPatch(Mat mat,PetscInt ncolors,PetscInt n,ISColoringValue colorarray[],ISColoring *iscoloring)
7939 {
7940   PetscFunctionBegin;
7941   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7942   PetscValidType(mat,1);
7943   PetscValidIntPointer(colorarray,4);
7944   PetscValidPointer(iscoloring,5);
7945   MatCheckPreallocated(mat,1);
7946 
7947   if (!mat->ops->coloringpatch) {
7948     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat),ncolors,n,colorarray,PETSC_OWN_POINTER,iscoloring));
7949   } else {
7950     PetscCall((*mat->ops->coloringpatch)(mat,ncolors,n,colorarray,iscoloring));
7951   }
7952   PetscFunctionReturn(0);
7953 }
7954 
7955 /*@
7956    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7957 
7958    Logically Collective on Mat
7959 
7960    Input Parameter:
7961 .  mat - the factored matrix to be reset
7962 
7963    Notes:
7964    This routine should be used only with factored matrices formed by in-place
7965    factorization via ILU(0) (or by in-place LU factorization for the MATSEQDENSE
7966    format).  This option can save memory, for example, when solving nonlinear
7967    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7968    ILU(0) preconditioner.
7969 
7970    Note that one can specify in-place ILU(0) factorization by calling
7971 .vb
7972      PCType(pc,PCILU);
7973      PCFactorSeUseInPlace(pc);
7974 .ve
7975    or by using the options -pc_type ilu -pc_factor_in_place
7976 
7977    In-place factorization ILU(0) can also be used as a local
7978    solver for the blocks within the block Jacobi or additive Schwarz
7979    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7980    for details on setting local solver options.
7981 
7982    Most users should employ the simplified KSP interface for linear solvers
7983    instead of working directly with matrix algebra routines such as this.
7984    See, e.g., KSPCreate().
7985 
7986    Level: developer
7987 
7988 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7989 
7990 @*/
7991 PetscErrorCode MatSetUnfactored(Mat mat)
7992 {
7993   PetscFunctionBegin;
7994   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7995   PetscValidType(mat,1);
7996   MatCheckPreallocated(mat,1);
7997   mat->factortype = MAT_FACTOR_NONE;
7998   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
7999   PetscCall((*mat->ops->setunfactored)(mat));
8000   PetscFunctionReturn(0);
8001 }
8002 
8003 /*MC
8004     MatDenseGetArrayF90 - Accesses a matrix array from Fortran90.
8005 
8006     Synopsis:
8007     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8008 
8009     Not collective
8010 
8011     Input Parameter:
8012 .   x - matrix
8013 
8014     Output Parameters:
8015 +   xx_v - the Fortran90 pointer to the array
8016 -   ierr - error code
8017 
8018     Example of Usage:
8019 .vb
8020       PetscScalar, pointer xx_v(:,:)
8021       ....
8022       call MatDenseGetArrayF90(x,xx_v,ierr)
8023       a = xx_v(3)
8024       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8025 .ve
8026 
8027     Level: advanced
8028 
8029 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8030 
8031 M*/
8032 
8033 /*MC
8034     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8035     accessed with MatDenseGetArrayF90().
8036 
8037     Synopsis:
8038     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8039 
8040     Not collective
8041 
8042     Input Parameters:
8043 +   x - matrix
8044 -   xx_v - the Fortran90 pointer to the array
8045 
8046     Output Parameter:
8047 .   ierr - error code
8048 
8049     Example of Usage:
8050 .vb
8051        PetscScalar, pointer xx_v(:,:)
8052        ....
8053        call MatDenseGetArrayF90(x,xx_v,ierr)
8054        a = xx_v(3)
8055        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8056 .ve
8057 
8058     Level: advanced
8059 
8060 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8061 
8062 M*/
8063 
8064 /*MC
8065     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran90.
8066 
8067     Synopsis:
8068     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8069 
8070     Not collective
8071 
8072     Input Parameter:
8073 .   x - matrix
8074 
8075     Output Parameters:
8076 +   xx_v - the Fortran90 pointer to the array
8077 -   ierr - error code
8078 
8079     Example of Usage:
8080 .vb
8081       PetscScalar, pointer xx_v(:)
8082       ....
8083       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8084       a = xx_v(3)
8085       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8086 .ve
8087 
8088     Level: advanced
8089 
8090 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8091 
8092 M*/
8093 
8094 /*MC
8095     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8096     accessed with MatSeqAIJGetArrayF90().
8097 
8098     Synopsis:
8099     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8100 
8101     Not collective
8102 
8103     Input Parameters:
8104 +   x - matrix
8105 -   xx_v - the Fortran90 pointer to the array
8106 
8107     Output Parameter:
8108 .   ierr - error code
8109 
8110     Example of Usage:
8111 .vb
8112        PetscScalar, pointer xx_v(:)
8113        ....
8114        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8115        a = xx_v(3)
8116        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8117 .ve
8118 
8119     Level: advanced
8120 
8121 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8122 
8123 M*/
8124 
8125 /*@
8126     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8127                       as the original matrix.
8128 
8129     Collective on Mat
8130 
8131     Input Parameters:
8132 +   mat - the original matrix
8133 .   isrow - parallel IS containing the rows this processor should obtain
8134 .   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.
8135 -   cll - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
8136 
8137     Output Parameter:
8138 .   newmat - the new submatrix, of the same type as the old
8139 
8140     Level: advanced
8141 
8142     Notes:
8143     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8144 
8145     Some matrix types place restrictions on the row and column indices, such
8146     as that they be sorted or that they be equal to each other.
8147 
8148     The index sets may not have duplicate entries.
8149 
8150       The first time this is called you should use a cll of MAT_INITIAL_MATRIX,
8151    the MatCreateSubMatrix() routine will create the newmat for you. Any additional calls
8152    to this routine with a mat of the same nonzero structure and with a call of MAT_REUSE_MATRIX
8153    will reuse the matrix generated the first time.  You should call MatDestroy() on newmat when
8154    you are finished using it.
8155 
8156     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8157     the input matrix.
8158 
8159     If iscol is NULL then all columns are obtained (not supported in Fortran).
8160 
8161    Example usage:
8162    Consider the following 8x8 matrix with 34 non-zero values, that is
8163    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8164    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8165    as follows:
8166 
8167 .vb
8168             1  2  0  |  0  3  0  |  0  4
8169     Proc0   0  5  6  |  7  0  0  |  8  0
8170             9  0 10  | 11  0  0  | 12  0
8171     -------------------------------------
8172            13  0 14  | 15 16 17  |  0  0
8173     Proc1   0 18  0  | 19 20 21  |  0  0
8174             0  0  0  | 22 23  0  | 24  0
8175     -------------------------------------
8176     Proc2  25 26 27  |  0  0 28  | 29  0
8177            30  0  0  | 31 32 33  |  0 34
8178 .ve
8179 
8180     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8181 
8182 .vb
8183             2  0  |  0  3  0  |  0
8184     Proc0   5  6  |  7  0  0  |  8
8185     -------------------------------
8186     Proc1  18  0  | 19 20 21  |  0
8187     -------------------------------
8188     Proc2  26 27  |  0  0 28  | 29
8189             0  0  | 31 32 33  |  0
8190 .ve
8191 
8192 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8193 @*/
8194 PetscErrorCode MatCreateSubMatrix(Mat mat,IS isrow,IS iscol,MatReuse cll,Mat *newmat)
8195 {
8196   PetscMPIInt    size;
8197   Mat            *local;
8198   IS             iscoltmp;
8199   PetscBool      flg;
8200 
8201   PetscFunctionBegin;
8202   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8203   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
8204   if (iscol) PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
8205   PetscValidPointer(newmat,5);
8206   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat,MAT_CLASSID,5);
8207   PetscValidType(mat,1);
8208   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8209   PetscCheck(cll != MAT_IGNORE_MATRIX,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Cannot use MAT_IGNORE_MATRIX");
8210 
8211   MatCheckPreallocated(mat,1);
8212   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8213 
8214   if (!iscol || isrow == iscol) {
8215     PetscBool   stride;
8216     PetscMPIInt grabentirematrix = 0,grab;
8217     PetscCall(PetscObjectTypeCompare((PetscObject)isrow,ISSTRIDE,&stride));
8218     if (stride) {
8219       PetscInt first,step,n,rstart,rend;
8220       PetscCall(ISStrideGetInfo(isrow,&first,&step));
8221       if (step == 1) {
8222         PetscCall(MatGetOwnershipRange(mat,&rstart,&rend));
8223         if (rstart == first) {
8224           PetscCall(ISGetLocalSize(isrow,&n));
8225           if (n == rend-rstart) {
8226             grabentirematrix = 1;
8227           }
8228         }
8229       }
8230     }
8231     PetscCall(MPIU_Allreduce(&grabentirematrix,&grab,1,MPI_INT,MPI_MIN,PetscObjectComm((PetscObject)mat)));
8232     if (grab) {
8233       PetscCall(PetscInfo(mat,"Getting entire matrix as submatrix\n"));
8234       if (cll == MAT_INITIAL_MATRIX) {
8235         *newmat = mat;
8236         PetscCall(PetscObjectReference((PetscObject)mat));
8237       }
8238       PetscFunctionReturn(0);
8239     }
8240   }
8241 
8242   if (!iscol) {
8243     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat),mat->cmap->n,mat->cmap->rstart,1,&iscoltmp));
8244   } else {
8245     iscoltmp = iscol;
8246   }
8247 
8248   /* if original matrix is on just one processor then use submatrix generated */
8249   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8250     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_REUSE_MATRIX,&newmat));
8251     goto setproperties;
8252   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8253     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_INITIAL_MATRIX,&local));
8254     *newmat = *local;
8255     PetscCall(PetscFree(local));
8256     goto setproperties;
8257   } else if (!mat->ops->createsubmatrix) {
8258     /* Create a new matrix type that implements the operation using the full matrix */
8259     PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8260     switch (cll) {
8261     case MAT_INITIAL_MATRIX:
8262       PetscCall(MatCreateSubMatrixVirtual(mat,isrow,iscoltmp,newmat));
8263       break;
8264     case MAT_REUSE_MATRIX:
8265       PetscCall(MatSubMatrixVirtualUpdate(*newmat,mat,isrow,iscoltmp));
8266       break;
8267     default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8268     }
8269     PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8270     goto setproperties;
8271   }
8272 
8273   PetscCheck(mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8274   PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8275   PetscCall((*mat->ops->createsubmatrix)(mat,isrow,iscoltmp,cll,newmat));
8276   PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8277 
8278 setproperties:
8279   PetscCall(ISEqualUnsorted(isrow,iscoltmp,&flg));
8280   if (flg) PetscCall(MatPropagateSymmetryOptions(mat,*newmat));
8281   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8282   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8283   PetscFunctionReturn(0);
8284 }
8285 
8286 /*@
8287    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8288 
8289    Not Collective
8290 
8291    Input Parameters:
8292 +  A - the matrix we wish to propagate options from
8293 -  B - the matrix we wish to propagate options to
8294 
8295    Level: beginner
8296 
8297    Notes:
8298    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8299 
8300 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8301 @*/
8302 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8303 {
8304   PetscFunctionBegin;
8305   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8306   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
8307   B->symmetry_eternal            = A->symmetry_eternal;
8308   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8309   B->symmetric                   = A->symmetric;
8310   B->structurally_symmetric      = A->structurally_symmetric;
8311   B->spd                         = A->spd;
8312   B->hermitian                   = A->hermitian;
8313   PetscFunctionReturn(0);
8314 }
8315 
8316 /*@
8317    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8318    used during the assembly process to store values that belong to
8319    other processors.
8320 
8321    Not Collective
8322 
8323    Input Parameters:
8324 +  mat   - the matrix
8325 .  size  - the initial size of the stash.
8326 -  bsize - the initial size of the block-stash(if used).
8327 
8328    Options Database Keys:
8329 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8330 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8331 
8332    Level: intermediate
8333 
8334    Notes:
8335      The block-stash is used for values set with MatSetValuesBlocked() while
8336      the stash is used for values set with MatSetValues()
8337 
8338      Run with the option -info and look for output of the form
8339      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8340      to determine the appropriate value, MM, to use for size and
8341      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8342      to determine the value, BMM to use for bsize
8343 
8344 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8345 
8346 @*/
8347 PetscErrorCode MatStashSetInitialSize(Mat mat,PetscInt size, PetscInt bsize)
8348 {
8349   PetscFunctionBegin;
8350   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8351   PetscValidType(mat,1);
8352   PetscCall(MatStashSetInitialSize_Private(&mat->stash,size));
8353   PetscCall(MatStashSetInitialSize_Private(&mat->bstash,bsize));
8354   PetscFunctionReturn(0);
8355 }
8356 
8357 /*@
8358    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8359      the matrix
8360 
8361    Neighbor-wise Collective on Mat
8362 
8363    Input Parameters:
8364 +  mat   - the matrix
8365 .  x,y - the vectors
8366 -  w - where the result is stored
8367 
8368    Level: intermediate
8369 
8370    Notes:
8371     w may be the same vector as y.
8372 
8373     This allows one to use either the restriction or interpolation (its transpose)
8374     matrix to do the interpolation
8375 
8376 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8377 
8378 @*/
8379 PetscErrorCode MatInterpolateAdd(Mat A,Vec x,Vec y,Vec w)
8380 {
8381   PetscInt       M,N,Ny;
8382 
8383   PetscFunctionBegin;
8384   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8385   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8386   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8387   PetscValidHeaderSpecific(w,VEC_CLASSID,4);
8388   PetscCall(MatGetSize(A,&M,&N));
8389   PetscCall(VecGetSize(y,&Ny));
8390   if (M == Ny) {
8391     PetscCall(MatMultAdd(A,x,y,w));
8392   } else {
8393     PetscCall(MatMultTransposeAdd(A,x,y,w));
8394   }
8395   PetscFunctionReturn(0);
8396 }
8397 
8398 /*@
8399    MatInterpolate - y = A*x or A'*x depending on the shape of
8400      the matrix
8401 
8402    Neighbor-wise Collective on Mat
8403 
8404    Input Parameters:
8405 +  mat   - the matrix
8406 -  x,y - the vectors
8407 
8408    Level: intermediate
8409 
8410    Notes:
8411     This allows one to use either the restriction or interpolation (its transpose)
8412     matrix to do the interpolation
8413 
8414 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8415 
8416 @*/
8417 PetscErrorCode MatInterpolate(Mat A,Vec x,Vec y)
8418 {
8419   PetscInt       M,N,Ny;
8420 
8421   PetscFunctionBegin;
8422   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8423   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8424   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8425   PetscCall(MatGetSize(A,&M,&N));
8426   PetscCall(VecGetSize(y,&Ny));
8427   if (M == Ny) {
8428     PetscCall(MatMult(A,x,y));
8429   } else {
8430     PetscCall(MatMultTranspose(A,x,y));
8431   }
8432   PetscFunctionReturn(0);
8433 }
8434 
8435 /*@
8436    MatRestrict - y = A*x or A'*x
8437 
8438    Neighbor-wise Collective on Mat
8439 
8440    Input Parameters:
8441 +  mat   - the matrix
8442 -  x,y - the vectors
8443 
8444    Level: intermediate
8445 
8446    Notes:
8447     This allows one to use either the restriction or interpolation (its transpose)
8448     matrix to do the restriction
8449 
8450 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`
8451 
8452 @*/
8453 PetscErrorCode MatRestrict(Mat A,Vec x,Vec y)
8454 {
8455   PetscInt       M,N,Ny;
8456 
8457   PetscFunctionBegin;
8458   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8459   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8460   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8461   PetscCall(MatGetSize(A,&M,&N));
8462   PetscCall(VecGetSize(y,&Ny));
8463   if (M == Ny) {
8464     PetscCall(MatMult(A,x,y));
8465   } else {
8466     PetscCall(MatMultTranspose(A,x,y));
8467   }
8468   PetscFunctionReturn(0);
8469 }
8470 
8471 /*@
8472    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8473 
8474    Neighbor-wise Collective on Mat
8475 
8476    Input Parameters:
8477 +  mat   - the matrix
8478 -  w, x - the input dense matrices
8479 
8480    Output Parameters:
8481 .  y - the output dense matrix
8482 
8483    Level: intermediate
8484 
8485    Notes:
8486     This allows one to use either the restriction or interpolation (its transpose)
8487     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8488     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8489 
8490 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`
8491 
8492 @*/
8493 PetscErrorCode MatMatInterpolateAdd(Mat A,Mat x,Mat w,Mat *y)
8494 {
8495   PetscInt       M,N,Mx,Nx,Mo,My = 0,Ny = 0;
8496   PetscBool      trans = PETSC_TRUE;
8497   MatReuse       reuse = MAT_INITIAL_MATRIX;
8498 
8499   PetscFunctionBegin;
8500   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8501   PetscValidHeaderSpecific(x,MAT_CLASSID,2);
8502   PetscValidType(x,2);
8503   if (w) PetscValidHeaderSpecific(w,MAT_CLASSID,3);
8504   if (*y) PetscValidHeaderSpecific(*y,MAT_CLASSID,4);
8505   PetscCall(MatGetSize(A,&M,&N));
8506   PetscCall(MatGetSize(x,&Mx,&Nx));
8507   if (N == Mx) trans = PETSC_FALSE;
8508   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);
8509   Mo = trans ? N : M;
8510   if (*y) {
8511     PetscCall(MatGetSize(*y,&My,&Ny));
8512     if (Mo == My && Nx == Ny) { reuse = MAT_REUSE_MATRIX; }
8513     else {
8514       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);
8515       PetscCall(MatDestroy(y));
8516     }
8517   }
8518 
8519   if (w && *y == w) { /* this is to minimize changes in PCMG */
8520     PetscBool flg;
8521 
8522     PetscCall(PetscObjectQuery((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject*)&w));
8523     if (w) {
8524       PetscInt My,Ny,Mw,Nw;
8525 
8526       PetscCall(PetscObjectTypeCompare((PetscObject)*y,((PetscObject)w)->type_name,&flg));
8527       PetscCall(MatGetSize(*y,&My,&Ny));
8528       PetscCall(MatGetSize(w,&Mw,&Nw));
8529       if (!flg || My != Mw || Ny != Nw) w = NULL;
8530     }
8531     if (!w) {
8532       PetscCall(MatDuplicate(*y,MAT_COPY_VALUES,&w));
8533       PetscCall(PetscObjectCompose((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject)w));
8534       PetscCall(PetscLogObjectParent((PetscObject)*y,(PetscObject)w));
8535       PetscCall(PetscObjectDereference((PetscObject)w));
8536     } else {
8537       PetscCall(MatCopy(*y,w,UNKNOWN_NONZERO_PATTERN));
8538     }
8539   }
8540   if (!trans) {
8541     PetscCall(MatMatMult(A,x,reuse,PETSC_DEFAULT,y));
8542   } else {
8543     PetscCall(MatTransposeMatMult(A,x,reuse,PETSC_DEFAULT,y));
8544   }
8545   if (w) PetscCall(MatAXPY(*y,1.0,w,UNKNOWN_NONZERO_PATTERN));
8546   PetscFunctionReturn(0);
8547 }
8548 
8549 /*@
8550    MatMatInterpolate - Y = A*X or A'*X
8551 
8552    Neighbor-wise Collective on Mat
8553 
8554    Input Parameters:
8555 +  mat   - the matrix
8556 -  x - the input dense matrix
8557 
8558    Output Parameters:
8559 .  y - the output dense matrix
8560 
8561    Level: intermediate
8562 
8563    Notes:
8564     This allows one to use either the restriction or interpolation (its transpose)
8565     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8566     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8567 
8568 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`
8569 
8570 @*/
8571 PetscErrorCode MatMatInterpolate(Mat A,Mat x,Mat *y)
8572 {
8573   PetscFunctionBegin;
8574   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8575   PetscFunctionReturn(0);
8576 }
8577 
8578 /*@
8579    MatMatRestrict - Y = A*X or A'*X
8580 
8581    Neighbor-wise Collective on Mat
8582 
8583    Input Parameters:
8584 +  mat   - the matrix
8585 -  x - the input dense matrix
8586 
8587    Output Parameters:
8588 .  y - the output dense matrix
8589 
8590    Level: intermediate
8591 
8592    Notes:
8593     This allows one to use either the restriction or interpolation (its transpose)
8594     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8595     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8596 
8597 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`
8598 @*/
8599 PetscErrorCode MatMatRestrict(Mat A,Mat x,Mat *y)
8600 {
8601   PetscFunctionBegin;
8602   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8603   PetscFunctionReturn(0);
8604 }
8605 
8606 /*@
8607    MatGetNullSpace - retrieves the null space of a matrix.
8608 
8609    Logically Collective on Mat
8610 
8611    Input Parameters:
8612 +  mat - the matrix
8613 -  nullsp - the null space object
8614 
8615    Level: developer
8616 
8617 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`
8618 @*/
8619 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8620 {
8621   PetscFunctionBegin;
8622   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8623   PetscValidPointer(nullsp,2);
8624   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8625   PetscFunctionReturn(0);
8626 }
8627 
8628 /*@
8629    MatSetNullSpace - attaches a null space to a matrix.
8630 
8631    Logically Collective on Mat
8632 
8633    Input Parameters:
8634 +  mat - the matrix
8635 -  nullsp - the null space object
8636 
8637    Level: advanced
8638 
8639    Notes:
8640       This null space is used by the KSP linear solvers to solve singular systems.
8641 
8642       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
8643 
8644       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
8645       to zero but the linear system will still be solved in a least squares sense.
8646 
8647       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8648    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).
8649    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
8650    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
8651    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).
8652    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8653 
8654     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
8655     routine also automatically calls MatSetTransposeNullSpace().
8656 
8657     The user should call `MatNullSpaceDestroy()`.
8658 
8659 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8660           `KSPSetPCSide()`
8661 @*/
8662 PetscErrorCode MatSetNullSpace(Mat mat,MatNullSpace nullsp)
8663 {
8664   PetscFunctionBegin;
8665   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8666   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8667   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8668   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8669   mat->nullsp = nullsp;
8670   if (mat->symmetric == PETSC_BOOL3_TRUE) {
8671     PetscCall(MatSetTransposeNullSpace(mat,nullsp));
8672   }
8673   PetscFunctionReturn(0);
8674 }
8675 
8676 /*@
8677    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8678 
8679    Logically Collective on Mat
8680 
8681    Input Parameters:
8682 +  mat - the matrix
8683 -  nullsp - the null space object
8684 
8685    Level: developer
8686 
8687 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8688 @*/
8689 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8690 {
8691   PetscFunctionBegin;
8692   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8693   PetscValidType(mat,1);
8694   PetscValidPointer(nullsp,2);
8695   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8696   PetscFunctionReturn(0);
8697 }
8698 
8699 /*@
8700    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8701 
8702    Logically Collective on Mat
8703 
8704    Input Parameters:
8705 +  mat - the matrix
8706 -  nullsp - the null space object
8707 
8708    Level: advanced
8709 
8710    Notes:
8711       This allows solving singular linear systems defined by the transpose of the matrix using KSP solvers with left preconditioning.
8712 
8713       See MatSetNullSpace()
8714 
8715 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8716 @*/
8717 PetscErrorCode MatSetTransposeNullSpace(Mat mat,MatNullSpace nullsp)
8718 {
8719   PetscFunctionBegin;
8720   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8721   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8722   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8723   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8724   mat->transnullsp = nullsp;
8725   PetscFunctionReturn(0);
8726 }
8727 
8728 /*@
8729    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8730         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8731 
8732    Logically Collective on Mat
8733 
8734    Input Parameters:
8735 +  mat - the matrix
8736 -  nullsp - the null space object
8737 
8738    Level: advanced
8739 
8740    Notes:
8741       Overwrites any previous near null space that may have been attached
8742 
8743       You can remove the null space by calling this routine with an nullsp of NULL
8744 
8745 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8746 @*/
8747 PetscErrorCode MatSetNearNullSpace(Mat mat,MatNullSpace nullsp)
8748 {
8749   PetscFunctionBegin;
8750   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8751   PetscValidType(mat,1);
8752   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8753   MatCheckPreallocated(mat,1);
8754   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8755   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8756   mat->nearnullsp = nullsp;
8757   PetscFunctionReturn(0);
8758 }
8759 
8760 /*@
8761    MatGetNearNullSpace - Get null space attached with MatSetNearNullSpace()
8762 
8763    Not Collective
8764 
8765    Input Parameter:
8766 .  mat - the matrix
8767 
8768    Output Parameter:
8769 .  nullsp - the null space object, NULL if not set
8770 
8771    Level: developer
8772 
8773 .seealso: `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8774 @*/
8775 PetscErrorCode MatGetNearNullSpace(Mat mat,MatNullSpace *nullsp)
8776 {
8777   PetscFunctionBegin;
8778   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8779   PetscValidType(mat,1);
8780   PetscValidPointer(nullsp,2);
8781   MatCheckPreallocated(mat,1);
8782   *nullsp = mat->nearnullsp;
8783   PetscFunctionReturn(0);
8784 }
8785 
8786 /*@C
8787    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8788 
8789    Collective on Mat
8790 
8791    Input Parameters:
8792 +  mat - the matrix
8793 .  row - row/column permutation
8794 .  fill - expected fill factor >= 1.0
8795 -  level - level of fill, for ICC(k)
8796 
8797    Notes:
8798    Probably really in-place only when level of fill is zero, otherwise allocates
8799    new space to store factored matrix and deletes previous memory.
8800 
8801    Most users should employ the simplified KSP interface for linear solvers
8802    instead of working directly with matrix algebra routines such as this.
8803    See, e.g., KSPCreate().
8804 
8805    Level: developer
8806 
8807 .seealso: `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8808 
8809     Developer Note: fortran interface is not autogenerated as the f90
8810     interface definition cannot be generated correctly [due to MatFactorInfo]
8811 
8812 @*/
8813 PetscErrorCode MatICCFactor(Mat mat,IS row,const MatFactorInfo *info)
8814 {
8815   PetscFunctionBegin;
8816   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8817   PetscValidType(mat,1);
8818   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
8819   PetscValidPointer(info,3);
8820   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
8821   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
8822   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8823   PetscCheck(mat->ops->iccfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8824   MatCheckPreallocated(mat,1);
8825   PetscCall((*mat->ops->iccfactor)(mat,row,info));
8826   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8827   PetscFunctionReturn(0);
8828 }
8829 
8830 /*@
8831    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8832          ghosted ones.
8833 
8834    Not Collective
8835 
8836    Input Parameters:
8837 +  mat - the matrix
8838 -  diag - the diagonal values, including ghost ones
8839 
8840    Level: developer
8841 
8842    Notes:
8843     Works only for MPIAIJ and MPIBAIJ matrices
8844 
8845 .seealso: `MatDiagonalScale()`
8846 @*/
8847 PetscErrorCode MatDiagonalScaleLocal(Mat mat,Vec diag)
8848 {
8849   PetscMPIInt    size;
8850 
8851   PetscFunctionBegin;
8852   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8853   PetscValidHeaderSpecific(diag,VEC_CLASSID,2);
8854   PetscValidType(mat,1);
8855 
8856   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be already assembled");
8857   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
8858   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8859   if (size == 1) {
8860     PetscInt n,m;
8861     PetscCall(VecGetSize(diag,&n));
8862     PetscCall(MatGetSize(mat,NULL,&m));
8863     if (m == n) {
8864       PetscCall(MatDiagonalScale(mat,NULL,diag));
8865     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only supported for sequential matrices when no ghost points/periodic conditions");
8866   } else {
8867     PetscUseMethod(mat,"MatDiagonalScaleLocal_C",(Mat,Vec),(mat,diag));
8868   }
8869   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
8870   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8871   PetscFunctionReturn(0);
8872 }
8873 
8874 /*@
8875    MatGetInertia - Gets the inertia from a factored matrix
8876 
8877    Collective on Mat
8878 
8879    Input Parameter:
8880 .  mat - the matrix
8881 
8882    Output Parameters:
8883 +   nneg - number of negative eigenvalues
8884 .   nzero - number of zero eigenvalues
8885 -   npos - number of positive eigenvalues
8886 
8887    Level: advanced
8888 
8889    Notes:
8890     Matrix must have been factored by MatCholeskyFactor()
8891 
8892 @*/
8893 PetscErrorCode MatGetInertia(Mat mat,PetscInt *nneg,PetscInt *nzero,PetscInt *npos)
8894 {
8895   PetscFunctionBegin;
8896   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8897   PetscValidType(mat,1);
8898   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
8899   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Numeric factor mat is not assembled");
8900   PetscCheck(mat->ops->getinertia,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8901   PetscCall((*mat->ops->getinertia)(mat,nneg,nzero,npos));
8902   PetscFunctionReturn(0);
8903 }
8904 
8905 /* ----------------------------------------------------------------*/
8906 /*@C
8907    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8908 
8909    Neighbor-wise Collective on Mats
8910 
8911    Input Parameters:
8912 +  mat - the factored matrix
8913 -  b - the right-hand-side vectors
8914 
8915    Output Parameter:
8916 .  x - the result vectors
8917 
8918    Notes:
8919    The vectors b and x cannot be the same.  I.e., one cannot
8920    call MatSolves(A,x,x).
8921 
8922    Notes:
8923    Most users should employ the simplified KSP interface for linear solvers
8924    instead of working directly with matrix algebra routines such as this.
8925    See, e.g., KSPCreate().
8926 
8927    Level: developer
8928 
8929 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8930 @*/
8931 PetscErrorCode MatSolves(Mat mat,Vecs b,Vecs x)
8932 {
8933   PetscFunctionBegin;
8934   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8935   PetscValidType(mat,1);
8936   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
8937   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
8938   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
8939 
8940   PetscCheck(mat->ops->solves,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8941   MatCheckPreallocated(mat,1);
8942   PetscCall(PetscLogEventBegin(MAT_Solves,mat,0,0,0));
8943   PetscCall((*mat->ops->solves)(mat,b,x));
8944   PetscCall(PetscLogEventEnd(MAT_Solves,mat,0,0,0));
8945   PetscFunctionReturn(0);
8946 }
8947 
8948 /*@
8949    MatIsSymmetric - Test whether a matrix is symmetric
8950 
8951    Collective on Mat
8952 
8953    Input Parameters:
8954 +  A - the matrix to test
8955 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8956 
8957    Output Parameters:
8958 .  flg - the result
8959 
8960    Notes:
8961     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
8962 
8963     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
8964 
8965    Level: intermediate
8966 
8967 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`
8968 @*/
8969 PetscErrorCode MatIsSymmetric(Mat A,PetscReal tol,PetscBool *flg)
8970 {
8971   PetscFunctionBegin;
8972   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8973   PetscValidBoolPointer(flg,3);
8974 
8975   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8976   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8977   else {
8978     if (!A->ops->issymmetric) {
8979       MatType mattype;
8980       PetscCall(MatGetType(A,&mattype));
8981       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for symmetric",mattype);
8982     }
8983     PetscCall((*A->ops->issymmetric)(A,tol,flg));
8984     if (!tol) PetscCall(MatSetOption(A,MAT_SYMMETRIC,*flg));
8985   }
8986   PetscFunctionReturn(0);
8987 }
8988 
8989 /*@
8990    MatIsHermitian - Test whether a matrix is Hermitian
8991 
8992    Collective on Mat
8993 
8994    Input Parameters:
8995 +  A - the matrix to test
8996 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8997 
8998    Output Parameters:
8999 .  flg - the result
9000 
9001    Level: intermediate
9002 
9003    Notes:
9004     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
9005 
9006     If the matrix does not yet know if it is hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9007 
9008 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9009           `MatIsSymmetricKnown()`, `MatIsSymmetric()`
9010 @*/
9011 PetscErrorCode MatIsHermitian(Mat A,PetscReal tol,PetscBool *flg)
9012 {
9013   PetscFunctionBegin;
9014   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9015   PetscValidBoolPointer(flg,3);
9016 
9017   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9018   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9019   else {
9020     if (!A->ops->ishermitian) {
9021       MatType mattype;
9022       PetscCall(MatGetType(A,&mattype));
9023       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for hermitian",mattype);
9024     }
9025     PetscCall((*A->ops->ishermitian)(A,tol,flg));
9026     if (!tol) PetscCall(MatSetOption(A,MAT_HERMITIAN,*flg));
9027   }
9028   PetscFunctionReturn(0);
9029 }
9030 
9031 /*@
9032    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9033 
9034    Not Collective
9035 
9036    Input Parameter:
9037 .  A - the matrix to check
9038 
9039    Output Parameters:
9040 +  set - PETSC_TRUE if the matrix knows its symmetry state (this tells you if the next flag is valid)
9041 -  flg - the result (only valid if set is PETSC_TRUE)
9042 
9043    Level: advanced
9044 
9045    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsSymmetric()
9046          if you want it explicitly checked
9047 
9048 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9049 @*/
9050 PetscErrorCode MatIsSymmetricKnown(Mat A,PetscBool *set,PetscBool *flg)
9051 {
9052   PetscFunctionBegin;
9053   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9054   PetscValidBoolPointer(set,2);
9055   PetscValidBoolPointer(flg,3);
9056   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9057     *set = PETSC_TRUE;
9058     *flg = PetscBool3ToBool(A->symmetric);
9059   } else {
9060     *set = PETSC_FALSE;
9061   }
9062   PetscFunctionReturn(0);
9063 }
9064 
9065 /*@
9066    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9067 
9068    Not Collective
9069 
9070    Input Parameter:
9071 .  A - the matrix to check
9072 
9073    Output Parameters:
9074 +  set - PETSC_TRUE if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9075 -  flg - the result (only valid if set is PETSC_TRUE)
9076 
9077    Level: advanced
9078 
9079    Note:
9080    Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE).
9081 
9082 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9083 @*/
9084 PetscErrorCode MatIsSPDKnown(Mat A,PetscBool *set,PetscBool *flg)
9085 {
9086   PetscFunctionBegin;
9087   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9088   PetscValidBoolPointer(set,2);
9089   PetscValidBoolPointer(flg,3);
9090   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9091     *set = PETSC_TRUE;
9092     *flg = PetscBool3ToBool(A->spd);
9093   } else {
9094     *set = PETSC_FALSE;
9095   }
9096   PetscFunctionReturn(0);
9097 }
9098 
9099 /*@
9100    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9101 
9102    Not Collective
9103 
9104    Input Parameter:
9105 .  A - the matrix to check
9106 
9107    Output Parameters:
9108 +  set - PETSC_TRUE if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9109 -  flg - the result (only valid if set is PETSC_TRUE)
9110 
9111    Level: advanced
9112 
9113    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsHermitian()
9114          if you want it explicitly checked
9115 
9116 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9117 @*/
9118 PetscErrorCode MatIsHermitianKnown(Mat A,PetscBool *set,PetscBool *flg)
9119 {
9120   PetscFunctionBegin;
9121   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9122   PetscValidBoolPointer(set,2);
9123   PetscValidBoolPointer(flg,3);
9124   if (A->hermitian  != PETSC_BOOL3_UNKNOWN) {
9125     *set = PETSC_TRUE;
9126     *flg = PetscBool3ToBool(A->hermitian);
9127   } else {
9128     *set = PETSC_FALSE;
9129   }
9130   PetscFunctionReturn(0);
9131 }
9132 
9133 /*@
9134    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9135 
9136    Collective on Mat
9137 
9138    Input Parameter:
9139 .  A - the matrix to test
9140 
9141    Output Parameters:
9142 .  flg - the result
9143 
9144    Notes:
9145       If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9146 
9147    Level: intermediate
9148 
9149 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9150 @*/
9151 PetscErrorCode MatIsStructurallySymmetric(Mat A,PetscBool *flg)
9152 {
9153   PetscFunctionBegin;
9154   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9155   PetscValidBoolPointer(flg,2);
9156   if (A->structurally_symmetric  != PETSC_BOOL3_UNKNOWN) {
9157     *flg = PetscBool3ToBool(A->structurally_symmetric);
9158   } else {
9159     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);
9160     PetscCall((*A->ops->isstructurallysymmetric)(A,flg));
9161     PetscCall(MatSetOption(A,MAT_STRUCTURALLY_SYMMETRIC,*flg));
9162   }
9163   PetscFunctionReturn(0);
9164 }
9165 
9166 /*@
9167    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9168 
9169    Not Collective
9170 
9171    Input Parameter:
9172 .  A - the matrix to check
9173 
9174    Output Parameters:
9175 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9176 -  flg - the result (only valid if set is PETSC_TRUE)
9177 
9178    Level: advanced
9179 
9180 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9181 @*/
9182 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A,PetscBool *set,PetscBool *flg)
9183 {
9184   PetscFunctionBegin;
9185   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9186   PetscValidBoolPointer(set,2);
9187   PetscValidBoolPointer(flg,3);
9188   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9189     *set = PETSC_TRUE;
9190     *flg = PetscBool3ToBool(A->structurally_symmetric);
9191   } else {
9192     *set = PETSC_FALSE;
9193   }
9194   PetscFunctionReturn(0);
9195 }
9196 
9197 /*@
9198    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9199        to be communicated to other processors during the MatAssemblyBegin/End() process
9200 
9201     Not collective
9202 
9203    Input Parameter:
9204 .   vec - the vector
9205 
9206    Output Parameters:
9207 +   nstash   - the size of the stash
9208 .   reallocs - the number of additional mallocs incurred.
9209 .   bnstash   - the size of the block stash
9210 -   breallocs - the number of additional mallocs incurred.in the block stash
9211 
9212    Level: advanced
9213 
9214 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9215 
9216 @*/
9217 PetscErrorCode MatStashGetInfo(Mat mat,PetscInt *nstash,PetscInt *reallocs,PetscInt *bnstash,PetscInt *breallocs)
9218 {
9219   PetscFunctionBegin;
9220   PetscCall(MatStashGetInfo_Private(&mat->stash,nstash,reallocs));
9221   PetscCall(MatStashGetInfo_Private(&mat->bstash,bnstash,breallocs));
9222   PetscFunctionReturn(0);
9223 }
9224 
9225 /*@C
9226    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9227      parallel layout
9228 
9229    Collective on Mat
9230 
9231    Input Parameter:
9232 .  mat - the matrix
9233 
9234    Output Parameters:
9235 +   right - (optional) vector that the matrix can be multiplied against
9236 -   left - (optional) vector that the matrix vector product can be stored in
9237 
9238    Notes:
9239     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().
9240 
9241   Notes:
9242     These are new vectors which are not owned by the Mat, they should be destroyed in VecDestroy() when no longer needed
9243 
9244   Level: advanced
9245 
9246 .seealso: `MatCreate()`, `VecDestroy()`
9247 @*/
9248 PetscErrorCode MatCreateVecs(Mat mat,Vec *right,Vec *left)
9249 {
9250   PetscFunctionBegin;
9251   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9252   PetscValidType(mat,1);
9253   if (mat->ops->getvecs) {
9254     PetscCall((*mat->ops->getvecs)(mat,right,left));
9255   } else {
9256     PetscInt rbs,cbs;
9257     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
9258     if (right) {
9259       PetscCheck(mat->cmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for columns not yet setup");
9260       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),right));
9261       PetscCall(VecSetSizes(*right,mat->cmap->n,PETSC_DETERMINE));
9262       PetscCall(VecSetBlockSize(*right,cbs));
9263       PetscCall(VecSetType(*right,mat->defaultvectype));
9264 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9265       if (mat->boundtocpu && mat->bindingpropagates) {
9266         PetscCall(VecSetBindingPropagates(*right,PETSC_TRUE));
9267         PetscCall(VecBindToCPU(*right,PETSC_TRUE));
9268       }
9269 #endif
9270       PetscCall(PetscLayoutReference(mat->cmap,&(*right)->map));
9271     }
9272     if (left) {
9273       PetscCheck(mat->rmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for rows not yet setup");
9274       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),left));
9275       PetscCall(VecSetSizes(*left,mat->rmap->n,PETSC_DETERMINE));
9276       PetscCall(VecSetBlockSize(*left,rbs));
9277       PetscCall(VecSetType(*left,mat->defaultvectype));
9278 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9279       if (mat->boundtocpu && mat->bindingpropagates) {
9280         PetscCall(VecSetBindingPropagates(*left,PETSC_TRUE));
9281         PetscCall(VecBindToCPU(*left,PETSC_TRUE));
9282       }
9283 #endif
9284       PetscCall(PetscLayoutReference(mat->rmap,&(*left)->map));
9285     }
9286   }
9287   PetscFunctionReturn(0);
9288 }
9289 
9290 /*@C
9291    MatFactorInfoInitialize - Initializes a MatFactorInfo data structure
9292      with default values.
9293 
9294    Not Collective
9295 
9296    Input Parameters:
9297 .    info - the MatFactorInfo data structure
9298 
9299    Notes:
9300     The solvers are generally used through the KSP and PC objects, for example
9301           PCLU, PCILU, PCCHOLESKY, PCICC
9302 
9303    Level: developer
9304 
9305 .seealso: `MatFactorInfo`
9306 
9307     Developer Note: fortran interface is not autogenerated as the f90
9308     interface definition cannot be generated correctly [due to MatFactorInfo]
9309 
9310 @*/
9311 
9312 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9313 {
9314   PetscFunctionBegin;
9315   PetscCall(PetscMemzero(info,sizeof(MatFactorInfo)));
9316   PetscFunctionReturn(0);
9317 }
9318 
9319 /*@
9320    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9321 
9322    Collective on Mat
9323 
9324    Input Parameters:
9325 +  mat - the factored matrix
9326 -  is - the index set defining the Schur indices (0-based)
9327 
9328    Notes:
9329     Call MatFactorSolveSchurComplement() or MatFactorSolveSchurComplementTranspose() after this call to solve a Schur complement system.
9330 
9331    You can call MatFactorGetSchurComplement() or MatFactorCreateSchurComplement() after this call.
9332 
9333    Level: developer
9334 
9335 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9336           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`
9337 
9338 @*/
9339 PetscErrorCode MatFactorSetSchurIS(Mat mat,IS is)
9340 {
9341   PetscErrorCode (*f)(Mat,IS);
9342 
9343   PetscFunctionBegin;
9344   PetscValidType(mat,1);
9345   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9346   PetscValidType(is,2);
9347   PetscValidHeaderSpecific(is,IS_CLASSID,2);
9348   PetscCheckSameComm(mat,1,is,2);
9349   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
9350   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorSetSchurIS_C",&f));
9351   PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9352   PetscCall(MatDestroy(&mat->schur));
9353   PetscCall((*f)(mat,is));
9354   PetscCheck(mat->schur,PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Schur complement has not been created");
9355   PetscFunctionReturn(0);
9356 }
9357 
9358 /*@
9359   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9360 
9361    Logically Collective on Mat
9362 
9363    Input Parameters:
9364 +  F - the factored matrix obtained by calling MatGetFactor() from PETSc-MUMPS interface
9365 .  S - location where to return the Schur complement, can be NULL
9366 -  status - the status of the Schur complement matrix, can be NULL
9367 
9368    Notes:
9369    You must call MatFactorSetSchurIS() before calling this routine.
9370 
9371    The routine provides a copy of the Schur matrix stored within the solver data structures.
9372    The caller must destroy the object when it is no longer needed.
9373    If MatFactorInvertSchurComplement() has been called, the routine gets back the inverse.
9374 
9375    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)
9376 
9377    Developer Notes:
9378     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9379    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9380 
9381    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9382 
9383    Level: advanced
9384 
9385    References:
9386 
9387 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`
9388 @*/
9389 PetscErrorCode MatFactorCreateSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9390 {
9391   PetscFunctionBegin;
9392   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9393   if (S) PetscValidPointer(S,2);
9394   if (status) PetscValidPointer(status,3);
9395   if (S) {
9396     PetscErrorCode (*f)(Mat,Mat*);
9397 
9398     PetscCall(PetscObjectQueryFunction((PetscObject)F,"MatFactorCreateSchurComplement_C",&f));
9399     if (f) {
9400       PetscCall((*f)(F,S));
9401     } else {
9402       PetscCall(MatDuplicate(F->schur,MAT_COPY_VALUES,S));
9403     }
9404   }
9405   if (status) *status = F->schur_status;
9406   PetscFunctionReturn(0);
9407 }
9408 
9409 /*@
9410   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9411 
9412    Logically Collective on Mat
9413 
9414    Input Parameters:
9415 +  F - the factored matrix obtained by calling MatGetFactor()
9416 .  *S - location where to return the Schur complement, can be NULL
9417 -  status - the status of the Schur complement matrix, can be NULL
9418 
9419    Notes:
9420    You must call MatFactorSetSchurIS() before calling this routine.
9421 
9422    Schur complement mode is currently implemented for sequential matrices.
9423    The routine returns a the Schur Complement stored within the data strutures of the solver.
9424    If MatFactorInvertSchurComplement() has previously been called, the returned matrix is actually the inverse of the Schur complement.
9425    The returned matrix should not be destroyed; the caller should call MatFactorRestoreSchurComplement() when the object is no longer needed.
9426 
9427    Use MatFactorCreateSchurComplement() to create a copy of the Schur complement matrix that is within a factored matrix
9428 
9429    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9430 
9431    Level: advanced
9432 
9433    References:
9434 
9435 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9436 @*/
9437 PetscErrorCode MatFactorGetSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9438 {
9439   PetscFunctionBegin;
9440   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9441   if (S) PetscValidPointer(S,2);
9442   if (status) PetscValidPointer(status,3);
9443   if (S) *S = F->schur;
9444   if (status) *status = F->schur_status;
9445   PetscFunctionReturn(0);
9446 }
9447 
9448 /*@
9449   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to MatFactorGetSchurComplement
9450 
9451    Logically Collective on Mat
9452 
9453    Input Parameters:
9454 +  F - the factored matrix obtained by calling MatGetFactor()
9455 .  *S - location where the Schur complement is stored
9456 -  status - the status of the Schur complement matrix (see MatFactorSchurStatus)
9457 
9458    Notes:
9459 
9460    Level: advanced
9461 
9462    References:
9463 
9464 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9465 @*/
9466 PetscErrorCode MatFactorRestoreSchurComplement(Mat F,Mat* S,MatFactorSchurStatus status)
9467 {
9468   PetscFunctionBegin;
9469   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9470   if (S) {
9471     PetscValidHeaderSpecific(*S,MAT_CLASSID,2);
9472     *S = NULL;
9473   }
9474   F->schur_status = status;
9475   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9476   PetscFunctionReturn(0);
9477 }
9478 
9479 /*@
9480   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9481 
9482    Logically Collective on Mat
9483 
9484    Input Parameters:
9485 +  F - the factored matrix obtained by calling MatGetFactor()
9486 .  rhs - location where the right hand side of the Schur complement system is stored
9487 -  sol - location where the solution of the Schur complement system has to be returned
9488 
9489    Notes:
9490    The sizes of the vectors should match the size of the Schur complement
9491 
9492    Must be called after MatFactorSetSchurIS()
9493 
9494    Level: advanced
9495 
9496    References:
9497 
9498 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9499 @*/
9500 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9501 {
9502   PetscFunctionBegin;
9503   PetscValidType(F,1);
9504   PetscValidType(rhs,2);
9505   PetscValidType(sol,3);
9506   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9507   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9508   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9509   PetscCheckSameComm(F,1,rhs,2);
9510   PetscCheckSameComm(F,1,sol,3);
9511   PetscCall(MatFactorFactorizeSchurComplement(F));
9512   switch (F->schur_status) {
9513   case MAT_FACTOR_SCHUR_FACTORED:
9514     PetscCall(MatSolveTranspose(F->schur,rhs,sol));
9515     break;
9516   case MAT_FACTOR_SCHUR_INVERTED:
9517     PetscCall(MatMultTranspose(F->schur,rhs,sol));
9518     break;
9519   default:
9520     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9521   }
9522   PetscFunctionReturn(0);
9523 }
9524 
9525 /*@
9526   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9527 
9528    Logically Collective on Mat
9529 
9530    Input Parameters:
9531 +  F - the factored matrix obtained by calling MatGetFactor()
9532 .  rhs - location where the right hand side of the Schur complement system is stored
9533 -  sol - location where the solution of the Schur complement system has to be returned
9534 
9535    Notes:
9536    The sizes of the vectors should match the size of the Schur complement
9537 
9538    Must be called after MatFactorSetSchurIS()
9539 
9540    Level: advanced
9541 
9542    References:
9543 
9544 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9545 @*/
9546 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9547 {
9548   PetscFunctionBegin;
9549   PetscValidType(F,1);
9550   PetscValidType(rhs,2);
9551   PetscValidType(sol,3);
9552   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9553   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9554   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9555   PetscCheckSameComm(F,1,rhs,2);
9556   PetscCheckSameComm(F,1,sol,3);
9557   PetscCall(MatFactorFactorizeSchurComplement(F));
9558   switch (F->schur_status) {
9559   case MAT_FACTOR_SCHUR_FACTORED:
9560     PetscCall(MatSolve(F->schur,rhs,sol));
9561     break;
9562   case MAT_FACTOR_SCHUR_INVERTED:
9563     PetscCall(MatMult(F->schur,rhs,sol));
9564     break;
9565   default:
9566     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9567   }
9568   PetscFunctionReturn(0);
9569 }
9570 
9571 /*@
9572   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9573 
9574    Logically Collective on Mat
9575 
9576    Input Parameters:
9577 .  F - the factored matrix obtained by calling MatGetFactor()
9578 
9579    Notes:
9580     Must be called after MatFactorSetSchurIS().
9581 
9582    Call MatFactorGetSchurComplement() or  MatFactorCreateSchurComplement() AFTER this call to actually compute the inverse and get access to it.
9583 
9584    Level: advanced
9585 
9586    References:
9587 
9588 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9589 @*/
9590 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9591 {
9592   PetscFunctionBegin;
9593   PetscValidType(F,1);
9594   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9595   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9596   PetscCall(MatFactorFactorizeSchurComplement(F));
9597   PetscCall(MatFactorInvertSchurComplement_Private(F));
9598   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9599   PetscFunctionReturn(0);
9600 }
9601 
9602 /*@
9603   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9604 
9605    Logically Collective on Mat
9606 
9607    Input Parameters:
9608 .  F - the factored matrix obtained by calling MatGetFactor()
9609 
9610    Notes:
9611     Must be called after MatFactorSetSchurIS().
9612 
9613    Level: advanced
9614 
9615    References:
9616 
9617 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9618 @*/
9619 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9620 {
9621   PetscFunctionBegin;
9622   PetscValidType(F,1);
9623   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9624   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9625   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9626   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9627   PetscFunctionReturn(0);
9628 }
9629 
9630 /*@
9631    MatPtAP - Creates the matrix product C = P^T * A * P
9632 
9633    Neighbor-wise Collective on Mat
9634 
9635    Input Parameters:
9636 +  A - the matrix
9637 .  P - the projection matrix
9638 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9639 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use PETSC_DEFAULT if you do not have a good estimate
9640           if the result is a dense matrix this is irrelevant
9641 
9642    Output Parameters:
9643 .  C - the product matrix
9644 
9645    Notes:
9646    C will be created and must be destroyed by the user with MatDestroy().
9647 
9648    For matrix types without special implementation the function fallbacks to MatMatMult() followed by MatTransposeMatMult().
9649 
9650    Level: intermediate
9651 
9652 .seealso: `MatMatMult()`, `MatRARt()`
9653 @*/
9654 PetscErrorCode MatPtAP(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
9655 {
9656   PetscFunctionBegin;
9657   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9658   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9659 
9660   if (scall == MAT_INITIAL_MATRIX) {
9661     PetscCall(MatProductCreate(A,P,NULL,C));
9662     PetscCall(MatProductSetType(*C,MATPRODUCT_PtAP));
9663     PetscCall(MatProductSetAlgorithm(*C,"default"));
9664     PetscCall(MatProductSetFill(*C,fill));
9665 
9666     (*C)->product->api_user = PETSC_TRUE;
9667     PetscCall(MatProductSetFromOptions(*C));
9668     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);
9669     PetscCall(MatProductSymbolic(*C));
9670   } else { /* scall == MAT_REUSE_MATRIX */
9671     PetscCall(MatProductReplaceMats(A,P,NULL,*C));
9672   }
9673 
9674   PetscCall(MatProductNumeric(*C));
9675   (*C)->symmetric = A->symmetric;
9676   (*C)->spd       = A->spd;
9677   PetscFunctionReturn(0);
9678 }
9679 
9680 /*@
9681    MatRARt - Creates the matrix product C = R * A * R^T
9682 
9683    Neighbor-wise Collective on Mat
9684 
9685    Input Parameters:
9686 +  A - the matrix
9687 .  R - the projection matrix
9688 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9689 -  fill - expected fill as ratio of nnz(C)/nnz(A), use PETSC_DEFAULT if you do not have a good estimate
9690           if the result is a dense matrix this is irrelevant
9691 
9692    Output Parameters:
9693 .  C - the product matrix
9694 
9695    Notes:
9696    C will be created and must be destroyed by the user with MatDestroy().
9697 
9698    This routine is currently only implemented for pairs of AIJ matrices and classes
9699    which inherit from AIJ. Due to PETSc sparse matrix block row distribution among processes,
9700    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9701    We recommend using MatPtAP().
9702 
9703    Level: intermediate
9704 
9705 .seealso: `MatMatMult()`, `MatPtAP()`
9706 @*/
9707 PetscErrorCode MatRARt(Mat A,Mat R,MatReuse scall,PetscReal fill,Mat *C)
9708 {
9709   PetscFunctionBegin;
9710   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9711   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9712 
9713   if (scall == MAT_INITIAL_MATRIX) {
9714     PetscCall(MatProductCreate(A,R,NULL,C));
9715     PetscCall(MatProductSetType(*C,MATPRODUCT_RARt));
9716     PetscCall(MatProductSetAlgorithm(*C,"default"));
9717     PetscCall(MatProductSetFill(*C,fill));
9718 
9719     (*C)->product->api_user = PETSC_TRUE;
9720     PetscCall(MatProductSetFromOptions(*C));
9721     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);
9722     PetscCall(MatProductSymbolic(*C));
9723   } else { /* scall == MAT_REUSE_MATRIX */
9724     PetscCall(MatProductReplaceMats(A,R,NULL,*C));
9725   }
9726 
9727   PetscCall(MatProductNumeric(*C));
9728   if (A->symmetric == PETSC_BOOL3_TRUE) {
9729     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9730   }
9731   PetscFunctionReturn(0);
9732 }
9733 
9734 static PetscErrorCode MatProduct_Private(Mat A,Mat B,MatReuse scall,PetscReal fill,MatProductType ptype, Mat *C)
9735 {
9736   PetscFunctionBegin;
9737   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9738 
9739   if (scall == MAT_INITIAL_MATRIX) {
9740     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n",MatProductTypes[ptype]));
9741     PetscCall(MatProductCreate(A,B,NULL,C));
9742     PetscCall(MatProductSetType(*C,ptype));
9743     PetscCall(MatProductSetAlgorithm(*C,MATPRODUCTALGORITHMDEFAULT));
9744     PetscCall(MatProductSetFill(*C,fill));
9745 
9746     (*C)->product->api_user = PETSC_TRUE;
9747     PetscCall(MatProductSetFromOptions(*C));
9748     PetscCall(MatProductSymbolic(*C));
9749   } else { /* scall == MAT_REUSE_MATRIX */
9750     Mat_Product *product = (*C)->product;
9751     PetscBool isdense;
9752 
9753     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C),&isdense,MATSEQDENSE,MATMPIDENSE,""));
9754     if (isdense && product && product->type != ptype) {
9755       PetscCall(MatProductClear(*C));
9756       product = NULL;
9757     }
9758     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n",product ? "with" : "without",MatProductTypes[ptype]));
9759     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9760       if (isdense) {
9761         PetscCall(MatProductCreate_Private(A,B,NULL,*C));
9762         product = (*C)->product;
9763         product->fill     = fill;
9764         product->api_user = PETSC_TRUE;
9765         product->clear    = PETSC_TRUE;
9766 
9767         PetscCall(MatProductSetType(*C,ptype));
9768         PetscCall(MatProductSetFromOptions(*C));
9769         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);
9770         PetscCall(MatProductSymbolic(*C));
9771       } else SETERRQ(PetscObjectComm((PetscObject)(*C)),PETSC_ERR_SUP,"Call MatProductCreate() first");
9772     } else { /* user may change input matrices A or B when REUSE */
9773       PetscCall(MatProductReplaceMats(A,B,NULL,*C));
9774     }
9775   }
9776   PetscCall(MatProductNumeric(*C));
9777   PetscFunctionReturn(0);
9778 }
9779 
9780 /*@
9781    MatMatMult - Performs Matrix-Matrix Multiplication C=A*B.
9782 
9783    Neighbor-wise Collective on Mat
9784 
9785    Input Parameters:
9786 +  A - the left matrix
9787 .  B - the right matrix
9788 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9789 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if you do not have a good estimate
9790           if the result is a dense matrix this is irrelevant
9791 
9792    Output Parameters:
9793 .  C - the product matrix
9794 
9795    Notes:
9796    Unless scall is MAT_REUSE_MATRIX C will be created.
9797 
9798    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
9799    call to this function with MAT_INITIAL_MATRIX.
9800 
9801    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9802 
9803    If you have many matrices with the same non-zero structure to multiply, you should use MatProductCreate()/MatProductSymbolic()/MatProductReplaceMats(), and call MatProductNumeric() repeatedly.
9804 
9805    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.
9806 
9807    Example of Usage:
9808 .vb
9809      MatProductCreate(A,B,NULL,&C);
9810      MatProductSetType(C,MATPRODUCT_AB);
9811      MatProductSymbolic(C);
9812      MatProductNumeric(C); // compute C=A * B
9813      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9814      MatProductNumeric(C);
9815      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9816      MatProductNumeric(C);
9817 .ve
9818 
9819    Level: intermediate
9820 
9821 .seealso: `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9822 @*/
9823 PetscErrorCode MatMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9824 {
9825   PetscFunctionBegin;
9826   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AB,C));
9827   PetscFunctionReturn(0);
9828 }
9829 
9830 /*@
9831    MatMatTransposeMult - Performs Matrix-Matrix Multiplication C=A*B^T.
9832 
9833    Neighbor-wise Collective on Mat
9834 
9835    Input Parameters:
9836 +  A - the left matrix
9837 .  B - the right matrix
9838 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9839 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9840 
9841    Output Parameters:
9842 .  C - the product matrix
9843 
9844    Notes:
9845    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9846 
9847    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9848 
9849   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9850    actually needed.
9851 
9852    This routine is currently only implemented for pairs of SeqAIJ matrices, for the SeqDense class,
9853    and for pairs of MPIDense matrices.
9854 
9855    Options Database Keys:
9856 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for MPIDense matrices: the
9857               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9858               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9859 
9860    Level: intermediate
9861 
9862 .seealso: `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`
9863 @*/
9864 PetscErrorCode MatMatTransposeMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9865 {
9866   PetscFunctionBegin;
9867   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_ABt,C));
9868   if (A == B) {
9869     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9870   }
9871   PetscFunctionReturn(0);
9872 }
9873 
9874 /*@
9875    MatTransposeMatMult - Performs Matrix-Matrix Multiplication C=A^T*B.
9876 
9877    Neighbor-wise Collective on Mat
9878 
9879    Input Parameters:
9880 +  A - the left matrix
9881 .  B - the right matrix
9882 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9883 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9884 
9885    Output Parameters:
9886 .  C - the product matrix
9887 
9888    Notes:
9889    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9890 
9891    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9892 
9893   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9894    actually needed.
9895 
9896    This routine is currently implemented for pairs of AIJ matrices and pairs of SeqDense matrices and classes
9897    which inherit from SeqAIJ.  C will be of the same type as the input matrices.
9898 
9899    Level: intermediate
9900 
9901 .seealso: `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9902 @*/
9903 PetscErrorCode MatTransposeMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9904 {
9905   PetscFunctionBegin;
9906   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AtB,C));
9907   PetscFunctionReturn(0);
9908 }
9909 
9910 /*@
9911    MatMatMatMult - Performs Matrix-Matrix-Matrix Multiplication D=A*B*C.
9912 
9913    Neighbor-wise Collective on Mat
9914 
9915    Input Parameters:
9916 +  A - the left matrix
9917 .  B - the middle matrix
9918 .  C - the right matrix
9919 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9920 -  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
9921           if the result is a dense matrix this is irrelevant
9922 
9923    Output Parameters:
9924 .  D - the product matrix
9925 
9926    Notes:
9927    Unless scall is MAT_REUSE_MATRIX D will be created.
9928 
9929    MAT_REUSE_MATRIX can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9930 
9931    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9932    actually needed.
9933 
9934    If you have many matrices with the same non-zero structure to multiply, you
9935    should use MAT_REUSE_MATRIX in all calls but the first
9936 
9937    Level: intermediate
9938 
9939 .seealso: `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9940 @*/
9941 PetscErrorCode MatMatMatMult(Mat A,Mat B,Mat C,MatReuse scall,PetscReal fill,Mat *D)
9942 {
9943   PetscFunctionBegin;
9944   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D,6);
9945   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9946 
9947   if (scall == MAT_INITIAL_MATRIX) {
9948     PetscCall(MatProductCreate(A,B,C,D));
9949     PetscCall(MatProductSetType(*D,MATPRODUCT_ABC));
9950     PetscCall(MatProductSetAlgorithm(*D,"default"));
9951     PetscCall(MatProductSetFill(*D,fill));
9952 
9953     (*D)->product->api_user = PETSC_TRUE;
9954     PetscCall(MatProductSetFromOptions(*D));
9955     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);
9956     PetscCall(MatProductSymbolic(*D));
9957   } else { /* user may change input matrices when REUSE */
9958     PetscCall(MatProductReplaceMats(A,B,C,*D));
9959   }
9960   PetscCall(MatProductNumeric(*D));
9961   PetscFunctionReturn(0);
9962 }
9963 
9964 /*@
9965    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9966 
9967    Collective on Mat
9968 
9969    Input Parameters:
9970 +  mat - the matrix
9971 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9972 .  subcomm - MPI communicator split from the communicator where mat resides in (or MPI_COMM_NULL if nsubcomm is used)
9973 -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9974 
9975    Output Parameter:
9976 .  matredundant - redundant matrix
9977 
9978    Notes:
9979    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
9980    original matrix has not changed from that last call to MatCreateRedundantMatrix().
9981 
9982    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9983    calling it.
9984 
9985    Level: advanced
9986 
9987 .seealso: `MatDestroy()`
9988 @*/
9989 PetscErrorCode MatCreateRedundantMatrix(Mat mat,PetscInt nsubcomm,MPI_Comm subcomm,MatReuse reuse,Mat *matredundant)
9990 {
9991   MPI_Comm       comm;
9992   PetscMPIInt    size;
9993   PetscInt       mloc_sub,nloc_sub,rstart,rend,M=mat->rmap->N,N=mat->cmap->N,bs=mat->rmap->bs;
9994   Mat_Redundant  *redund=NULL;
9995   PetscSubcomm   psubcomm=NULL;
9996   MPI_Comm       subcomm_in=subcomm;
9997   Mat            *matseq;
9998   IS             isrow,iscol;
9999   PetscBool      newsubcomm=PETSC_FALSE;
10000 
10001   PetscFunctionBegin;
10002   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10003   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10004     PetscValidPointer(*matredundant,5);
10005     PetscValidHeaderSpecific(*matredundant,MAT_CLASSID,5);
10006   }
10007 
10008   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10009   if (size == 1 || nsubcomm == 1) {
10010     if (reuse == MAT_INITIAL_MATRIX) {
10011       PetscCall(MatDuplicate(mat,MAT_COPY_VALUES,matredundant));
10012     } else {
10013       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");
10014       PetscCall(MatCopy(mat,*matredundant,SAME_NONZERO_PATTERN));
10015     }
10016     PetscFunctionReturn(0);
10017   }
10018 
10019   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10020   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10021   MatCheckPreallocated(mat,1);
10022 
10023   PetscCall(PetscLogEventBegin(MAT_RedundantMat,mat,0,0,0));
10024   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10025     /* create psubcomm, then get subcomm */
10026     PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10027     PetscCallMPI(MPI_Comm_size(comm,&size));
10028     PetscCheck(nsubcomm >= 1 && nsubcomm <= size,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"nsubcomm must between 1 and %d",size);
10029 
10030     PetscCall(PetscSubcommCreate(comm,&psubcomm));
10031     PetscCall(PetscSubcommSetNumber(psubcomm,nsubcomm));
10032     PetscCall(PetscSubcommSetType(psubcomm,PETSC_SUBCOMM_CONTIGUOUS));
10033     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10034     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm),&subcomm,NULL));
10035     newsubcomm = PETSC_TRUE;
10036     PetscCall(PetscSubcommDestroy(&psubcomm));
10037   }
10038 
10039   /* get isrow, iscol and a local sequential matrix matseq[0] */
10040   if (reuse == MAT_INITIAL_MATRIX) {
10041     mloc_sub = PETSC_DECIDE;
10042     nloc_sub = PETSC_DECIDE;
10043     if (bs < 1) {
10044       PetscCall(PetscSplitOwnership(subcomm,&mloc_sub,&M));
10045       PetscCall(PetscSplitOwnership(subcomm,&nloc_sub,&N));
10046     } else {
10047       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&mloc_sub,&M));
10048       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&nloc_sub,&N));
10049     }
10050     PetscCallMPI(MPI_Scan(&mloc_sub,&rend,1,MPIU_INT,MPI_SUM,subcomm));
10051     rstart = rend - mloc_sub;
10052     PetscCall(ISCreateStride(PETSC_COMM_SELF,mloc_sub,rstart,1,&isrow));
10053     PetscCall(ISCreateStride(PETSC_COMM_SELF,N,0,1,&iscol));
10054   } else { /* reuse == MAT_REUSE_MATRIX */
10055     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");
10056     /* retrieve subcomm */
10057     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant),&subcomm));
10058     redund = (*matredundant)->redundant;
10059     isrow  = redund->isrow;
10060     iscol  = redund->iscol;
10061     matseq = redund->matseq;
10062   }
10063   PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscol,reuse,&matseq));
10064 
10065   /* get matredundant over subcomm */
10066   if (reuse == MAT_INITIAL_MATRIX) {
10067     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],nloc_sub,reuse,matredundant));
10068 
10069     /* create a supporting struct and attach it to C for reuse */
10070     PetscCall(PetscNewLog(*matredundant,&redund));
10071     (*matredundant)->redundant = redund;
10072     redund->isrow              = isrow;
10073     redund->iscol              = iscol;
10074     redund->matseq             = matseq;
10075     if (newsubcomm) {
10076       redund->subcomm          = subcomm;
10077     } else {
10078       redund->subcomm          = MPI_COMM_NULL;
10079     }
10080   } else {
10081     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],PETSC_DECIDE,reuse,matredundant));
10082   }
10083 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
10084   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10085     PetscCall(MatBindToCPU(*matredundant,PETSC_TRUE));
10086     PetscCall(MatSetBindingPropagates(*matredundant,PETSC_TRUE));
10087   }
10088 #endif
10089   PetscCall(PetscLogEventEnd(MAT_RedundantMat,mat,0,0,0));
10090   PetscFunctionReturn(0);
10091 }
10092 
10093 /*@C
10094    MatGetMultiProcBlock - Create multiple [bjacobi] 'parallel submatrices' from
10095    a given 'mat' object. Each submatrix can span multiple procs.
10096 
10097    Collective on Mat
10098 
10099    Input Parameters:
10100 +  mat - the matrix
10101 .  subcomm - the subcommunicator obtained by com_split(comm)
10102 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10103 
10104    Output Parameter:
10105 .  subMat - 'parallel submatrices each spans a given subcomm
10106 
10107   Notes:
10108   The submatrix partition across processors is dictated by 'subComm' a
10109   communicator obtained by MPI_comm_split(). The subComm
10110   is not restriced to be grouped with consecutive original ranks.
10111 
10112   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10113   map directly to the layout of the original matrix [wrt the local
10114   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10115   into the 'DiagonalMat' of the subMat, hence it is used directly from
10116   the subMat. However the offDiagMat looses some columns - and this is
10117   reconstructed with MatSetValues()
10118 
10119   Level: advanced
10120 
10121 .seealso: `MatCreateSubMatrices()`
10122 @*/
10123 PetscErrorCode   MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall,Mat *subMat)
10124 {
10125   PetscMPIInt    commsize,subCommSize;
10126 
10127   PetscFunctionBegin;
10128   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&commsize));
10129   PetscCallMPI(MPI_Comm_size(subComm,&subCommSize));
10130   PetscCheck(subCommSize <= commsize,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"CommSize %d < SubCommZize %d",commsize,subCommSize);
10131 
10132   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");
10133   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock,mat,0,0,0));
10134   PetscCall((*mat->ops->getmultiprocblock)(mat,subComm,scall,subMat));
10135   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock,mat,0,0,0));
10136   PetscFunctionReturn(0);
10137 }
10138 
10139 /*@
10140    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10141 
10142    Not Collective
10143 
10144    Input Parameters:
10145 +  mat - matrix to extract local submatrix from
10146 .  isrow - local row indices for submatrix
10147 -  iscol - local column indices for submatrix
10148 
10149    Output Parameter:
10150 .  submat - the submatrix
10151 
10152    Level: intermediate
10153 
10154    Notes:
10155    The submat should be returned with MatRestoreLocalSubMatrix().
10156 
10157    Depending on the format of mat, the returned submat may not implement MatMult().  Its communicator may be
10158    the same as mat, it may be PETSC_COMM_SELF, or some other subcomm of mat's.
10159 
10160    The submat always implements MatSetValuesLocal().  If isrow and iscol have the same block size, then
10161    MatSetValuesBlockedLocal() will also be implemented.
10162 
10163    The mat must have had a ISLocalToGlobalMapping provided to it with MatSetLocalToGlobalMapping(). Note that
10164    matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10165 
10166 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10167 @*/
10168 PetscErrorCode MatGetLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10169 {
10170   PetscFunctionBegin;
10171   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10172   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10173   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10174   PetscCheckSameComm(isrow,2,iscol,3);
10175   PetscValidPointer(submat,4);
10176   PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must have local to global mapping provided before this call");
10177 
10178   if (mat->ops->getlocalsubmatrix) {
10179     PetscCall((*mat->ops->getlocalsubmatrix)(mat,isrow,iscol,submat));
10180   } else {
10181     PetscCall(MatCreateLocalRef(mat,isrow,iscol,submat));
10182   }
10183   PetscFunctionReturn(0);
10184 }
10185 
10186 /*@
10187    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering
10188 
10189    Not Collective
10190 
10191    Input Parameters:
10192 +  mat - matrix to extract local submatrix from
10193 .  isrow - local row indices for submatrix
10194 .  iscol - local column indices for submatrix
10195 -  submat - the submatrix
10196 
10197    Level: intermediate
10198 
10199 .seealso: `MatGetLocalSubMatrix()`
10200 @*/
10201 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10202 {
10203   PetscFunctionBegin;
10204   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10205   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10206   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10207   PetscCheckSameComm(isrow,2,iscol,3);
10208   PetscValidPointer(submat,4);
10209   if (*submat) {
10210     PetscValidHeaderSpecific(*submat,MAT_CLASSID,4);
10211   }
10212 
10213   if (mat->ops->restorelocalsubmatrix) {
10214     PetscCall((*mat->ops->restorelocalsubmatrix)(mat,isrow,iscol,submat));
10215   } else {
10216     PetscCall(MatDestroy(submat));
10217   }
10218   *submat = NULL;
10219   PetscFunctionReturn(0);
10220 }
10221 
10222 /* --------------------------------------------------------*/
10223 /*@
10224    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10225 
10226    Collective on Mat
10227 
10228    Input Parameter:
10229 .  mat - the matrix
10230 
10231    Output Parameter:
10232 .  is - if any rows have zero diagonals this contains the list of them
10233 
10234    Level: developer
10235 
10236 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10237 @*/
10238 PetscErrorCode MatFindZeroDiagonals(Mat mat,IS *is)
10239 {
10240   PetscFunctionBegin;
10241   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10242   PetscValidType(mat,1);
10243   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10244   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10245 
10246   if (!mat->ops->findzerodiagonals) {
10247     Vec                diag;
10248     const PetscScalar *a;
10249     PetscInt          *rows;
10250     PetscInt           rStart, rEnd, r, nrow = 0;
10251 
10252     PetscCall(MatCreateVecs(mat, &diag, NULL));
10253     PetscCall(MatGetDiagonal(mat, diag));
10254     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10255     PetscCall(VecGetArrayRead(diag, &a));
10256     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) ++nrow;
10257     PetscCall(PetscMalloc1(nrow, &rows));
10258     nrow = 0;
10259     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) rows[nrow++] = r+rStart;
10260     PetscCall(VecRestoreArrayRead(diag, &a));
10261     PetscCall(VecDestroy(&diag));
10262     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) mat), nrow, rows, PETSC_OWN_POINTER, is));
10263   } else {
10264     PetscCall((*mat->ops->findzerodiagonals)(mat, is));
10265   }
10266   PetscFunctionReturn(0);
10267 }
10268 
10269 /*@
10270    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10271 
10272    Collective on Mat
10273 
10274    Input Parameter:
10275 .  mat - the matrix
10276 
10277    Output Parameter:
10278 .  is - contains the list of rows with off block diagonal entries
10279 
10280    Level: developer
10281 
10282 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10283 @*/
10284 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat,IS *is)
10285 {
10286   PetscFunctionBegin;
10287   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10288   PetscValidType(mat,1);
10289   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10290   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10291 
10292   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);
10293   PetscCall((*mat->ops->findoffblockdiagonalentries)(mat,is));
10294   PetscFunctionReturn(0);
10295 }
10296 
10297 /*@C
10298   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10299 
10300   Collective on Mat
10301 
10302   Input Parameters:
10303 . mat - the matrix
10304 
10305   Output Parameters:
10306 . values - the block inverses in column major order (FORTRAN-like)
10307 
10308    Note:
10309      The size of the blocks is determined by the block size of the matrix.
10310 
10311    Fortran Note:
10312      This routine is not available from Fortran.
10313 
10314   Level: advanced
10315 
10316 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10317 @*/
10318 PetscErrorCode MatInvertBlockDiagonal(Mat mat,const PetscScalar **values)
10319 {
10320   PetscFunctionBegin;
10321   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10322   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10323   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10324   PetscCheck(mat->ops->invertblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10325   PetscCall((*mat->ops->invertblockdiagonal)(mat,values));
10326   PetscFunctionReturn(0);
10327 }
10328 
10329 /*@C
10330   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10331 
10332   Collective on Mat
10333 
10334   Input Parameters:
10335 + mat - the matrix
10336 . nblocks - the number of blocks on the process, set with MatSetVariableBlockSizes()
10337 - bsizes - the size of each block on the process, set with MatSetVariableBlockSizes()
10338 
10339   Output Parameters:
10340 . values - the block inverses in column major order (FORTRAN-like)
10341 
10342    Note:
10343    This routine is not available from Fortran.
10344 
10345   Level: advanced
10346 
10347 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10348 @*/
10349 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *values)
10350 {
10351   PetscFunctionBegin;
10352   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10353   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10354   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10355   PetscCheck(mat->ops->invertvariableblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10356   PetscCall((*mat->ops->invertvariableblockdiagonal)(mat,nblocks,bsizes,values));
10357   PetscFunctionReturn(0);
10358 }
10359 
10360 /*@
10361   MatInvertBlockDiagonalMat - set matrix C to be the inverted block diagonal of matrix A
10362 
10363   Collective on Mat
10364 
10365   Input Parameters:
10366 . A - the matrix
10367 
10368   Output Parameters:
10369 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10370 
10371   Notes: the blocksize of the matrix is used to determine the blocks on the diagonal of C
10372 
10373   Level: advanced
10374 
10375 .seealso: `MatInvertBlockDiagonal()`
10376 @*/
10377 PetscErrorCode MatInvertBlockDiagonalMat(Mat A,Mat C)
10378 {
10379   const PetscScalar *vals;
10380   PetscInt          *dnnz;
10381   PetscInt           m,rstart,rend,bs,i,j;
10382 
10383   PetscFunctionBegin;
10384   PetscCall(MatInvertBlockDiagonal(A,&vals));
10385   PetscCall(MatGetBlockSize(A,&bs));
10386   PetscCall(MatGetLocalSize(A,&m,NULL));
10387   PetscCall(MatSetLayouts(C,A->rmap,A->cmap));
10388   PetscCall(PetscMalloc1(m/bs,&dnnz));
10389   for (j = 0; j < m/bs; j++) dnnz[j] = 1;
10390   PetscCall(MatXAIJSetPreallocation(C,bs,dnnz,NULL,NULL,NULL));
10391   PetscCall(PetscFree(dnnz));
10392   PetscCall(MatGetOwnershipRange(C,&rstart,&rend));
10393   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_FALSE));
10394   for (i = rstart/bs; i < rend/bs; i++) {
10395     PetscCall(MatSetValuesBlocked(C,1,&i,1,&i,&vals[(i-rstart/bs)*bs*bs],INSERT_VALUES));
10396   }
10397   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
10398   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
10399   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_TRUE));
10400   PetscFunctionReturn(0);
10401 }
10402 
10403 /*@C
10404     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10405     via MatTransposeColoringCreate().
10406 
10407     Collective on MatTransposeColoring
10408 
10409     Input Parameter:
10410 .   c - coloring context
10411 
10412     Level: intermediate
10413 
10414 .seealso: `MatTransposeColoringCreate()`
10415 @*/
10416 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10417 {
10418   MatTransposeColoring matcolor=*c;
10419 
10420   PetscFunctionBegin;
10421   if (!matcolor) PetscFunctionReturn(0);
10422   if (--((PetscObject)matcolor)->refct > 0) {matcolor = NULL; PetscFunctionReturn(0);}
10423 
10424   PetscCall(PetscFree3(matcolor->ncolumns,matcolor->nrows,matcolor->colorforrow));
10425   PetscCall(PetscFree(matcolor->rows));
10426   PetscCall(PetscFree(matcolor->den2sp));
10427   PetscCall(PetscFree(matcolor->colorforcol));
10428   PetscCall(PetscFree(matcolor->columns));
10429   if (matcolor->brows>0) PetscCall(PetscFree(matcolor->lstart));
10430   PetscCall(PetscHeaderDestroy(c));
10431   PetscFunctionReturn(0);
10432 }
10433 
10434 /*@C
10435     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10436     a MatTransposeColoring context has been created, computes a dense B^T by Apply
10437     MatTransposeColoring to sparse B.
10438 
10439     Collective on MatTransposeColoring
10440 
10441     Input Parameters:
10442 +   B - sparse matrix B
10443 .   Btdense - symbolic dense matrix B^T
10444 -   coloring - coloring context created with MatTransposeColoringCreate()
10445 
10446     Output Parameter:
10447 .   Btdense - dense matrix B^T
10448 
10449     Level: advanced
10450 
10451      Notes:
10452     These are used internally for some implementations of MatRARt()
10453 
10454 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10455 
10456 @*/
10457 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring,Mat B,Mat Btdense)
10458 {
10459   PetscFunctionBegin;
10460   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10461   PetscValidHeaderSpecific(Btdense,MAT_CLASSID,3);
10462   PetscValidHeaderSpecific(coloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10463 
10464   PetscCheck(B->ops->transcoloringapplysptoden,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)B)->type_name);
10465   PetscCall((B->ops->transcoloringapplysptoden)(coloring,B,Btdense));
10466   PetscFunctionReturn(0);
10467 }
10468 
10469 /*@C
10470     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10471     a MatTransposeColoring context has been created and a dense matrix Cden=A*Btdense
10472     in which Btdens is obtained from MatTransColoringApplySpToDen(), recover sparse matrix
10473     Csp from Cden.
10474 
10475     Collective on MatTransposeColoring
10476 
10477     Input Parameters:
10478 +   coloring - coloring context created with MatTransposeColoringCreate()
10479 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10480 
10481     Output Parameter:
10482 .   Csp - sparse matrix
10483 
10484     Level: advanced
10485 
10486      Notes:
10487     These are used internally for some implementations of MatRARt()
10488 
10489 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10490 
10491 @*/
10492 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring,Mat Cden,Mat Csp)
10493 {
10494   PetscFunctionBegin;
10495   PetscValidHeaderSpecific(matcoloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10496   PetscValidHeaderSpecific(Cden,MAT_CLASSID,2);
10497   PetscValidHeaderSpecific(Csp,MAT_CLASSID,3);
10498 
10499   PetscCheck(Csp->ops->transcoloringapplydentosp,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)Csp)->type_name);
10500   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring,Cden,Csp));
10501   PetscCall(MatAssemblyBegin(Csp,MAT_FINAL_ASSEMBLY));
10502   PetscCall(MatAssemblyEnd(Csp,MAT_FINAL_ASSEMBLY));
10503   PetscFunctionReturn(0);
10504 }
10505 
10506 /*@C
10507    MatTransposeColoringCreate - Creates a matrix coloring context for matrix product C=A*B^T.
10508 
10509    Collective on Mat
10510 
10511    Input Parameters:
10512 +  mat - the matrix product C
10513 -  iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring()
10514 
10515     Output Parameter:
10516 .   color - the new coloring context
10517 
10518     Level: intermediate
10519 
10520 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10521           `MatTransColoringApplyDenToSp()`
10522 @*/
10523 PetscErrorCode MatTransposeColoringCreate(Mat mat,ISColoring iscoloring,MatTransposeColoring *color)
10524 {
10525   MatTransposeColoring c;
10526   MPI_Comm             comm;
10527 
10528   PetscFunctionBegin;
10529   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate,mat,0,0,0));
10530   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10531   PetscCall(PetscHeaderCreate(c,MAT_TRANSPOSECOLORING_CLASSID,"MatTransposeColoring","Matrix product C=A*B^T via coloring","Mat",comm,MatTransposeColoringDestroy,NULL));
10532 
10533   c->ctype = iscoloring->ctype;
10534   if (mat->ops->transposecoloringcreate) {
10535     PetscCall((*mat->ops->transposecoloringcreate)(mat,iscoloring,c));
10536   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);
10537 
10538   *color = c;
10539   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate,mat,0,0,0));
10540   PetscFunctionReturn(0);
10541 }
10542 
10543 /*@
10544       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10545         matrix has had no new nonzero locations added to the matrix since the previous call then the value will be the
10546         same, otherwise it will be larger
10547 
10548      Not Collective
10549 
10550   Input Parameter:
10551 .    A  - the matrix
10552 
10553   Output Parameter:
10554 .    state - the current state
10555 
10556   Notes:
10557     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10558          different matrices
10559 
10560   Level: intermediate
10561 
10562 .seealso: `PetscObjectStateGet()`
10563 @*/
10564 PetscErrorCode MatGetNonzeroState(Mat mat,PetscObjectState *state)
10565 {
10566   PetscFunctionBegin;
10567   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10568   *state = mat->nonzerostate;
10569   PetscFunctionReturn(0);
10570 }
10571 
10572 /*@
10573       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10574                  matrices from each processor
10575 
10576     Collective
10577 
10578    Input Parameters:
10579 +    comm - the communicators the parallel matrix will live on
10580 .    seqmat - the input sequential matrices
10581 .    n - number of local columns (or PETSC_DECIDE)
10582 -    reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10583 
10584    Output Parameter:
10585 .    mpimat - the parallel matrix generated
10586 
10587     Level: advanced
10588 
10589    Notes:
10590     The number of columns of the matrix in EACH processor MUST be the same.
10591 
10592 @*/
10593 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm,Mat seqmat,PetscInt n,MatReuse reuse,Mat *mpimat)
10594 {
10595   PetscMPIInt size;
10596 
10597   PetscFunctionBegin;
10598   PetscCallMPI(MPI_Comm_size(comm,&size));
10599   if (size == 1) {
10600     if (reuse == MAT_INITIAL_MATRIX) {
10601       PetscCall(MatDuplicate(seqmat,MAT_COPY_VALUES,mpimat));
10602     } else {
10603       PetscCall(MatCopy(seqmat,*mpimat,SAME_NONZERO_PATTERN));
10604     }
10605     PetscFunctionReturn(0);
10606   }
10607 
10608   PetscCheck(seqmat->ops->creatempimatconcatenateseqmat,PetscObjectComm((PetscObject)seqmat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)seqmat)->type_name);
10609   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");
10610 
10611   PetscCall(PetscLogEventBegin(MAT_Merge,seqmat,0,0,0));
10612   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm,seqmat,n,reuse,mpimat));
10613   PetscCall(PetscLogEventEnd(MAT_Merge,seqmat,0,0,0));
10614   PetscFunctionReturn(0);
10615 }
10616 
10617 /*@
10618      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent
10619                  ranks' ownership ranges.
10620 
10621     Collective on A
10622 
10623    Input Parameters:
10624 +    A   - the matrix to create subdomains from
10625 -    N   - requested number of subdomains
10626 
10627    Output Parameters:
10628 +    n   - number of subdomains resulting on this rank
10629 -    iss - IS list with indices of subdomains on this rank
10630 
10631     Level: advanced
10632 
10633     Notes:
10634     number of subdomains must be smaller than the communicator size
10635 @*/
10636 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A,PetscInt N,PetscInt *n,IS *iss[])
10637 {
10638   MPI_Comm        comm,subcomm;
10639   PetscMPIInt     size,rank,color;
10640   PetscInt        rstart,rend,k;
10641 
10642   PetscFunctionBegin;
10643   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
10644   PetscCallMPI(MPI_Comm_size(comm,&size));
10645   PetscCallMPI(MPI_Comm_rank(comm,&rank));
10646   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);
10647   *n = 1;
10648   k = ((PetscInt)size)/N + ((PetscInt)size%N>0); /* There are up to k ranks to a color */
10649   color = rank/k;
10650   PetscCallMPI(MPI_Comm_split(comm,color,rank,&subcomm));
10651   PetscCall(PetscMalloc1(1,iss));
10652   PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
10653   PetscCall(ISCreateStride(subcomm,rend-rstart,rstart,1,iss[0]));
10654   PetscCallMPI(MPI_Comm_free(&subcomm));
10655   PetscFunctionReturn(0);
10656 }
10657 
10658 /*@
10659    MatGalerkin - Constructs the coarse grid problem via Galerkin projection.
10660 
10661    If the interpolation and restriction operators are the same, uses MatPtAP.
10662    If they are not the same, use MatMatMatMult.
10663 
10664    Once the coarse grid problem is constructed, correct for interpolation operators
10665    that are not of full rank, which can legitimately happen in the case of non-nested
10666    geometric multigrid.
10667 
10668    Input Parameters:
10669 +  restrct - restriction operator
10670 .  dA - fine grid matrix
10671 .  interpolate - interpolation operator
10672 .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10673 -  fill - expected fill, use PETSC_DEFAULT if you do not have a good estimate
10674 
10675    Output Parameters:
10676 .  A - the Galerkin coarse matrix
10677 
10678    Options Database Key:
10679 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10680 
10681    Level: developer
10682 
10683 .seealso: `MatPtAP()`, `MatMatMatMult()`
10684 @*/
10685 PetscErrorCode  MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10686 {
10687   IS             zerorows;
10688   Vec            diag;
10689 
10690   PetscFunctionBegin;
10691   PetscCheck(reuse != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
10692   /* Construct the coarse grid matrix */
10693   if (interpolate == restrct) {
10694     PetscCall(MatPtAP(dA,interpolate,reuse,fill,A));
10695   } else {
10696     PetscCall(MatMatMatMult(restrct,dA,interpolate,reuse,fill,A));
10697   }
10698 
10699   /* If the interpolation matrix is not of full rank, A will have zero rows.
10700      This can legitimately happen in the case of non-nested geometric multigrid.
10701      In that event, we set the rows of the matrix to the rows of the identity,
10702      ignoring the equations (as the RHS will also be zero). */
10703 
10704   PetscCall(MatFindZeroRows(*A, &zerorows));
10705 
10706   if (zerorows != NULL) { /* if there are any zero rows */
10707     PetscCall(MatCreateVecs(*A, &diag, NULL));
10708     PetscCall(MatGetDiagonal(*A, diag));
10709     PetscCall(VecISSet(diag, zerorows, 1.0));
10710     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10711     PetscCall(VecDestroy(&diag));
10712     PetscCall(ISDestroy(&zerorows));
10713   }
10714   PetscFunctionReturn(0);
10715 }
10716 
10717 /*@C
10718     MatSetOperation - Allows user to set a matrix operation for any matrix type
10719 
10720    Logically Collective on Mat
10721 
10722     Input Parameters:
10723 +   mat - the matrix
10724 .   op - the name of the operation
10725 -   f - the function that provides the operation
10726 
10727    Level: developer
10728 
10729     Usage:
10730 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10731 $      PetscCall(MatCreateXXX(comm,...&A);
10732 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10733 
10734     Notes:
10735     See the file include/petscmat.h for a complete list of matrix
10736     operations, which all have the form MATOP_<OPERATION>, where
10737     <OPERATION> is the name (in all capital letters) of the
10738     user interface routine (e.g., MatMult() -> MATOP_MULT).
10739 
10740     All user-provided functions (except for MATOP_DESTROY) should have the same calling
10741     sequence as the usual matrix interface routines, since they
10742     are intended to be accessed via the usual matrix interface
10743     routines, e.g.,
10744 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10745 
10746     In particular each function MUST return an error code of 0 on success and
10747     nonzero on failure.
10748 
10749     This routine is distinct from MatShellSetOperation() in that it can be called on any matrix type.
10750 
10751 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10752 @*/
10753 PetscErrorCode MatSetOperation(Mat mat,MatOperation op,void (*f)(void))
10754 {
10755   PetscFunctionBegin;
10756   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10757   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) {
10758     mat->ops->viewnative = mat->ops->view;
10759   }
10760   (((void(**)(void))mat->ops)[op]) = f;
10761   PetscFunctionReturn(0);
10762 }
10763 
10764 /*@C
10765     MatGetOperation - Gets a matrix operation for any matrix type.
10766 
10767     Not Collective
10768 
10769     Input Parameters:
10770 +   mat - the matrix
10771 -   op - the name of the operation
10772 
10773     Output Parameter:
10774 .   f - the function that provides the operation
10775 
10776     Level: developer
10777 
10778     Usage:
10779 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10780 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10781 
10782     Notes:
10783     See the file include/petscmat.h for a complete list of matrix
10784     operations, which all have the form MATOP_<OPERATION>, where
10785     <OPERATION> is the name (in all capital letters) of the
10786     user interface routine (e.g., MatMult() -> MATOP_MULT).
10787 
10788     This routine is distinct from MatShellGetOperation() in that it can be called on any matrix type.
10789 
10790 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10791 @*/
10792 PetscErrorCode MatGetOperation(Mat mat,MatOperation op,void(**f)(void))
10793 {
10794   PetscFunctionBegin;
10795   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10796   *f = (((void (**)(void))mat->ops)[op]);
10797   PetscFunctionReturn(0);
10798 }
10799 
10800 /*@
10801     MatHasOperation - Determines whether the given matrix supports the particular
10802     operation.
10803 
10804    Not Collective
10805 
10806    Input Parameters:
10807 +  mat - the matrix
10808 -  op - the operation, for example, MATOP_GET_DIAGONAL
10809 
10810    Output Parameter:
10811 .  has - either PETSC_TRUE or PETSC_FALSE
10812 
10813    Level: advanced
10814 
10815    Notes:
10816    See the file include/petscmat.h for a complete list of matrix
10817    operations, which all have the form MATOP_<OPERATION>, where
10818    <OPERATION> is the name (in all capital letters) of the
10819    user-level routine.  E.g., MatNorm() -> MATOP_NORM.
10820 
10821 .seealso: `MatCreateShell()`
10822 @*/
10823 PetscErrorCode MatHasOperation(Mat mat,MatOperation op,PetscBool *has)
10824 {
10825   PetscFunctionBegin;
10826   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10827   PetscValidBoolPointer(has,3);
10828   if (mat->ops->hasoperation) {
10829     PetscCall((*mat->ops->hasoperation)(mat,op,has));
10830   } else {
10831     if (((void**)mat->ops)[op]) *has = PETSC_TRUE;
10832     else {
10833       *has = PETSC_FALSE;
10834       if (op == MATOP_CREATE_SUBMATRIX) {
10835         PetscMPIInt size;
10836 
10837         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10838         if (size == 1) {
10839           PetscCall(MatHasOperation(mat,MATOP_CREATE_SUBMATRICES,has));
10840         }
10841       }
10842     }
10843   }
10844   PetscFunctionReturn(0);
10845 }
10846 
10847 /*@
10848     MatHasCongruentLayouts - Determines whether the rows and columns layouts
10849     of the matrix are congruent
10850 
10851    Collective on mat
10852 
10853    Input Parameters:
10854 .  mat - the matrix
10855 
10856    Output Parameter:
10857 .  cong - either PETSC_TRUE or PETSC_FALSE
10858 
10859    Level: beginner
10860 
10861    Notes:
10862 
10863 .seealso: `MatCreate()`, `MatSetSizes()`
10864 @*/
10865 PetscErrorCode MatHasCongruentLayouts(Mat mat,PetscBool *cong)
10866 {
10867   PetscFunctionBegin;
10868   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10869   PetscValidType(mat,1);
10870   PetscValidBoolPointer(cong,2);
10871   if (!mat->rmap || !mat->cmap) {
10872     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10873     PetscFunctionReturn(0);
10874   }
10875   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10876     PetscCall(PetscLayoutSetUp(mat->rmap));
10877     PetscCall(PetscLayoutSetUp(mat->cmap));
10878     PetscCall(PetscLayoutCompare(mat->rmap,mat->cmap,cong));
10879     if (*cong) mat->congruentlayouts = 1;
10880     else       mat->congruentlayouts = 0;
10881   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10882   PetscFunctionReturn(0);
10883 }
10884 
10885 PetscErrorCode MatSetInf(Mat A)
10886 {
10887   PetscFunctionBegin;
10888   PetscCheck(A->ops->setinf,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10889   PetscCall((*A->ops->setinf)(A));
10890   PetscFunctionReturn(0);
10891 }
10892 
10893 /*C
10894    MatCreateGraph - create a scalar matrix, for use in graph algorithms
10895 
10896    Collective on mat
10897 
10898    Input Parameters:
10899 +  A - the matrix
10900 -  sym - PETSC_TRUE indicates that the graph will be symmetrized
10901 .  scale - PETSC_TRUE indicates that the graph will be scaled with the diagonal
10902 
10903    Output Parameter:
10904 .  graph - the resulting graph
10905 
10906    Level: advanced
10907 
10908    Notes:
10909 
10910 .seealso: `MatCreate()`, `MatFilter()`
10911 */
10912 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, Mat *graph)
10913 {
10914   PetscFunctionBegin;
10915   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
10916   PetscValidType(A,1);
10917   PetscValidPointer(graph,3);
10918   PetscCheck(A->ops->creategraph,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10919   PetscCall((*A->ops->creategraph)(A,sym,scale,graph));
10920   PetscFunctionReturn(0);
10921 }
10922 
10923 /*C
10924    MatFilter - filters a Mat values with an absolut value equal to or below a give threshold
10925 
10926    Collective on mat
10927 
10928    Input Parameter:
10929 .  value - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries <= value
10930 
10931    Input/Output Parameter:
10932 .  A - the Mat to filter in place
10933 
10934    Level: advanced
10935 
10936    Notes:
10937 
10938 .seealso: `MatCreate()`, `MatCreateGraph()`
10939 */
10940 PETSC_EXTERN PetscErrorCode MatFilter(Mat G,PetscReal value,Mat *F)
10941 {
10942   PetscFunctionBegin;
10943   PetscValidHeaderSpecific(G,MAT_CLASSID,1);
10944   PetscValidType(G,1);
10945   PetscValidPointer(F,3);
10946   if (value >= 0.0) {
10947     PetscCheck(G->ops->filter,PetscObjectComm((PetscObject)G),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10948     PetscCall((G->ops->filter)(G,value,F));
10949   }
10950   PetscFunctionReturn(0);
10951 }
10952