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