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