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