xref: /petsc/src/mat/interface/matrix.c (revision 099c1ef3aaa6581ddf7dc3337ef0a5bdc33c31f7)
1 /*
2    This is where the abstract matrix operations are defined
3 */
4 
5 #include <petsc/private/matimpl.h>        /*I "petscmat.h" I*/
6 #include <petsc/private/isimpl.h>
7 #include <petsc/private/vecimpl.h>
8 
9 /* Logging support */
10 PetscClassId MAT_CLASSID;
11 PetscClassId MAT_COLORING_CLASSID;
12 PetscClassId MAT_FDCOLORING_CLASSID;
13 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
14 
15 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
16 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve,MAT_MatTrSolve;
17 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
18 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
19 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
20 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
21 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
22 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
23 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply,MAT_Transpose,MAT_FDColoringFunction, MAT_CreateSubMat;
24 PetscLogEvent MAT_TransposeColoringCreate;
25 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
26 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric,MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
27 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
28 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
29 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
30 PetscLogEvent MAT_MultHermitianTranspose,MAT_MultHermitianTransposeAdd;
31 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
32 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
33 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
34 PetscLogEvent MAT_GetMultiProcBlock;
35 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
36 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
37 PetscLogEvent MAT_SetValuesBatch;
38 PetscLogEvent MAT_ViennaCLCopyToGPU;
39 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
40 PetscLogEvent MAT_Merge,MAT_Residual,MAT_SetRandom;
41 PetscLogEvent MAT_FactorFactS,MAT_FactorInvS;
42 PetscLogEvent MATCOLORING_Apply,MATCOLORING_Comm,MATCOLORING_Local,MATCOLORING_ISCreate,MATCOLORING_SetUp,MATCOLORING_Weights;
43 PetscLogEvent MAT_H2Opus_Build,MAT_H2Opus_Compress,MAT_H2Opus_Orthog,MAT_H2Opus_LR;
44 
45 const char *const MatFactorTypes[] = {"NONE","LU","CHOLESKY","ILU","ICC","ILUDT","QR","MatFactorType","MAT_FACTOR_",NULL};
46 
47 /*@
48    MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
49                   for sparse matrices that already have locations it fills the locations with random numbers
50 
51    Logically Collective on Mat
52 
53    Input Parameters:
54 +  x  - the matrix
55 -  rctx - the random number context, formed by PetscRandomCreate(), or NULL and
56           it will create one internally.
57 
58    Output Parameter:
59 .  x  - the matrix
60 
61    Example of Usage:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68    Level: intermediate
69 
70 .seealso: `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
71 @*/
72 PetscErrorCode MatSetRandom(Mat x,PetscRandom rctx)
73 {
74   PetscRandom    randObj = NULL;
75 
76   PetscFunctionBegin;
77   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
78   if (rctx) PetscValidHeaderSpecific(rctx,PETSC_RANDOM_CLASSID,2);
79   PetscValidType(x,1);
80   MatCheckPreallocated(x,1);
81 
82   PetscCheck(x->ops->setrandom,PetscObjectComm((PetscObject)x),PETSC_ERR_SUP,"Mat type %s",((PetscObject)x)->type_name);
83 
84   if (!rctx) {
85     MPI_Comm comm;
86     PetscCall(PetscObjectGetComm((PetscObject)x,&comm));
87     PetscCall(PetscRandomCreate(comm,&randObj));
88     PetscCall(PetscRandomSetFromOptions(randObj));
89     rctx = randObj;
90   }
91   PetscCall(PetscLogEventBegin(MAT_SetRandom,x,rctx,0,0));
92   PetscCall((*x->ops->setrandom)(x,rctx));
93   PetscCall(PetscLogEventEnd(MAT_SetRandom,x,rctx,0,0));
94 
95   PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY));
96   PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY));
97   PetscCall(PetscRandomDestroy(&randObj));
98   PetscFunctionReturn(0);
99 }
100 
101 /*@
102    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
103 
104    Logically Collective on Mat
105 
106    Input Parameter:
107 .  mat - the factored matrix
108 
109    Output Parameters:
110 +  pivot - the pivot value computed
111 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
112          the share the matrix
113 
114    Level: advanced
115 
116    Notes:
117     This routine does not work for factorizations done with external packages.
118 
119     This routine should only be called if MatGetFactorError() returns a value of MAT_FACTOR_NUMERIC_ZEROPIVOT
120 
121     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
122 
123 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`
124 @*/
125 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat,PetscReal *pivot,PetscInt *row)
126 {
127   PetscFunctionBegin;
128   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
129   PetscValidRealPointer(pivot,2);
130   PetscValidIntPointer(row,3);
131   *pivot = mat->factorerror_zeropivot_value;
132   *row   = mat->factorerror_zeropivot_row;
133   PetscFunctionReturn(0);
134 }
135 
136 /*@
137    MatFactorGetError - gets the error code from a factorization
138 
139    Logically Collective on Mat
140 
141    Input Parameters:
142 .  mat - the factored matrix
143 
144    Output Parameter:
145 .  err  - the error code
146 
147    Level: advanced
148 
149    Notes:
150     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
151 
152 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`
153 @*/
154 PetscErrorCode MatFactorGetError(Mat mat,MatFactorError *err)
155 {
156   PetscFunctionBegin;
157   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
158   PetscValidPointer(err,2);
159   *err = mat->factorerrortype;
160   PetscFunctionReturn(0);
161 }
162 
163 /*@
164    MatFactorClearError - clears the error code in a factorization
165 
166    Logically Collective on Mat
167 
168    Input Parameter:
169 .  mat - the factored matrix
170 
171    Level: developer
172 
173    Notes:
174     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
175 
176 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`
177 @*/
178 PetscErrorCode MatFactorClearError(Mat mat)
179 {
180   PetscFunctionBegin;
181   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
182   mat->factorerrortype             = MAT_FACTOR_NOERROR;
183   mat->factorerror_zeropivot_value = 0.0;
184   mat->factorerror_zeropivot_row   = 0;
185   PetscFunctionReturn(0);
186 }
187 
188 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat,PetscBool cols,PetscReal tol,IS *nonzero)
189 {
190   Vec               r,l;
191   const PetscScalar *al;
192   PetscInt          i,nz,gnz,N,n;
193 
194   PetscFunctionBegin;
195   PetscCall(MatCreateVecs(mat,&r,&l));
196   if (!cols) { /* nonzero rows */
197     PetscCall(MatGetSize(mat,&N,NULL));
198     PetscCall(MatGetLocalSize(mat,&n,NULL));
199     PetscCall(VecSet(l,0.0));
200     PetscCall(VecSetRandom(r,NULL));
201     PetscCall(MatMult(mat,r,l));
202     PetscCall(VecGetArrayRead(l,&al));
203   } else { /* nonzero columns */
204     PetscCall(MatGetSize(mat,NULL,&N));
205     PetscCall(MatGetLocalSize(mat,NULL,&n));
206     PetscCall(VecSet(r,0.0));
207     PetscCall(VecSetRandom(l,NULL));
208     PetscCall(MatMultTranspose(mat,l,r));
209     PetscCall(VecGetArrayRead(r,&al));
210   }
211   if (tol <= 0.0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nz++; }
212   else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nz++; }
213   PetscCall(MPIU_Allreduce(&nz,&gnz,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
214   if (gnz != N) {
215     PetscInt *nzr;
216     PetscCall(PetscMalloc1(nz,&nzr));
217     if (nz) {
218       if (tol < 0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nzr[nz++] = i; }
219       else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; }
220     }
221     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat),nz,nzr,PETSC_OWN_POINTER,nonzero));
222   } else *nonzero = NULL;
223   if (!cols) { /* nonzero rows */
224     PetscCall(VecRestoreArrayRead(l,&al));
225   } else {
226     PetscCall(VecRestoreArrayRead(r,&al));
227   }
228   PetscCall(VecDestroy(&l));
229   PetscCall(VecDestroy(&r));
230   PetscFunctionReturn(0);
231 }
232 
233 /*@
234       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
235 
236   Input Parameter:
237 .    A  - the matrix
238 
239   Output Parameter:
240 .    keptrows - the rows that are not completely zero
241 
242   Notes:
243     keptrows is set to NULL if all rows are nonzero.
244 
245   Level: intermediate
246 
247  @*/
248 PetscErrorCode MatFindNonzeroRows(Mat mat,IS *keptrows)
249 {
250   PetscFunctionBegin;
251   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
252   PetscValidType(mat,1);
253   PetscValidPointer(keptrows,2);
254   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
255   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
256   if (mat->ops->findnonzerorows) {
257     PetscCall((*mat->ops->findnonzerorows)(mat,keptrows));
258   } else {
259     PetscCall(MatFindNonzeroRowsOrCols_Basic(mat,PETSC_FALSE,0.0,keptrows));
260   }
261   PetscFunctionReturn(0);
262 }
263 
264 /*@
265       MatFindZeroRows - Locate all rows that are completely zero in the matrix
266 
267   Input Parameter:
268 .    A  - the matrix
269 
270   Output Parameter:
271 .    zerorows - the rows that are completely zero
272 
273   Notes:
274     zerorows is set to NULL if no rows are zero.
275 
276   Level: intermediate
277 
278  @*/
279 PetscErrorCode MatFindZeroRows(Mat mat,IS *zerorows)
280 {
281   IS       keptrows;
282   PetscInt m, n;
283 
284   PetscFunctionBegin;
285   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
286   PetscValidType(mat,1);
287   PetscValidPointer(zerorows,2);
288   PetscCall(MatFindNonzeroRows(mat, &keptrows));
289   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
290      In keeping with this convention, we set zerorows to NULL if there are no zero
291      rows. */
292   if (keptrows == NULL) {
293     *zerorows = NULL;
294   } else {
295     PetscCall(MatGetOwnershipRange(mat,&m,&n));
296     PetscCall(ISComplement(keptrows,m,n,zerorows));
297     PetscCall(ISDestroy(&keptrows));
298   }
299   PetscFunctionReturn(0);
300 }
301 
302 /*@
303    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
304 
305    Not Collective
306 
307    Input Parameters:
308 .   A - the matrix
309 
310    Output Parameters:
311 .   a - the diagonal part (which is a SEQUENTIAL matrix)
312 
313    Notes:
314     see the manual page for MatCreateAIJ() for more information on the "diagonal part" of the matrix.
315           Use caution, as the reference count on the returned matrix is not incremented and it is used as
316           part of the containing MPI Mat's normal operation.
317 
318    Level: advanced
319 
320 @*/
321 PetscErrorCode MatGetDiagonalBlock(Mat A,Mat *a)
322 {
323   PetscFunctionBegin;
324   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
325   PetscValidType(A,1);
326   PetscValidPointer(a,2);
327   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
328   if (A->ops->getdiagonalblock) {
329     PetscCall((*A->ops->getdiagonalblock)(A,a));
330   } else {
331     PetscMPIInt size;
332 
333     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
334     PetscCheck(size == 1,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not for parallel matrix type %s",((PetscObject)A)->type_name);
335     *a = A;
336   }
337   PetscFunctionReturn(0);
338 }
339 
340 /*@
341    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
342 
343    Collective on Mat
344 
345    Input Parameters:
346 .  mat - the matrix
347 
348    Output Parameter:
349 .   trace - the sum of the diagonal entries
350 
351    Level: advanced
352 
353 @*/
354 PetscErrorCode MatGetTrace(Mat mat,PetscScalar *trace)
355 {
356   Vec diag;
357 
358   PetscFunctionBegin;
359   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
360   PetscValidScalarPointer(trace,2);
361   PetscCall(MatCreateVecs(mat,&diag,NULL));
362   PetscCall(MatGetDiagonal(mat,diag));
363   PetscCall(VecSum(diag,trace));
364   PetscCall(VecDestroy(&diag));
365   PetscFunctionReturn(0);
366 }
367 
368 /*@
369    MatRealPart - Zeros out the imaginary part of the matrix
370 
371    Logically Collective on Mat
372 
373    Input Parameters:
374 .  mat - the matrix
375 
376    Level: advanced
377 
378 .seealso: `MatImaginaryPart()`
379 @*/
380 PetscErrorCode MatRealPart(Mat mat)
381 {
382   PetscFunctionBegin;
383   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
384   PetscValidType(mat,1);
385   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
386   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
387   PetscCheck(mat->ops->realpart,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
388   MatCheckPreallocated(mat,1);
389   PetscCall((*mat->ops->realpart)(mat));
390   PetscFunctionReturn(0);
391 }
392 
393 /*@C
394    MatGetGhosts - Get the global index of all ghost nodes defined by the sparse matrix
395 
396    Collective on Mat
397 
398    Input Parameter:
399 .  mat - the matrix
400 
401    Output Parameters:
402 +   nghosts - number of ghosts (note for BAIJ matrices there is one ghost for each block)
403 -   ghosts - the global indices of the ghost points
404 
405    Notes:
406     the nghosts and ghosts are suitable to pass into VecCreateGhost()
407 
408    Level: advanced
409 
410 @*/
411 PetscErrorCode MatGetGhosts(Mat mat,PetscInt *nghosts,const PetscInt *ghosts[])
412 {
413   PetscFunctionBegin;
414   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
415   PetscValidType(mat,1);
416   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
417   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
418   if (mat->ops->getghosts) {
419     PetscCall((*mat->ops->getghosts)(mat,nghosts,ghosts));
420   } else {
421     if (nghosts) *nghosts = 0;
422     if (ghosts)  *ghosts  = NULL;
423   }
424   PetscFunctionReturn(0);
425 }
426 
427 /*@
428    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
429 
430    Logically Collective on Mat
431 
432    Input Parameters:
433 .  mat - the matrix
434 
435    Level: advanced
436 
437 .seealso: `MatRealPart()`
438 @*/
439 PetscErrorCode MatImaginaryPart(Mat mat)
440 {
441   PetscFunctionBegin;
442   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
443   PetscValidType(mat,1);
444   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
445   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
446   PetscCheck(mat->ops->imaginarypart,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
447   MatCheckPreallocated(mat,1);
448   PetscCall((*mat->ops->imaginarypart)(mat));
449   PetscFunctionReturn(0);
450 }
451 
452 /*@
453    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for BAIJ matrices)
454 
455    Not Collective
456 
457    Input Parameter:
458 .  mat - the matrix
459 
460    Output Parameters:
461 +  missing - is any diagonal missing
462 -  dd - first diagonal entry that is missing (optional) on this process
463 
464    Level: advanced
465 
466 .seealso: `MatRealPart()`
467 @*/
468 PetscErrorCode MatMissingDiagonal(Mat mat,PetscBool *missing,PetscInt *dd)
469 {
470   PetscFunctionBegin;
471   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
472   PetscValidType(mat,1);
473   PetscValidBoolPointer(missing,2);
474   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix %s",((PetscObject)mat)->type_name);
475   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
476   PetscCheck(mat->ops->missingdiagonal,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
477   PetscCall((*mat->ops->missingdiagonal)(mat,missing,dd));
478   PetscFunctionReturn(0);
479 }
480 
481 /*@C
482    MatGetRow - Gets a row of a matrix.  You MUST call MatRestoreRow()
483    for each row that you get to ensure that your application does
484    not bleed memory.
485 
486    Not Collective
487 
488    Input Parameters:
489 +  mat - the matrix
490 -  row - the row to get
491 
492    Output Parameters:
493 +  ncols -  if not NULL, the number of nonzeros in the row
494 .  cols - if not NULL, the column numbers
495 -  vals - if not NULL, the values
496 
497    Notes:
498    This routine is provided for people who need to have direct access
499    to the structure of a matrix.  We hope that we provide enough
500    high-level matrix routines that few users will need it.
501 
502    MatGetRow() always returns 0-based column indices, regardless of
503    whether the internal representation is 0-based (default) or 1-based.
504 
505    For better efficiency, set cols and/or vals to NULL if you do
506    not wish to extract these quantities.
507 
508    The user can only examine the values extracted with MatGetRow();
509    the values cannot be altered.  To change the matrix entries, one
510    must use MatSetValues().
511 
512    You can only have one call to MatGetRow() outstanding for a particular
513    matrix at a time, per processor. MatGetRow() can only obtain rows
514    associated with the given processor, it cannot get rows from the
515    other processors; for that we suggest using MatCreateSubMatrices(), then
516    MatGetRow() on the submatrix. The row index passed to MatGetRow()
517    is in the global number of rows.
518 
519    Fortran Notes:
520    The calling sequence from Fortran is
521 .vb
522    MatGetRow(matrix,row,ncols,cols,values,ierr)
523          Mat     matrix (input)
524          integer row    (input)
525          integer ncols  (output)
526          integer cols(maxcols) (output)
527          double precision (or double complex) values(maxcols) output
528 .ve
529    where maxcols >= maximum nonzeros in any row of the matrix.
530 
531    Caution:
532    Do not try to change the contents of the output arrays (cols and vals).
533    In some cases, this may corrupt the matrix.
534 
535    Level: advanced
536 
537 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`
538 @*/
539 PetscErrorCode MatGetRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
540 {
541   PetscInt incols;
542 
543   PetscFunctionBegin;
544   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
545   PetscValidType(mat,1);
546   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
547   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
548   PetscCheck(mat->ops->getrow,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
549   MatCheckPreallocated(mat,1);
550   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")",row,mat->rmap->rstart,mat->rmap->rend);
551   PetscCall(PetscLogEventBegin(MAT_GetRow,mat,0,0,0));
552   PetscCall((*mat->ops->getrow)(mat,row,&incols,(PetscInt**)cols,(PetscScalar**)vals));
553   if (ncols) *ncols = incols;
554   PetscCall(PetscLogEventEnd(MAT_GetRow,mat,0,0,0));
555   PetscFunctionReturn(0);
556 }
557 
558 /*@
559    MatConjugate - replaces the matrix values with their complex conjugates
560 
561    Logically Collective on Mat
562 
563    Input Parameters:
564 .  mat - the matrix
565 
566    Level: advanced
567 
568 .seealso: `VecConjugate()`
569 @*/
570 PetscErrorCode MatConjugate(Mat mat)
571 {
572   PetscFunctionBegin;
573   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
574   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
575   if (PetscDefined(USE_COMPLEX)) {
576     PetscCheck(mat->ops->conjugate,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not provided for matrix type %s, send email to petsc-maint@mcs.anl.gov",((PetscObject)mat)->type_name);
577     PetscCall((*mat->ops->conjugate)(mat));
578   }
579   PetscFunctionReturn(0);
580 }
581 
582 /*@C
583    MatRestoreRow - Frees any temporary space allocated by MatGetRow().
584 
585    Not Collective
586 
587    Input Parameters:
588 +  mat - the matrix
589 .  row - the row to get
590 .  ncols, cols - the number of nonzeros and their columns
591 -  vals - if nonzero the column values
592 
593    Notes:
594    This routine should be called after you have finished examining the entries.
595 
596    This routine zeros out ncols, cols, and vals. This is to prevent accidental
597    us of the array after it has been restored. If you pass NULL, it will
598    not zero the pointers.  Use of cols or vals after MatRestoreRow is invalid.
599 
600    Fortran Notes:
601    The calling sequence from Fortran is
602 .vb
603    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
604       Mat     matrix (input)
605       integer row    (input)
606       integer ncols  (output)
607       integer cols(maxcols) (output)
608       double precision (or double complex) values(maxcols) output
609 .ve
610    Where maxcols >= maximum nonzeros in any row of the matrix.
611 
612    In Fortran MatRestoreRow() MUST be called after MatGetRow()
613    before another call to MatGetRow() can be made.
614 
615    Level: advanced
616 
617 .seealso: `MatGetRow()`
618 @*/
619 PetscErrorCode MatRestoreRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
620 {
621   PetscFunctionBegin;
622   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
623   if (ncols) PetscValidIntPointer(ncols,3);
624   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
625   if (!mat->ops->restorerow) PetscFunctionReturn(0);
626   PetscCall((*mat->ops->restorerow)(mat,row,ncols,(PetscInt **)cols,(PetscScalar **)vals));
627   if (ncols) *ncols = 0;
628   if (cols)  *cols = NULL;
629   if (vals)  *vals = NULL;
630   PetscFunctionReturn(0);
631 }
632 
633 /*@
634    MatGetRowUpperTriangular - Sets a flag to enable calls to MatGetRow() for matrix in MATSBAIJ format.
635    You should call MatRestoreRowUpperTriangular() after calling MatGetRow/MatRestoreRow() to disable the flag.
636 
637    Not Collective
638 
639    Input Parameters:
640 .  mat - the matrix
641 
642    Notes:
643    The flag is to ensure that users are aware of MatGetRow() only provides the upper triangular part of the row for the matrices in MATSBAIJ format.
644 
645    Level: advanced
646 
647 .seealso: `MatRestoreRowUpperTriangular()`
648 @*/
649 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
650 {
651   PetscFunctionBegin;
652   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
653   PetscValidType(mat,1);
654   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
655   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
656   MatCheckPreallocated(mat,1);
657   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
658   PetscCall((*mat->ops->getrowuppertriangular)(mat));
659   PetscFunctionReturn(0);
660 }
661 
662 /*@
663    MatRestoreRowUpperTriangular - Disable calls to MatGetRow() for matrix in MATSBAIJ format.
664 
665    Not Collective
666 
667    Input Parameters:
668 .  mat - the matrix
669 
670    Notes:
671    This routine should be called after you have finished MatGetRow/MatRestoreRow().
672 
673    Level: advanced
674 
675 .seealso: `MatGetRowUpperTriangular()`
676 @*/
677 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
678 {
679   PetscFunctionBegin;
680   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
681   PetscValidType(mat,1);
682   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
683   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
684   MatCheckPreallocated(mat,1);
685   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
686   PetscCall((*mat->ops->restorerowuppertriangular)(mat));
687   PetscFunctionReturn(0);
688 }
689 
690 /*@C
691    MatSetOptionsPrefix - Sets the prefix used for searching for all
692    Mat options in the database.
693 
694    Logically Collective on Mat
695 
696    Input Parameters:
697 +  A - the Mat context
698 -  prefix - the prefix to prepend to all option names
699 
700    Notes:
701    A hyphen (-) must NOT be given at the beginning of the prefix name.
702    The first character of all runtime options is AUTOMATICALLY the hyphen.
703 
704    This is NOT used for options for the factorization of the matrix. Normally the
705    prefix is automatically passed in from the PC calling the factorization. To set
706    it directly use  `MatSetOptionsPrefixFactor()`
707 
708    Level: advanced
709 
710 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
711 @*/
712 PetscErrorCode MatSetOptionsPrefix(Mat A,const char prefix[])
713 {
714   PetscFunctionBegin;
715   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
716   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A,prefix));
717   PetscFunctionReturn(0);
718 }
719 
720 /*@C
721    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all Mat factor options in the database for
722    for matrices created with `MatGetFactor()`
723 
724    Logically Collective on Mat
725 
726    Input Parameters:
727 +  A - the Mat context
728 -  prefix - the prefix to prepend to all option names for the factored matrix
729 
730    Notes:
731    A hyphen (-) must NOT be given at the beginning of the prefix name.
732    The first character of all runtime options is AUTOMATICALLY the hyphen.
733 
734    Normally the prefix is automatically passed in from the PC calling the factorization. To set
735    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
736 
737    Level: developer
738 
739 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
740 @*/
741 PetscErrorCode MatSetOptionsPrefixFactor(Mat A,const char prefix[])
742 {
743   PetscFunctionBegin;
744   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
745   if (prefix) {
746     PetscValidCharPointer(prefix,2);
747     PetscCheck(prefix[0] != '-',PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
748     if (prefix != A->factorprefix) {
749       PetscCall(PetscFree(A->factorprefix));
750       PetscCall(PetscStrallocpy(prefix,&A->factorprefix));
751     }
752   } else PetscCall(PetscFree(A->factorprefix));
753   PetscFunctionReturn(0);
754 }
755 
756 /*@C
757    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all Mat factor options in the database for
758    for matrices created with `MatGetFactor()`
759 
760    Logically Collective on Mat
761 
762    Input Parameters:
763 +  A - the Mat context
764 -  prefix - the prefix to prepend to all option names for the factored matrix
765 
766    Notes:
767    A hyphen (-) must NOT be given at the beginning of the prefix name.
768    The first character of all runtime options is AUTOMATICALLY the hyphen.
769 
770    Normally the prefix is automatically passed in from the PC calling the factorization. To set
771    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
772 
773    Level: developer
774    .seealso: `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
775              `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
776              `MatSetOptionsPrefix()`
777 @*/
778 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A,const char prefix[])
779 {
780   char           *buf = A->factorprefix;
781   size_t         len1,len2;
782 
783   PetscFunctionBegin;
784   PetscValidHeader(A,1);
785   if (!prefix) PetscFunctionReturn(0);
786   if (!buf) {
787     PetscCall(MatSetOptionsPrefixFactor(A,prefix));
788     PetscFunctionReturn(0);
789   }
790   PetscCheck(prefix[0] != '-',PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
791 
792   PetscCall(PetscStrlen(prefix,&len1));
793   PetscCall(PetscStrlen(buf,&len2));
794   PetscCall(PetscMalloc1(1+len1+len2,&A->factorprefix));
795   PetscCall(PetscStrcpy(A->factorprefix,buf));
796   PetscCall(PetscStrcat(A->factorprefix,prefix));
797   PetscCall(PetscFree(buf));
798   PetscFunctionReturn(0);
799 }
800 
801 /*@C
802    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
803    Mat options in the database.
804 
805    Logically Collective on Mat
806 
807    Input Parameters:
808 +  A - the Mat context
809 -  prefix - the prefix to prepend to all option names
810 
811    Notes:
812    A hyphen (-) must NOT be given at the beginning of the prefix name.
813    The first character of all runtime options is AUTOMATICALLY the hyphen.
814 
815    Level: advanced
816 
817 .seealso: `MatGetOptionsPrefix()`
818 @*/
819 PetscErrorCode MatAppendOptionsPrefix(Mat A,const char prefix[])
820 {
821   PetscFunctionBegin;
822   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
823   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A,prefix));
824   PetscFunctionReturn(0);
825 }
826 
827 /*@C
828    MatGetOptionsPrefix - Gets the prefix used for searching for all
829    Mat options in the database.
830 
831    Not Collective
832 
833    Input Parameter:
834 .  A - the Mat context
835 
836    Output Parameter:
837 .  prefix - pointer to the prefix string used
838 
839    Notes:
840     On the fortran side, the user should pass in a string 'prefix' of
841    sufficient length to hold the prefix.
842 
843    Level: advanced
844 
845 .seealso: `MatAppendOptionsPrefix()`
846 @*/
847 PetscErrorCode MatGetOptionsPrefix(Mat A,const char *prefix[])
848 {
849   PetscFunctionBegin;
850   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
851   PetscValidPointer(prefix,2);
852   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A,prefix));
853   PetscFunctionReturn(0);
854 }
855 
856 /*@
857    MatResetPreallocation - Reset mat to use the original nonzero pattern provided by users.
858 
859    Collective on Mat
860 
861    Input Parameters:
862 .  A - the Mat context
863 
864    Notes:
865    The allocated memory will be shrunk after calling MatAssembly with MAT_FINAL_ASSEMBLY. Users can reset the preallocation to access the original memory.
866    Currently support MPIAIJ and SEQAIJ.
867 
868    Level: beginner
869 
870 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
871 @*/
872 PetscErrorCode MatResetPreallocation(Mat A)
873 {
874   PetscFunctionBegin;
875   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
876   PetscValidType(A,1);
877   PetscUseMethod(A,"MatResetPreallocation_C",(Mat),(A));
878   PetscFunctionReturn(0);
879 }
880 
881 /*@
882    MatSetUp - Sets up the internal matrix data structures for later use.
883 
884    Collective on Mat
885 
886    Input Parameters:
887 .  A - the Mat context
888 
889    Notes:
890    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
891 
892    If a suitable preallocation routine is used, this function does not need to be called.
893 
894    See the Performance chapter of the PETSc users manual for how to preallocate matrices
895 
896    Level: beginner
897 
898 .seealso: `MatCreate()`, `MatDestroy()`
899 @*/
900 PetscErrorCode MatSetUp(Mat A)
901 {
902   PetscFunctionBegin;
903   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
904   if (!((PetscObject)A)->type_name) {
905     PetscMPIInt size;
906 
907     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
908     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
909   }
910   if (!A->preallocated && A->ops->setup) {
911     PetscCall(PetscInfo(A,"Warning not preallocating matrix storage\n"));
912     PetscCall((*A->ops->setup)(A));
913   }
914   PetscCall(PetscLayoutSetUp(A->rmap));
915   PetscCall(PetscLayoutSetUp(A->cmap));
916   A->preallocated = PETSC_TRUE;
917   PetscFunctionReturn(0);
918 }
919 
920 #if defined(PETSC_HAVE_SAWS)
921 #include <petscviewersaws.h>
922 #endif
923 
924 /*@C
925    MatViewFromOptions - View from Options
926 
927    Collective on Mat
928 
929    Input Parameters:
930 +  A - the Mat context
931 .  obj - Optional object
932 -  name - command line option
933 
934    Level: intermediate
935 .seealso: `Mat`, `MatView`, `PetscObjectViewFromOptions()`, `MatCreate()`
936 @*/
937 PetscErrorCode  MatViewFromOptions(Mat A,PetscObject obj,const char name[])
938 {
939   PetscFunctionBegin;
940   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
941   PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name));
942   PetscFunctionReturn(0);
943 }
944 
945 /*@C
946    MatView - Visualizes a matrix object.
947 
948    Collective on Mat
949 
950    Input Parameters:
951 +  mat - the matrix
952 -  viewer - visualization context
953 
954   Notes:
955   The available visualization contexts include
956 +    PETSC_VIEWER_STDOUT_SELF - for sequential matrices
957 .    PETSC_VIEWER_STDOUT_WORLD - for parallel matrices created on PETSC_COMM_WORLD
958 .    PETSC_VIEWER_STDOUT_(comm) - for matrices created on MPI communicator comm
959 -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
960 
961    The user can open alternative visualization contexts with
962 +    PetscViewerASCIIOpen() - Outputs matrix to a specified file
963 .    PetscViewerBinaryOpen() - Outputs matrix in binary to a
964          specified file; corresponding input uses MatLoad()
965 .    PetscViewerDrawOpen() - Outputs nonzero matrix structure to
966          an X window display
967 -    PetscViewerSocketOpen() - Outputs matrix to Socket viewer.
968          Currently only the sequential dense and AIJ
969          matrix types support the Socket viewer.
970 
971    The user can call PetscViewerPushFormat() to specify the output
972    format of ASCII printed objects (when using PETSC_VIEWER_STDOUT_SELF,
973    PETSC_VIEWER_STDOUT_WORLD and PetscViewerASCIIOpen).  Available formats include
974 +    PETSC_VIEWER_DEFAULT - default, prints matrix contents
975 .    PETSC_VIEWER_ASCII_MATLAB - prints matrix contents in Matlab format
976 .    PETSC_VIEWER_ASCII_DENSE - prints entire matrix including zeros
977 .    PETSC_VIEWER_ASCII_COMMON - prints matrix contents, using a sparse
978          format common among all matrix types
979 .    PETSC_VIEWER_ASCII_IMPL - prints matrix contents, using an implementation-specific
980          format (which is in many cases the same as the default)
981 .    PETSC_VIEWER_ASCII_INFO - prints basic information about the matrix
982          size and structure (not the matrix entries)
983 -    PETSC_VIEWER_ASCII_INFO_DETAIL - prints more detailed information about
984          the matrix structure
985 
986    Options Database Keys:
987 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatAssemblyEnd()
988 .  -mat_view ::ascii_info_detail - Prints more detailed info
989 .  -mat_view - Prints matrix in ASCII format
990 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
991 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
992 .  -display <name> - Sets display name (default is host)
993 .  -draw_pause <sec> - Sets number of seconds to pause after display
994 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
995 .  -viewer_socket_machine <machine> -
996 .  -viewer_socket_port <port> -
997 .  -mat_view binary - save matrix to file in binary format
998 -  -viewer_binary_filename <name> -
999 
1000    Level: beginner
1001 
1002    Notes:
1003     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1004     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1005 
1006     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1007 
1008     See the manual page for MatLoad() for the exact format of the binary file when the binary
1009       viewer is used.
1010 
1011       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1012       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1013 
1014       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1015       and then use the following mouse functions.
1016 .vb
1017   left mouse: zoom in
1018   middle mouse: zoom out
1019   right mouse: continue with the simulation
1020 .ve
1021 
1022 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`,
1023           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`
1024 @*/
1025 PetscErrorCode MatView(Mat mat,PetscViewer viewer)
1026 {
1027   PetscInt          rows,cols,rbs,cbs;
1028   PetscBool         isascii,isstring,issaws;
1029   PetscViewerFormat format;
1030   PetscMPIInt       size;
1031 
1032   PetscFunctionBegin;
1033   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1034   PetscValidType(mat,1);
1035   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat),&viewer));
1036   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1037   PetscCheckSameComm(mat,1,viewer,2);
1038   MatCheckPreallocated(mat,1);
1039 
1040   PetscCall(PetscViewerGetFormat(viewer,&format));
1041   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
1042   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1043 
1044   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring));
1045   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
1046   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws));
1047   if ((!isascii || (format != PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) && mat->factortype) {
1048     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"No viewers for factored matrix except ASCII info or info_detail");
1049   }
1050 
1051   PetscCall(PetscLogEventBegin(MAT_View,mat,viewer,0,0));
1052   if (isascii) {
1053     PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Must call MatAssemblyBegin/End() before viewing matrix");
1054     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat,viewer));
1055     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1056       MatNullSpace nullsp,transnullsp;
1057 
1058       PetscCall(PetscViewerASCIIPushTab(viewer));
1059       PetscCall(MatGetSize(mat,&rows,&cols));
1060       PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
1061       if (rbs != 1 || cbs != 1) {
1062         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n",rows,cols,rbs,cbs));
1063         else            PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n",rows,cols,rbs));
1064       } else PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n",rows,cols));
1065       if (mat->factortype) {
1066         MatSolverType solver;
1067         PetscCall(MatFactorGetSolverType(mat,&solver));
1068         PetscCall(PetscViewerASCIIPrintf(viewer,"package used to perform factorization: %s\n",solver));
1069       }
1070       if (mat->ops->getinfo) {
1071         MatInfo info;
1072         PetscCall(MatGetInfo(mat,MAT_GLOBAL_SUM,&info));
1073         PetscCall(PetscViewerASCIIPrintf(viewer,"total: nonzeros=%.f, allocated nonzeros=%.f\n",info.nz_used,info.nz_allocated));
1074         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer,"total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n",(PetscInt)info.mallocs));
1075       }
1076       PetscCall(MatGetNullSpace(mat,&nullsp));
1077       PetscCall(MatGetTransposeNullSpace(mat,&transnullsp));
1078       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached null space\n"));
1079       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached transposed null space\n"));
1080       PetscCall(MatGetNearNullSpace(mat,&nullsp));
1081       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached near null space\n"));
1082       PetscCall(PetscViewerASCIIPushTab(viewer));
1083       PetscCall(MatProductView(mat,viewer));
1084       PetscCall(PetscViewerASCIIPopTab(viewer));
1085     }
1086   } else if (issaws) {
1087 #if defined(PETSC_HAVE_SAWS)
1088     PetscMPIInt rank;
1089 
1090     PetscCall(PetscObjectName((PetscObject)mat));
1091     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
1092     if (!((PetscObject)mat)->amsmem && rank == 0) {
1093       PetscCall(PetscObjectViewSAWs((PetscObject)mat,viewer));
1094     }
1095 #endif
1096   } else if (isstring) {
1097     const char *type;
1098     PetscCall(MatGetType(mat,&type));
1099     PetscCall(PetscViewerStringSPrintf(viewer," MatType: %-7.7s",type));
1100     if (mat->ops->view) PetscCall((*mat->ops->view)(mat,viewer));
1101   }
1102   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1103     PetscCall(PetscViewerASCIIPushTab(viewer));
1104     PetscCall((*mat->ops->viewnative)(mat,viewer));
1105     PetscCall(PetscViewerASCIIPopTab(viewer));
1106   } else if (mat->ops->view) {
1107     PetscCall(PetscViewerASCIIPushTab(viewer));
1108     PetscCall((*mat->ops->view)(mat,viewer));
1109     PetscCall(PetscViewerASCIIPopTab(viewer));
1110   }
1111   if (isascii) {
1112     PetscCall(PetscViewerGetFormat(viewer,&format));
1113     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1114       PetscCall(PetscViewerASCIIPopTab(viewer));
1115     }
1116   }
1117   PetscCall(PetscLogEventEnd(MAT_View,mat,viewer,0,0));
1118   PetscFunctionReturn(0);
1119 }
1120 
1121 #if defined(PETSC_USE_DEBUG)
1122 #include <../src/sys/totalview/tv_data_display.h>
1123 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1124 {
1125   TV_add_row("Local rows", "int", &mat->rmap->n);
1126   TV_add_row("Local columns", "int", &mat->cmap->n);
1127   TV_add_row("Global rows", "int", &mat->rmap->N);
1128   TV_add_row("Global columns", "int", &mat->cmap->N);
1129   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1130   return TV_format_OK;
1131 }
1132 #endif
1133 
1134 /*@C
1135    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1136    with MatView().  The matrix format is determined from the options database.
1137    Generates a parallel MPI matrix if the communicator has more than one
1138    processor.  The default matrix type is AIJ.
1139 
1140    Collective on PetscViewer
1141 
1142    Input Parameters:
1143 +  mat - the newly loaded matrix, this needs to have been created with MatCreate()
1144             or some related function before a call to MatLoad()
1145 -  viewer - binary/HDF5 file viewer
1146 
1147    Options Database Keys:
1148    Used with block matrix formats (MATSEQBAIJ,  ...) to specify
1149    block size
1150 .    -matload_block_size <bs> - set block size
1151 
1152    Level: beginner
1153 
1154    Notes:
1155    If the Mat type has not yet been given then MATAIJ is used, call MatSetFromOptions() on the
1156    Mat before calling this routine if you wish to set it from the options database.
1157 
1158    MatLoad() automatically loads into the options database any options
1159    given in the file filename.info where filename is the name of the file
1160    that was passed to the PetscViewerBinaryOpen(). The options in the info
1161    file will be ignored if you use the -viewer_binary_skip_info option.
1162 
1163    If the type or size of mat is not set before a call to MatLoad, PETSc
1164    sets the default matrix type AIJ and sets the local and global sizes.
1165    If type and/or size is already set, then the same are used.
1166 
1167    In parallel, each processor can load a subset of rows (or the
1168    entire matrix).  This routine is especially useful when a large
1169    matrix is stored on disk and only part of it is desired on each
1170    processor.  For example, a parallel solver may access only some of
1171    the rows from each processor.  The algorithm used here reads
1172    relatively small blocks of data rather than reading the entire
1173    matrix and then subsetting it.
1174 
1175    Viewer's PetscViewerType must be either PETSCVIEWERBINARY or PETSCVIEWERHDF5.
1176    Such viewer can be created using PetscViewerBinaryOpen()/PetscViewerHDF5Open(),
1177    or the sequence like
1178 $    PetscViewer v;
1179 $    PetscViewerCreate(PETSC_COMM_WORLD,&v);
1180 $    PetscViewerSetType(v,PETSCVIEWERBINARY);
1181 $    PetscViewerSetFromOptions(v);
1182 $    PetscViewerFileSetMode(v,FILE_MODE_READ);
1183 $    PetscViewerFileSetName(v,"datafile");
1184    The optional PetscViewerSetFromOptions() call allows to override PetscViewerSetType() using option
1185 $ -viewer_type {binary,hdf5}
1186 
1187    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1188    and src/mat/tutorials/ex10.c with the second approach.
1189 
1190    Notes about the PETSc binary format:
1191    In case of PETSCVIEWERBINARY, a native PETSc binary format is used. Each of the blocks
1192    is read onto rank 0 and then shipped to its destination rank, one after another.
1193    Multiple objects, both matrices and vectors, can be stored within the same file.
1194    Their PetscObject name is ignored; they are loaded in the order of their storage.
1195 
1196    Most users should not need to know the details of the binary storage
1197    format, since MatLoad() and MatView() completely hide these details.
1198    But for anyone who's interested, the standard binary matrix storage
1199    format is
1200 
1201 $    PetscInt    MAT_FILE_CLASSID
1202 $    PetscInt    number of rows
1203 $    PetscInt    number of columns
1204 $    PetscInt    total number of nonzeros
1205 $    PetscInt    *number nonzeros in each row
1206 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1207 $    PetscScalar *values of all nonzeros
1208 
1209    PETSc automatically does the byte swapping for
1210 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1211 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1212 read/write routines you have to swap the bytes; see PetscBinaryRead()
1213 and PetscBinaryWrite() to see how this may be done.
1214 
1215    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1216    In case of PETSCVIEWERHDF5, a parallel HDF5 reader is used.
1217    Each processor's chunk is loaded independently by its owning rank.
1218    Multiple objects, both matrices and vectors, can be stored within the same file.
1219    They are looked up by their PetscObject name.
1220 
1221    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1222    by default the same structure and naming of the AIJ arrays and column count
1223    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1224 $    save example.mat A b -v7.3
1225    can be directly read by this routine (see Reference 1 for details).
1226    Note that depending on your MATLAB version, this format might be a default,
1227    otherwise you can set it as default in Preferences.
1228 
1229    Unless -nocompression flag is used to save the file in MATLAB,
1230    PETSc must be configured with ZLIB package.
1231 
1232    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1233 
1234    Current HDF5 (MAT-File) limitations:
1235    This reader currently supports only real MATSEQAIJ, MATMPIAIJ, MATSEQDENSE and MATMPIDENSE matrices.
1236 
1237    Corresponding MatView() is not yet implemented.
1238 
1239    The loaded matrix is actually a transpose of the original one in MATLAB,
1240    unless you push PETSC_VIEWER_HDF5_MAT format (see examples above).
1241    With this format, matrix is automatically transposed by PETSc,
1242    unless the matrix is marked as SPD or symmetric
1243    (see MatSetOption(), MAT_SPD, MAT_SYMMETRIC).
1244 
1245    References:
1246 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1247 
1248 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1249 
1250  @*/
1251 PetscErrorCode MatLoad(Mat mat,PetscViewer viewer)
1252 {
1253   PetscBool flg;
1254 
1255   PetscFunctionBegin;
1256   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1257   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1258 
1259   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat,MATAIJ));
1260 
1261   flg  = PETSC_FALSE;
1262   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matload_symmetric",&flg,NULL));
1263   if (flg) {
1264     PetscCall(MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE));
1265     PetscCall(MatSetOption(mat,MAT_SYMMETRY_ETERNAL,PETSC_TRUE));
1266   }
1267   flg  = PETSC_FALSE;
1268   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matload_spd",&flg,NULL));
1269   if (flg) PetscCall(MatSetOption(mat,MAT_SPD,PETSC_TRUE));
1270 
1271   PetscCheck(mat->ops->load,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatLoad is not supported for type %s",((PetscObject)mat)->type_name);
1272   PetscCall(PetscLogEventBegin(MAT_Load,mat,viewer,0,0));
1273   PetscCall((*mat->ops->load)(mat,viewer));
1274   PetscCall(PetscLogEventEnd(MAT_Load,mat,viewer,0,0));
1275   PetscFunctionReturn(0);
1276 }
1277 
1278 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1279 {
1280   Mat_Redundant *redund = *redundant;
1281 
1282   PetscFunctionBegin;
1283   if (redund) {
1284     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1285       PetscCall(ISDestroy(&redund->isrow));
1286       PetscCall(ISDestroy(&redund->iscol));
1287       PetscCall(MatDestroySubMatrices(1,&redund->matseq));
1288     } else {
1289       PetscCall(PetscFree2(redund->send_rank,redund->recv_rank));
1290       PetscCall(PetscFree(redund->sbuf_j));
1291       PetscCall(PetscFree(redund->sbuf_a));
1292       for (PetscInt i=0; i<redund->nrecvs; i++) {
1293         PetscCall(PetscFree(redund->rbuf_j[i]));
1294         PetscCall(PetscFree(redund->rbuf_a[i]));
1295       }
1296       PetscCall(PetscFree4(redund->sbuf_nz,redund->rbuf_nz,redund->rbuf_j,redund->rbuf_a));
1297     }
1298 
1299     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1300     PetscCall(PetscFree(redund));
1301   }
1302   PetscFunctionReturn(0);
1303 }
1304 
1305 /*@C
1306    MatDestroy - Frees space taken by a matrix.
1307 
1308    Collective on Mat
1309 
1310    Input Parameter:
1311 .  A - the matrix
1312 
1313    Level: beginner
1314 
1315    Developer Notes:
1316    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1317    MatDestroySubMatrices(). Thus one must be sure that any changes here must also be made in those routines.
1318    MatHeaderMerge() and MatHeaderReplace() also manipulate the data in the Mat object and likely need changes
1319    if changes are needed here.
1320 @*/
1321 PetscErrorCode MatDestroy(Mat *A)
1322 {
1323   PetscFunctionBegin;
1324   if (!*A) PetscFunctionReturn(0);
1325   PetscValidHeaderSpecific(*A,MAT_CLASSID,1);
1326   if (--((PetscObject)(*A))->refct > 0) {*A = NULL; PetscFunctionReturn(0);}
1327 
1328   /* if memory was published with SAWs then destroy it */
1329   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1330   if ((*A)->ops->destroy) PetscCall((*(*A)->ops->destroy)(*A));
1331 
1332   PetscCall(PetscFree((*A)->factorprefix));
1333   PetscCall(PetscFree((*A)->defaultvectype));
1334   PetscCall(PetscFree((*A)->bsizes));
1335   PetscCall(PetscFree((*A)->solvertype));
1336   for (PetscInt i=0; i<MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1337   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1338   PetscCall(MatProductClear(*A));
1339   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1340   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1341   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1342   PetscCall(MatDestroy(&(*A)->schur));
1343   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1344   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1345   PetscCall(PetscHeaderDestroy(A));
1346   PetscFunctionReturn(0);
1347 }
1348 
1349 /*@C
1350    MatSetValues - Inserts or adds a block of values into a matrix.
1351    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
1352    MUST be called after all calls to MatSetValues() have been completed.
1353 
1354    Not Collective
1355 
1356    Input Parameters:
1357 +  mat - the matrix
1358 .  v - a logically two-dimensional array of values
1359 .  m, idxm - the number of rows and their global indices
1360 .  n, idxn - the number of columns and their global indices
1361 -  addv - either ADD_VALUES or INSERT_VALUES, where
1362    ADD_VALUES adds values to any existing entries, and
1363    INSERT_VALUES replaces existing entries with new values
1364 
1365    Notes:
1366    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
1367       MatSetUp() before using this routine
1368 
1369    By default the values, v, are row-oriented. See MatSetOption() for other options.
1370 
1371    Calls to MatSetValues() with the INSERT_VALUES and ADD_VALUES
1372    options cannot be mixed without intervening calls to the assembly
1373    routines.
1374 
1375    MatSetValues() uses 0-based row and column numbers in Fortran
1376    as well as in C.
1377 
1378    Negative indices may be passed in idxm and idxn, these rows and columns are
1379    simply ignored. This allows easily inserting element stiffness matrices
1380    with homogeneous Dirchlet boundary conditions that you don't want represented
1381    in the matrix.
1382 
1383    Efficiency Alert:
1384    The routine MatSetValuesBlocked() may offer much better efficiency
1385    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1386 
1387    Level: beginner
1388 
1389    Developer Notes:
1390     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1391                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1392 
1393 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1394           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1395 @*/
1396 PetscErrorCode MatSetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1397 {
1398   PetscFunctionBeginHot;
1399   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1400   PetscValidType(mat,1);
1401   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1402   PetscValidIntPointer(idxm,3);
1403   PetscValidIntPointer(idxn,5);
1404   MatCheckPreallocated(mat,1);
1405 
1406   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1407   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1408 
1409   if (PetscDefined(USE_DEBUG)) {
1410     PetscInt       i,j;
1411 
1412     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1413     PetscCheck(mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1414 
1415     for (i=0; i<m; i++) {
1416       for (j=0; j<n; j++) {
1417         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i*n+j]))
1418 #if defined(PETSC_USE_COMPLEX)
1419           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")",(double)PetscRealPart(v[i*n+j]),(double)PetscImaginaryPart(v[i*n+j]),idxm[i],idxn[j]);
1420 #else
1421           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")",(double)v[i*n+j],idxm[i],idxn[j]);
1422 #endif
1423       }
1424     }
1425     for (i=0; i<m; i++) PetscCheck(idxm[i] < mat->rmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT,idxm[i],mat->rmap->N-1);
1426     for (i=0; i<n; i++) PetscCheck(idxn[i] < mat->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT,idxn[i],mat->cmap->N-1);
1427   }
1428 
1429   if (mat->assembled) {
1430     mat->was_assembled = PETSC_TRUE;
1431     mat->assembled     = PETSC_FALSE;
1432   }
1433   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1434   PetscCall((*mat->ops->setvalues)(mat,m,idxm,n,idxn,v,addv));
1435   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1436   PetscFunctionReturn(0);
1437 }
1438 
1439 /*@C
1440    MatSetValuesIS - Inserts or adds a block of values into a matrix using IS to indicate the rows and columns
1441    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
1442    MUST be called after all calls to MatSetValues() have been completed.
1443 
1444    Not Collective
1445 
1446    Input Parameters:
1447 +  mat - the matrix
1448 .  v - a logically two-dimensional array of values
1449 .  ism - the rows to provide
1450 .  isn - the columns to provide
1451 -  addv - either ADD_VALUES or INSERT_VALUES, where
1452    ADD_VALUES adds values to any existing entries, and
1453    INSERT_VALUES replaces existing entries with new values
1454 
1455    Notes:
1456    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
1457       MatSetUp() before using this routine
1458 
1459    By default the values, v, are row-oriented. See MatSetOption() for other options.
1460 
1461    Calls to MatSetValues() with the INSERT_VALUES and ADD_VALUES
1462    options cannot be mixed without intervening calls to the assembly
1463    routines.
1464 
1465    MatSetValues() uses 0-based row and column numbers in Fortran
1466    as well as in C.
1467 
1468    Negative indices may be passed in ism and isn, these rows and columns are
1469    simply ignored. This allows easily inserting element stiffness matrices
1470    with homogeneous Dirchlet boundary conditions that you don't want represented
1471    in the matrix.
1472 
1473    Efficiency Alert:
1474    The routine MatSetValuesBlocked() may offer much better efficiency
1475    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1476 
1477    Level: beginner
1478 
1479    Developer Notes:
1480     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1481                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1482 
1483     This is currently not optimized for any particular IS type
1484 
1485 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal(),
1486           InsertMode, INSERT_VALUES, ADD_VALUES, MatSetValues()
1487 @*/
1488 PetscErrorCode MatSetValuesIS(Mat mat,IS ism,IS isn,const PetscScalar v[],InsertMode addv)
1489 {
1490   PetscInt       m,n;
1491   const PetscInt *rows,*cols;
1492 
1493   PetscFunctionBeginHot;
1494   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1495   PetscCall(ISGetIndices(ism,&rows));
1496   PetscCall(ISGetIndices(isn,&cols));
1497   PetscCall(ISGetLocalSize(ism,&m));
1498   PetscCall(ISGetLocalSize(isn,&n));
1499   PetscCall(MatSetValues(mat,m,rows,n,cols,v,addv));
1500   PetscCall(ISRestoreIndices(ism,&rows));
1501   PetscCall(ISRestoreIndices(isn,&cols));
1502   PetscFunctionReturn(0);
1503 }
1504 
1505 /*@
1506    MatSetValuesRowLocal - Inserts a row (block row for BAIJ matrices) of nonzero
1507         values into a matrix
1508 
1509    Not Collective
1510 
1511    Input Parameters:
1512 +  mat - the matrix
1513 .  row - the (block) row to set
1514 -  v - a logically two-dimensional array of values
1515 
1516    Notes:
1517    By the values, v, are column-oriented (for the block version) and sorted
1518 
1519    All the nonzeros in the row must be provided
1520 
1521    The matrix must have previously had its column indices set
1522 
1523    The row must belong to this process
1524 
1525    Level: intermediate
1526 
1527 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1528           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1529 @*/
1530 PetscErrorCode MatSetValuesRowLocal(Mat mat,PetscInt row,const PetscScalar v[])
1531 {
1532   PetscInt globalrow;
1533 
1534   PetscFunctionBegin;
1535   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1536   PetscValidType(mat,1);
1537   PetscValidScalarPointer(v,3);
1538   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,1,&row,&globalrow));
1539   PetscCall(MatSetValuesRow(mat,globalrow,v));
1540   PetscFunctionReturn(0);
1541 }
1542 
1543 /*@
1544    MatSetValuesRow - Inserts a row (block row for BAIJ matrices) of nonzero
1545         values into a matrix
1546 
1547    Not Collective
1548 
1549    Input Parameters:
1550 +  mat - the matrix
1551 .  row - the (block) row to set
1552 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1553 
1554    Notes:
1555    The values, v, are column-oriented for the block version.
1556 
1557    All the nonzeros in the row must be provided
1558 
1559    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually MatSetValues() is used.
1560 
1561    The row must belong to this process
1562 
1563    Level: advanced
1564 
1565 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1566           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1567 @*/
1568 PetscErrorCode MatSetValuesRow(Mat mat,PetscInt row,const PetscScalar v[])
1569 {
1570   PetscFunctionBeginHot;
1571   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1572   PetscValidType(mat,1);
1573   MatCheckPreallocated(mat,1);
1574   PetscValidScalarPointer(v,3);
1575   PetscCheck(mat->insertmode != ADD_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add and insert values");
1576   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1577   mat->insertmode = INSERT_VALUES;
1578 
1579   if (mat->assembled) {
1580     mat->was_assembled = PETSC_TRUE;
1581     mat->assembled     = PETSC_FALSE;
1582   }
1583   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1584   PetscCheck(mat->ops->setvaluesrow,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1585   PetscCall((*mat->ops->setvaluesrow)(mat,row,v));
1586   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1587   PetscFunctionReturn(0);
1588 }
1589 
1590 /*@
1591    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1592      Using structured grid indexing
1593 
1594    Not Collective
1595 
1596    Input Parameters:
1597 +  mat - the matrix
1598 .  m - number of rows being entered
1599 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1600 .  n - number of columns being entered
1601 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1602 .  v - a logically two-dimensional array of values
1603 -  addv - either ADD_VALUES or INSERT_VALUES, where
1604    ADD_VALUES adds values to any existing entries, and
1605    INSERT_VALUES replaces existing entries with new values
1606 
1607    Notes:
1608    By default the values, v, are row-oriented.  See MatSetOption() for other options.
1609 
1610    Calls to MatSetValuesStencil() with the INSERT_VALUES and ADD_VALUES
1611    options cannot be mixed without intervening calls to the assembly
1612    routines.
1613 
1614    The grid coordinates are across the entire grid, not just the local portion
1615 
1616    MatSetValuesStencil() uses 0-based row and column numbers in Fortran
1617    as well as in C.
1618 
1619    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1620 
1621    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1622    or call MatSetLocalToGlobalMapping() and MatSetStencil() first.
1623 
1624    The columns and rows in the stencil passed in MUST be contained within the
1625    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1626    if you create a DMDA with an overlap of one grid level and on a particular process its first
1627    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1628    first i index you can use in your column and row indices in MatSetStencil() is 5.
1629 
1630    In Fortran idxm and idxn should be declared as
1631 $     MatStencil idxm(4,m),idxn(4,n)
1632    and the values inserted using
1633 $    idxm(MatStencil_i,1) = i
1634 $    idxm(MatStencil_j,1) = j
1635 $    idxm(MatStencil_k,1) = k
1636 $    idxm(MatStencil_c,1) = c
1637    etc
1638 
1639    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1640    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1641    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1642    DM_BOUNDARY_PERIODIC boundary type.
1643 
1644    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1645    a single value per point) you can skip filling those indices.
1646 
1647    Inspired by the structured grid interface to the HYPRE package
1648    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1649 
1650    Efficiency Alert:
1651    The routine MatSetValuesBlockedStencil() may offer much better efficiency
1652    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1653 
1654    Level: beginner
1655 
1656 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1657           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1658 @*/
1659 PetscErrorCode MatSetValuesStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1660 {
1661   PetscInt       buf[8192],*bufm=NULL,*bufn=NULL,*jdxm,*jdxn;
1662   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1663   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1664 
1665   PetscFunctionBegin;
1666   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1667   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1668   PetscValidType(mat,1);
1669   PetscValidPointer(idxm,3);
1670   PetscValidPointer(idxn,5);
1671 
1672   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1673     jdxm = buf; jdxn = buf+m;
1674   } else {
1675     PetscCall(PetscMalloc2(m,&bufm,n,&bufn));
1676     jdxm = bufm; jdxn = bufn;
1677   }
1678   for (i=0; i<m; i++) {
1679     for (j=0; j<3-sdim; j++) dxm++;
1680     tmp = *dxm++ - starts[0];
1681     for (j=0; j<dim-1; j++) {
1682       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1683       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1684     }
1685     if (mat->stencil.noc) dxm++;
1686     jdxm[i] = tmp;
1687   }
1688   for (i=0; i<n; i++) {
1689     for (j=0; j<3-sdim; j++) dxn++;
1690     tmp = *dxn++ - starts[0];
1691     for (j=0; j<dim-1; j++) {
1692       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1693       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1694     }
1695     if (mat->stencil.noc) dxn++;
1696     jdxn[i] = tmp;
1697   }
1698   PetscCall(MatSetValuesLocal(mat,m,jdxm,n,jdxn,v,addv));
1699   PetscCall(PetscFree2(bufm,bufn));
1700   PetscFunctionReturn(0);
1701 }
1702 
1703 /*@
1704    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1705      Using structured grid indexing
1706 
1707    Not Collective
1708 
1709    Input Parameters:
1710 +  mat - the matrix
1711 .  m - number of rows being entered
1712 .  idxm - grid coordinates for matrix rows being entered
1713 .  n - number of columns being entered
1714 .  idxn - grid coordinates for matrix columns being entered
1715 .  v - a logically two-dimensional array of values
1716 -  addv - either ADD_VALUES or INSERT_VALUES, where
1717    ADD_VALUES adds values to any existing entries, and
1718    INSERT_VALUES replaces existing entries with new values
1719 
1720    Notes:
1721    By default the values, v, are row-oriented and unsorted.
1722    See MatSetOption() for other options.
1723 
1724    Calls to MatSetValuesBlockedStencil() with the INSERT_VALUES and ADD_VALUES
1725    options cannot be mixed without intervening calls to the assembly
1726    routines.
1727 
1728    The grid coordinates are across the entire grid, not just the local portion
1729 
1730    MatSetValuesBlockedStencil() uses 0-based row and column numbers in Fortran
1731    as well as in C.
1732 
1733    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1734 
1735    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1736    or call MatSetBlockSize(), MatSetLocalToGlobalMapping() and MatSetStencil() first.
1737 
1738    The columns and rows in the stencil passed in MUST be contained within the
1739    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1740    if you create a DMDA with an overlap of one grid level and on a particular process its first
1741    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1742    first i index you can use in your column and row indices in MatSetStencil() is 5.
1743 
1744    In Fortran idxm and idxn should be declared as
1745 $     MatStencil idxm(4,m),idxn(4,n)
1746    and the values inserted using
1747 $    idxm(MatStencil_i,1) = i
1748 $    idxm(MatStencil_j,1) = j
1749 $    idxm(MatStencil_k,1) = k
1750    etc
1751 
1752    Negative indices may be passed in idxm and idxn, these rows and columns are
1753    simply ignored. This allows easily inserting element stiffness matrices
1754    with homogeneous Dirchlet boundary conditions that you don't want represented
1755    in the matrix.
1756 
1757    Inspired by the structured grid interface to the HYPRE package
1758    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1759 
1760    Level: beginner
1761 
1762 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1763           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1764           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1765 @*/
1766 PetscErrorCode MatSetValuesBlockedStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1767 {
1768   PetscInt       buf[8192],*bufm=NULL,*bufn=NULL,*jdxm,*jdxn;
1769   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1770   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1771 
1772   PetscFunctionBegin;
1773   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1774   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1775   PetscValidType(mat,1);
1776   PetscValidPointer(idxm,3);
1777   PetscValidPointer(idxn,5);
1778   PetscValidScalarPointer(v,6);
1779 
1780   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1781     jdxm = buf; jdxn = buf+m;
1782   } else {
1783     PetscCall(PetscMalloc2(m,&bufm,n,&bufn));
1784     jdxm = bufm; jdxn = bufn;
1785   }
1786   for (i=0; i<m; i++) {
1787     for (j=0; j<3-sdim; j++) dxm++;
1788     tmp = *dxm++ - starts[0];
1789     for (j=0; j<sdim-1; j++) {
1790       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1791       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1792     }
1793     dxm++;
1794     jdxm[i] = tmp;
1795   }
1796   for (i=0; i<n; i++) {
1797     for (j=0; j<3-sdim; j++) dxn++;
1798     tmp = *dxn++ - starts[0];
1799     for (j=0; j<sdim-1; j++) {
1800       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1801       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1802     }
1803     dxn++;
1804     jdxn[i] = tmp;
1805   }
1806   PetscCall(MatSetValuesBlockedLocal(mat,m,jdxm,n,jdxn,v,addv));
1807   PetscCall(PetscFree2(bufm,bufn));
1808   PetscFunctionReturn(0);
1809 }
1810 
1811 /*@
1812    MatSetStencil - Sets the grid information for setting values into a matrix via
1813         MatSetValuesStencil()
1814 
1815    Not Collective
1816 
1817    Input Parameters:
1818 +  mat - the matrix
1819 .  dim - dimension of the grid 1, 2, or 3
1820 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1821 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1822 -  dof - number of degrees of freedom per node
1823 
1824    Inspired by the structured grid interface to the HYPRE package
1825    (www.llnl.gov/CASC/hyper)
1826 
1827    For matrices generated with DMCreateMatrix() this routine is automatically called and so not needed by the
1828    user.
1829 
1830    Level: beginner
1831 
1832 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1833           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1834 @*/
1835 PetscErrorCode MatSetStencil(Mat mat,PetscInt dim,const PetscInt dims[],const PetscInt starts[],PetscInt dof)
1836 {
1837   PetscFunctionBegin;
1838   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1839   PetscValidIntPointer(dims,3);
1840   PetscValidIntPointer(starts,4);
1841 
1842   mat->stencil.dim = dim + (dof > 1);
1843   for (PetscInt i=0; i<dim; i++) {
1844     mat->stencil.dims[i]   = dims[dim-i-1];      /* copy the values in backwards */
1845     mat->stencil.starts[i] = starts[dim-i-1];
1846   }
1847   mat->stencil.dims[dim]   = dof;
1848   mat->stencil.starts[dim] = 0;
1849   mat->stencil.noc         = (PetscBool)(dof == 1);
1850   PetscFunctionReturn(0);
1851 }
1852 
1853 /*@C
1854    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1855 
1856    Not Collective
1857 
1858    Input Parameters:
1859 +  mat - the matrix
1860 .  v - a logically two-dimensional array of values
1861 .  m, idxm - the number of block rows and their global block indices
1862 .  n, idxn - the number of block columns and their global block indices
1863 -  addv - either ADD_VALUES or INSERT_VALUES, where
1864    ADD_VALUES adds values to any existing entries, and
1865    INSERT_VALUES replaces existing entries with new values
1866 
1867    Notes:
1868    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call
1869    MatXXXXSetPreallocation() or MatSetUp() before using this routine.
1870 
1871    The m and n count the NUMBER of blocks in the row direction and column direction,
1872    NOT the total number of rows/columns; for example, if the block size is 2 and
1873    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1874    The values in idxm would be 1 2; that is the first index for each block divided by
1875    the block size.
1876 
1877    Note that you must call MatSetBlockSize() when constructing this matrix (before
1878    preallocating it).
1879 
1880    By default the values, v, are row-oriented, so the layout of
1881    v is the same as for MatSetValues(). See MatSetOption() for other options.
1882 
1883    Calls to MatSetValuesBlocked() with the INSERT_VALUES and ADD_VALUES
1884    options cannot be mixed without intervening calls to the assembly
1885    routines.
1886 
1887    MatSetValuesBlocked() uses 0-based row and column numbers in Fortran
1888    as well as in C.
1889 
1890    Negative indices may be passed in idxm and idxn, these rows and columns are
1891    simply ignored. This allows easily inserting element stiffness matrices
1892    with homogeneous Dirchlet boundary conditions that you don't want represented
1893    in the matrix.
1894 
1895    Each time an entry is set within a sparse matrix via MatSetValues(),
1896    internal searching must be done to determine where to place the
1897    data in the matrix storage space.  By instead inserting blocks of
1898    entries via MatSetValuesBlocked(), the overhead of matrix assembly is
1899    reduced.
1900 
1901    Example:
1902 $   Suppose m=n=2 and block size(bs) = 2 The array is
1903 $
1904 $   1  2  | 3  4
1905 $   5  6  | 7  8
1906 $   - - - | - - -
1907 $   9  10 | 11 12
1908 $   13 14 | 15 16
1909 $
1910 $   v[] should be passed in like
1911 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1912 $
1913 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1914 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1915 
1916    Level: intermediate
1917 
1918 .seealso: `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1919 @*/
1920 PetscErrorCode MatSetValuesBlocked(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1921 {
1922   PetscFunctionBeginHot;
1923   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1924   PetscValidType(mat,1);
1925   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1926   PetscValidIntPointer(idxm,3);
1927   PetscValidIntPointer(idxn,5);
1928   MatCheckPreallocated(mat,1);
1929   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1930   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1931   if (PetscDefined(USE_DEBUG)) {
1932     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1933     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1934   }
1935   if (PetscDefined(USE_DEBUG)) {
1936     PetscInt rbs,cbs,M,N,i;
1937     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
1938     PetscCall(MatGetSize(mat,&M,&N));
1939     for (i=0; i<m; i++) PetscCheck(idxm[i]*rbs < M,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT,i,idxm[i],M);
1940     for (i=0; i<n; i++) PetscCheck(idxn[i]*cbs < N,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT,i,idxn[i],N);
1941   }
1942   if (mat->assembled) {
1943     mat->was_assembled = PETSC_TRUE;
1944     mat->assembled     = PETSC_FALSE;
1945   }
1946   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1947   if (mat->ops->setvaluesblocked) {
1948     PetscCall((*mat->ops->setvaluesblocked)(mat,m,idxm,n,idxn,v,addv));
1949   } else {
1950     PetscInt buf[8192],*bufr=NULL,*bufc=NULL,*iidxm,*iidxn;
1951     PetscInt i,j,bs,cbs;
1952 
1953     PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
1954     if (m*bs+n*cbs <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1955       iidxm = buf;
1956       iidxn = buf + m*bs;
1957     } else {
1958       PetscCall(PetscMalloc2(m*bs,&bufr,n*cbs,&bufc));
1959       iidxm = bufr;
1960       iidxn = bufc;
1961     }
1962     for (i=0; i<m; i++) {
1963       for (j=0; j<bs; j++) {
1964         iidxm[i*bs+j] = bs*idxm[i] + j;
1965       }
1966     }
1967     if (m != n || bs != cbs || idxm != idxn) {
1968       for (i=0; i<n; i++) {
1969         for (j=0; j<cbs; j++) {
1970           iidxn[i*cbs+j] = cbs*idxn[i] + j;
1971         }
1972       }
1973     } else iidxn = iidxm;
1974     PetscCall(MatSetValues(mat,m*bs,iidxm,n*cbs,iidxn,v,addv));
1975     PetscCall(PetscFree2(bufr,bufc));
1976   }
1977   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1978   PetscFunctionReturn(0);
1979 }
1980 
1981 /*@C
1982    MatGetValues - Gets a block of values from a matrix.
1983 
1984    Not Collective; can only return values that are owned by the give process
1985 
1986    Input Parameters:
1987 +  mat - the matrix
1988 .  v - a logically two-dimensional array for storing the values
1989 .  m, idxm - the number of rows and their global indices
1990 -  n, idxn - the number of columns and their global indices
1991 
1992    Notes:
1993      The user must allocate space (m*n PetscScalars) for the values, v.
1994      The values, v, are then returned in a row-oriented format,
1995      analogous to that used by default in MatSetValues().
1996 
1997      MatGetValues() uses 0-based row and column numbers in
1998      Fortran as well as in C.
1999 
2000      MatGetValues() requires that the matrix has been assembled
2001      with MatAssemblyBegin()/MatAssemblyEnd().  Thus, calls to
2002      MatSetValues() and MatGetValues() CANNOT be made in succession
2003      without intermediate matrix assembly.
2004 
2005      Negative row or column indices will be ignored and those locations in v[] will be
2006      left unchanged.
2007 
2008      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2009      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2010      from MatGetOwnershipRange(mat,&rstart,&rend).
2011 
2012    Level: advanced
2013 
2014 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2015 @*/
2016 PetscErrorCode MatGetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
2017 {
2018   PetscFunctionBegin;
2019   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2020   PetscValidType(mat,1);
2021   if (!m || !n) PetscFunctionReturn(0);
2022   PetscValidIntPointer(idxm,3);
2023   PetscValidIntPointer(idxn,5);
2024   PetscValidScalarPointer(v,6);
2025   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2026   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2027   PetscCheck(mat->ops->getvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2028   MatCheckPreallocated(mat,1);
2029 
2030   PetscCall(PetscLogEventBegin(MAT_GetValues,mat,0,0,0));
2031   PetscCall((*mat->ops->getvalues)(mat,m,idxm,n,idxn,v));
2032   PetscCall(PetscLogEventEnd(MAT_GetValues,mat,0,0,0));
2033   PetscFunctionReturn(0);
2034 }
2035 
2036 /*@C
2037    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2038      defined previously by MatSetLocalToGlobalMapping()
2039 
2040    Not Collective
2041 
2042    Input Parameters:
2043 +  mat - the matrix
2044 .  nrow, irow - number of rows and their local indices
2045 -  ncol, icol - number of columns and their local indices
2046 
2047    Output Parameter:
2048 .  y -  a logically two-dimensional array of values
2049 
2050    Notes:
2051      If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine.
2052 
2053      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2054      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from MatGetOwnershipRange(mat,&rstart,&rend). One can
2055      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the ISLocalToGlobalMapping set
2056      with MatSetLocalToGlobalMapping().
2057 
2058    Developer Notes:
2059       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2060       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2061 
2062    Level: advanced
2063 
2064 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2065           `MatSetValuesLocal()`, `MatGetValues()`
2066 @*/
2067 PetscErrorCode MatGetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],PetscScalar y[])
2068 {
2069   PetscFunctionBeginHot;
2070   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2071   PetscValidType(mat,1);
2072   MatCheckPreallocated(mat,1);
2073   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2074   PetscValidIntPointer(irow,3);
2075   PetscValidIntPointer(icol,5);
2076   if (PetscDefined(USE_DEBUG)) {
2077     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2078     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2079   }
2080   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2081   PetscCall(PetscLogEventBegin(MAT_GetValues,mat,0,0,0));
2082   if (mat->ops->getvalueslocal) {
2083     PetscCall((*mat->ops->getvalueslocal)(mat,nrow,irow,ncol,icol,y));
2084   } else {
2085     PetscInt buf[8192],*bufr=NULL,*bufc=NULL,*irowm,*icolm;
2086     if ((nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2087       irowm = buf; icolm = buf+nrow;
2088     } else {
2089       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2090       irowm = bufr; icolm = bufc;
2091     }
2092     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2093     PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2094     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,irowm));
2095     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,icolm));
2096     PetscCall(MatGetValues(mat,nrow,irowm,ncol,icolm,y));
2097     PetscCall(PetscFree2(bufr,bufc));
2098   }
2099   PetscCall(PetscLogEventEnd(MAT_GetValues,mat,0,0,0));
2100   PetscFunctionReturn(0);
2101 }
2102 
2103 /*@
2104   MatSetValuesBatch - Adds (ADD_VALUES) many blocks of values into a matrix at once. The blocks must all be square and
2105   the same size. Currently, this can only be called once and creates the given matrix.
2106 
2107   Not Collective
2108 
2109   Input Parameters:
2110 + mat - the matrix
2111 . nb - the number of blocks
2112 . bs - the number of rows (and columns) in each block
2113 . rows - a concatenation of the rows for each block
2114 - v - a concatenation of logically two-dimensional arrays of values
2115 
2116   Notes:
2117   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2118 
2119   Level: advanced
2120 
2121 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2122           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
2123 @*/
2124 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2125 {
2126   PetscFunctionBegin;
2127   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2128   PetscValidType(mat,1);
2129   PetscValidIntPointer(rows,4);
2130   PetscValidScalarPointer(v,5);
2131   PetscAssert(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2132 
2133   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch,mat,0,0,0));
2134   if (mat->ops->setvaluesbatch) {
2135     PetscCall((*mat->ops->setvaluesbatch)(mat,nb,bs,rows,v));
2136   } else {
2137     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b*bs], bs, &rows[b*bs], &v[b*bs*bs], ADD_VALUES));
2138   }
2139   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch,mat,0,0,0));
2140   PetscFunctionReturn(0);
2141 }
2142 
2143 /*@
2144    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2145    the routine MatSetValuesLocal() to allow users to insert matrix entries
2146    using a local (per-processor) numbering.
2147 
2148    Not Collective
2149 
2150    Input Parameters:
2151 +  x - the matrix
2152 .  rmapping - row mapping created with ISLocalToGlobalMappingCreate() or ISLocalToGlobalMappingCreateIS()
2153 -  cmapping - column mapping
2154 
2155    Level: intermediate
2156 
2157 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2158 @*/
2159 PetscErrorCode MatSetLocalToGlobalMapping(Mat x,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
2160 {
2161   PetscFunctionBegin;
2162   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
2163   PetscValidType(x,1);
2164   if (rmapping) PetscValidHeaderSpecific(rmapping,IS_LTOGM_CLASSID,2);
2165   if (cmapping) PetscValidHeaderSpecific(cmapping,IS_LTOGM_CLASSID,3);
2166   if (x->ops->setlocaltoglobalmapping) {
2167     PetscCall((*x->ops->setlocaltoglobalmapping)(x,rmapping,cmapping));
2168   } else {
2169     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap,rmapping));
2170     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap,cmapping));
2171   }
2172   PetscFunctionReturn(0);
2173 }
2174 
2175 /*@
2176    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by MatSetLocalToGlobalMapping()
2177 
2178    Not Collective
2179 
2180    Input Parameter:
2181 .  A - the matrix
2182 
2183    Output Parameters:
2184 + rmapping - row mapping
2185 - cmapping - column mapping
2186 
2187    Level: advanced
2188 
2189 .seealso: `MatSetValuesLocal()`
2190 @*/
2191 PetscErrorCode MatGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping)
2192 {
2193   PetscFunctionBegin;
2194   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2195   PetscValidType(A,1);
2196   if (rmapping) {
2197     PetscValidPointer(rmapping,2);
2198     *rmapping = A->rmap->mapping;
2199   }
2200   if (cmapping) {
2201     PetscValidPointer(cmapping,3);
2202     *cmapping = A->cmap->mapping;
2203   }
2204   PetscFunctionReturn(0);
2205 }
2206 
2207 /*@
2208    MatSetLayouts - Sets the PetscLayout objects for rows and columns of a matrix
2209 
2210    Logically Collective on A
2211 
2212    Input Parameters:
2213 +  A - the matrix
2214 . rmap - row layout
2215 - cmap - column layout
2216 
2217    Level: advanced
2218 
2219 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2220 @*/
2221 PetscErrorCode MatSetLayouts(Mat A,PetscLayout rmap,PetscLayout cmap)
2222 {
2223   PetscFunctionBegin;
2224   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2225   PetscCall(PetscLayoutReference(rmap,&A->rmap));
2226   PetscCall(PetscLayoutReference(cmap,&A->cmap));
2227   PetscFunctionReturn(0);
2228 }
2229 
2230 /*@
2231    MatGetLayouts - Gets the PetscLayout objects for rows and columns
2232 
2233    Not Collective
2234 
2235    Input Parameter:
2236 .  A - the matrix
2237 
2238    Output Parameters:
2239 + rmap - row layout
2240 - cmap - column layout
2241 
2242    Level: advanced
2243 
2244 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2245 @*/
2246 PetscErrorCode MatGetLayouts(Mat A,PetscLayout *rmap,PetscLayout *cmap)
2247 {
2248   PetscFunctionBegin;
2249   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2250   PetscValidType(A,1);
2251   if (rmap) {
2252     PetscValidPointer(rmap,2);
2253     *rmap = A->rmap;
2254   }
2255   if (cmap) {
2256     PetscValidPointer(cmap,3);
2257     *cmap = A->cmap;
2258   }
2259   PetscFunctionReturn(0);
2260 }
2261 
2262 /*@C
2263    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2264    using a local numbering of the nodes.
2265 
2266    Not Collective
2267 
2268    Input Parameters:
2269 +  mat - the matrix
2270 .  nrow, irow - number of rows and their local indices
2271 .  ncol, icol - number of columns and their local indices
2272 .  y -  a logically two-dimensional array of values
2273 -  addv - either INSERT_VALUES or ADD_VALUES, where
2274    ADD_VALUES adds values to any existing entries, and
2275    INSERT_VALUES replaces existing entries with new values
2276 
2277    Notes:
2278    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2279       MatSetUp() before using this routine
2280 
2281    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine
2282 
2283    Calls to MatSetValuesLocal() with the INSERT_VALUES and ADD_VALUES
2284    options cannot be mixed without intervening calls to the assembly
2285    routines.
2286 
2287    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2288    MUST be called after all calls to MatSetValuesLocal() have been completed.
2289 
2290    Level: intermediate
2291 
2292    Developer Notes:
2293     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2294                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2295 
2296 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2297           `MatSetValueLocal()`, `MatGetValuesLocal()`
2298 @*/
2299 PetscErrorCode MatSetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2300 {
2301   PetscFunctionBeginHot;
2302   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2303   PetscValidType(mat,1);
2304   MatCheckPreallocated(mat,1);
2305   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2306   PetscValidIntPointer(irow,3);
2307   PetscValidIntPointer(icol,5);
2308   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2309   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2310   if (PetscDefined(USE_DEBUG)) {
2311     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2312     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2313   }
2314 
2315   if (mat->assembled) {
2316     mat->was_assembled = PETSC_TRUE;
2317     mat->assembled     = PETSC_FALSE;
2318   }
2319   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
2320   if (mat->ops->setvalueslocal) {
2321     PetscCall((*mat->ops->setvalueslocal)(mat,nrow,irow,ncol,icol,y,addv));
2322   } else {
2323     PetscInt       buf[8192],*bufr=NULL,*bufc=NULL;
2324     const PetscInt *irowm,*icolm;
2325 
2326     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2327       bufr  = buf;
2328       bufc  = buf + nrow;
2329       irowm = bufr;
2330       icolm = bufc;
2331     } else {
2332       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2333       irowm = bufr;
2334       icolm = bufc;
2335     }
2336     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,bufr));
2337     else irowm = irow;
2338     if (mat->cmap->mapping) {
2339       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2340         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,bufc));
2341       } else icolm = irowm;
2342     } else icolm = icol;
2343     PetscCall(MatSetValues(mat,nrow,irowm,ncol,icolm,y,addv));
2344     if (bufr != buf) PetscCall(PetscFree2(bufr,bufc));
2345   }
2346   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
2347   PetscFunctionReturn(0);
2348 }
2349 
2350 /*@C
2351    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2352    using a local ordering of the nodes a block at a time.
2353 
2354    Not Collective
2355 
2356    Input Parameters:
2357 +  x - the matrix
2358 .  nrow, irow - number of rows and their local indices
2359 .  ncol, icol - number of columns and their local indices
2360 .  y -  a logically two-dimensional array of values
2361 -  addv - either INSERT_VALUES or ADD_VALUES, where
2362    ADD_VALUES adds values to any existing entries, and
2363    INSERT_VALUES replaces existing entries with new values
2364 
2365    Notes:
2366    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2367       MatSetUp() before using this routine
2368 
2369    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetBlockSize() and MatSetLocalToGlobalMapping()
2370       before using this routineBefore calling MatSetValuesLocal(), the user must first set the
2371 
2372    Calls to MatSetValuesBlockedLocal() with the INSERT_VALUES and ADD_VALUES
2373    options cannot be mixed without intervening calls to the assembly
2374    routines.
2375 
2376    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2377    MUST be called after all calls to MatSetValuesBlockedLocal() have been completed.
2378 
2379    Level: intermediate
2380 
2381    Developer Notes:
2382     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2383                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2384 
2385 .seealso: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2386           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2387 @*/
2388 PetscErrorCode MatSetValuesBlockedLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2389 {
2390   PetscFunctionBeginHot;
2391   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2392   PetscValidType(mat,1);
2393   MatCheckPreallocated(mat,1);
2394   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2395   PetscValidIntPointer(irow,3);
2396   PetscValidIntPointer(icol,5);
2397   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2398   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2399   if (PetscDefined(USE_DEBUG)) {
2400     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2401     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2402   }
2403 
2404   if (mat->assembled) {
2405     mat->was_assembled = PETSC_TRUE;
2406     mat->assembled     = PETSC_FALSE;
2407   }
2408   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2409     PetscInt irbs, rbs;
2410     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2411     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&irbs));
2412     PetscCheck(rbs == irbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT,rbs,irbs);
2413   }
2414   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2415     PetscInt icbs, cbs;
2416     PetscCall(MatGetBlockSizes(mat,NULL,&cbs));
2417     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&icbs));
2418     PetscCheck(cbs == icbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT,cbs,icbs);
2419   }
2420   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
2421   if (mat->ops->setvaluesblockedlocal) {
2422     PetscCall((*mat->ops->setvaluesblockedlocal)(mat,nrow,irow,ncol,icol,y,addv));
2423   } else {
2424     PetscInt       buf[8192],*bufr=NULL,*bufc=NULL;
2425     const PetscInt *irowm,*icolm;
2426 
2427     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2428       bufr  = buf;
2429       bufc  = buf + nrow;
2430       irowm = bufr;
2431       icolm = bufc;
2432     } else {
2433       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2434       irowm = bufr;
2435       icolm = bufc;
2436     }
2437     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping,nrow,irow,bufr));
2438     else irowm = irow;
2439     if (mat->cmap->mapping) {
2440       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2441         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping,ncol,icol,bufc));
2442       } else icolm = irowm;
2443     } else icolm = icol;
2444     PetscCall(MatSetValuesBlocked(mat,nrow,irowm,ncol,icolm,y,addv));
2445     if (bufr != buf) PetscCall(PetscFree2(bufr,bufc));
2446   }
2447   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
2448   PetscFunctionReturn(0);
2449 }
2450 
2451 /*@
2452    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2453 
2454    Collective on Mat
2455 
2456    Input Parameters:
2457 +  mat - the matrix
2458 -  x   - the vector to be multiplied
2459 
2460    Output Parameters:
2461 .  y - the result
2462 
2463    Notes:
2464    The vectors x and y cannot be the same.  I.e., one cannot
2465    call MatMult(A,y,y).
2466 
2467    Level: developer
2468 
2469 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2470 @*/
2471 PetscErrorCode MatMultDiagonalBlock(Mat mat,Vec x,Vec y)
2472 {
2473   PetscFunctionBegin;
2474   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2475   PetscValidType(mat,1);
2476   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2477   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2478 
2479   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2480   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2481   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2482   MatCheckPreallocated(mat,1);
2483 
2484   PetscCheck(mat->ops->multdiagonalblock,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply defined",((PetscObject)mat)->type_name);
2485   PetscCall((*mat->ops->multdiagonalblock)(mat,x,y));
2486   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2487   PetscFunctionReturn(0);
2488 }
2489 
2490 /* --------------------------------------------------------*/
2491 /*@
2492    MatMult - Computes the matrix-vector product, y = Ax.
2493 
2494    Neighbor-wise Collective on Mat
2495 
2496    Input Parameters:
2497 +  mat - the matrix
2498 -  x   - the vector to be multiplied
2499 
2500    Output Parameters:
2501 .  y - the result
2502 
2503    Notes:
2504    The vectors x and y cannot be the same.  I.e., one cannot
2505    call MatMult(A,y,y).
2506 
2507    Level: beginner
2508 
2509 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2510 @*/
2511 PetscErrorCode MatMult(Mat mat,Vec x,Vec y)
2512 {
2513   PetscFunctionBegin;
2514   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2515   PetscValidType(mat,1);
2516   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2517   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2518   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2519   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2520   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2521   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
2522   PetscCheck(mat->rmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,y->map->N);
2523   PetscCheck(mat->cmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,x->map->n);
2524   PetscCheck(mat->rmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,y->map->n);
2525   PetscCall(VecSetErrorIfLocked(y,3));
2526   if (mat->erroriffailure) PetscCall(VecValidValues(x,2,PETSC_TRUE));
2527   MatCheckPreallocated(mat,1);
2528 
2529   PetscCall(VecLockReadPush(x));
2530   PetscCheck(mat->ops->mult,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply defined",((PetscObject)mat)->type_name);
2531   PetscCall(PetscLogEventBegin(MAT_Mult,mat,x,y,0));
2532   PetscCall((*mat->ops->mult)(mat,x,y));
2533   PetscCall(PetscLogEventEnd(MAT_Mult,mat,x,y,0));
2534   if (mat->erroriffailure) PetscCall(VecValidValues(y,3,PETSC_FALSE));
2535   PetscCall(VecLockReadPop(x));
2536   PetscFunctionReturn(0);
2537 }
2538 
2539 /*@
2540    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2541 
2542    Neighbor-wise Collective on Mat
2543 
2544    Input Parameters:
2545 +  mat - the matrix
2546 -  x   - the vector to be multiplied
2547 
2548    Output Parameters:
2549 .  y - the result
2550 
2551    Notes:
2552    The vectors x and y cannot be the same.  I.e., one cannot
2553    call MatMultTranspose(A,y,y).
2554 
2555    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2556    use MatMultHermitianTranspose()
2557 
2558    Level: beginner
2559 
2560 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2561 @*/
2562 PetscErrorCode MatMultTranspose(Mat mat,Vec x,Vec y)
2563 {
2564   PetscErrorCode (*op)(Mat,Vec,Vec) = NULL;
2565 
2566   PetscFunctionBegin;
2567   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2568   PetscValidType(mat,1);
2569   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2570   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2571 
2572   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2573   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2574   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2575   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
2576   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
2577   PetscCheck(mat->cmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,y->map->n);
2578   PetscCheck(mat->rmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,x->map->n);
2579   if (mat->erroriffailure) PetscCall(VecValidValues(x,2,PETSC_TRUE));
2580   MatCheckPreallocated(mat,1);
2581 
2582   if (!mat->ops->multtranspose) {
2583     if (mat->symmetric && mat->ops->mult) op = mat->ops->mult;
2584     PetscCheck(op,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined",((PetscObject)mat)->type_name);
2585   } else op = mat->ops->multtranspose;
2586   PetscCall(PetscLogEventBegin(MAT_MultTranspose,mat,x,y,0));
2587   PetscCall(VecLockReadPush(x));
2588   PetscCall((*op)(mat,x,y));
2589   PetscCall(VecLockReadPop(x));
2590   PetscCall(PetscLogEventEnd(MAT_MultTranspose,mat,x,y,0));
2591   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2592   if (mat->erroriffailure) PetscCall(VecValidValues(y,3,PETSC_FALSE));
2593   PetscFunctionReturn(0);
2594 }
2595 
2596 /*@
2597    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2598 
2599    Neighbor-wise Collective on Mat
2600 
2601    Input Parameters:
2602 +  mat - the matrix
2603 -  x   - the vector to be multilplied
2604 
2605    Output Parameters:
2606 .  y - the result
2607 
2608    Notes:
2609    The vectors x and y cannot be the same.  I.e., one cannot
2610    call MatMultHermitianTranspose(A,y,y).
2611 
2612    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2613 
2614    For real numbers MatMultTranspose() and MatMultHermitianTranspose() are identical.
2615 
2616    Level: beginner
2617 
2618 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2619 @*/
2620 PetscErrorCode MatMultHermitianTranspose(Mat mat,Vec x,Vec y)
2621 {
2622   PetscFunctionBegin;
2623   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2624   PetscValidType(mat,1);
2625   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2626   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2627 
2628   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2629   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2630   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2631   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
2632   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
2633   PetscCheck(mat->cmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,y->map->n);
2634   PetscCheck(mat->rmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,x->map->n);
2635   MatCheckPreallocated(mat,1);
2636 
2637   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose,mat,x,y,0));
2638 #if defined(PETSC_USE_COMPLEX)
2639   if (mat->ops->multhermitiantranspose || (mat->hermitian && mat->ops->mult)) {
2640     PetscCall(VecLockReadPush(x));
2641     if (mat->ops->multhermitiantranspose) {
2642       PetscCall((*mat->ops->multhermitiantranspose)(mat,x,y));
2643     } else {
2644       PetscCall((*mat->ops->mult)(mat,x,y));
2645     }
2646     PetscCall(VecLockReadPop(x));
2647   } else {
2648     Vec w;
2649     PetscCall(VecDuplicate(x,&w));
2650     PetscCall(VecCopy(x,w));
2651     PetscCall(VecConjugate(w));
2652     PetscCall(MatMultTranspose(mat,w,y));
2653     PetscCall(VecDestroy(&w));
2654     PetscCall(VecConjugate(y));
2655   }
2656   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2657 #else
2658   PetscCall(MatMultTranspose(mat,x,y));
2659 #endif
2660   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose,mat,x,y,0));
2661   PetscFunctionReturn(0);
2662 }
2663 
2664 /*@
2665     MatMultAdd -  Computes v3 = v2 + A * v1.
2666 
2667     Neighbor-wise Collective on Mat
2668 
2669     Input Parameters:
2670 +   mat - the matrix
2671 -   v1, v2 - the vectors
2672 
2673     Output Parameters:
2674 .   v3 - the result
2675 
2676     Notes:
2677     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2678     call MatMultAdd(A,v1,v2,v1).
2679 
2680     Level: beginner
2681 
2682 .seealso: `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2683 @*/
2684 PetscErrorCode MatMultAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2685 {
2686   PetscFunctionBegin;
2687   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2688   PetscValidType(mat,1);
2689   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2690   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2691   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2692 
2693   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2694   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2695   PetscCheck(mat->cmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v1->map->N);
2696   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2697      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2698   PetscCheck(mat->rmap->n == v3->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,v3->map->n);
2699   PetscCheck(mat->rmap->n == v2->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,v2->map->n);
2700   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2701   MatCheckPreallocated(mat,1);
2702 
2703   PetscCheck(mat->ops->multadd,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No MatMultAdd() for matrix type %s",((PetscObject)mat)->type_name);
2704   PetscCall(PetscLogEventBegin(MAT_MultAdd,mat,v1,v2,v3));
2705   PetscCall(VecLockReadPush(v1));
2706   PetscCall((*mat->ops->multadd)(mat,v1,v2,v3));
2707   PetscCall(VecLockReadPop(v1));
2708   PetscCall(PetscLogEventEnd(MAT_MultAdd,mat,v1,v2,v3));
2709   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2710   PetscFunctionReturn(0);
2711 }
2712 
2713 /*@
2714    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2715 
2716    Neighbor-wise Collective on Mat
2717 
2718    Input Parameters:
2719 +  mat - the matrix
2720 -  v1, v2 - the vectors
2721 
2722    Output Parameters:
2723 .  v3 - the result
2724 
2725    Notes:
2726    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2727    call MatMultTransposeAdd(A,v1,v2,v1).
2728 
2729    Level: beginner
2730 
2731 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2732 @*/
2733 PetscErrorCode MatMultTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2734 {
2735   PetscErrorCode (*op)(Mat,Vec,Vec,Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2736 
2737   PetscFunctionBegin;
2738   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2739   PetscValidType(mat,1);
2740   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2741   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2742   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2743 
2744   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2745   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2746   PetscCheck(mat->rmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v1->map->N);
2747   PetscCheck(mat->cmap->N == v2->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v2->map->N);
2748   PetscCheck(mat->cmap->N == v3->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v3->map->N);
2749   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2750   PetscCheck(op,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2751   MatCheckPreallocated(mat,1);
2752 
2753   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd,mat,v1,v2,v3));
2754   PetscCall(VecLockReadPush(v1));
2755   PetscCall((*op)(mat,v1,v2,v3));
2756   PetscCall(VecLockReadPop(v1));
2757   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd,mat,v1,v2,v3));
2758   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2759   PetscFunctionReturn(0);
2760 }
2761 
2762 /*@
2763    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2764 
2765    Neighbor-wise Collective on Mat
2766 
2767    Input Parameters:
2768 +  mat - the matrix
2769 -  v1, v2 - the vectors
2770 
2771    Output Parameters:
2772 .  v3 - the result
2773 
2774    Notes:
2775    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2776    call MatMultHermitianTransposeAdd(A,v1,v2,v1).
2777 
2778    Level: beginner
2779 
2780 .seealso: `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2781 @*/
2782 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2783 {
2784   PetscFunctionBegin;
2785   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2786   PetscValidType(mat,1);
2787   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2788   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2789   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2790 
2791   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2792   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2793   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2794   PetscCheck(mat->rmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v1->map->N);
2795   PetscCheck(mat->cmap->N == v2->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v2->map->N);
2796   PetscCheck(mat->cmap->N == v3->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v3->map->N);
2797   MatCheckPreallocated(mat,1);
2798 
2799   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3));
2800   PetscCall(VecLockReadPush(v1));
2801   if (mat->ops->multhermitiantransposeadd) {
2802     PetscCall((*mat->ops->multhermitiantransposeadd)(mat,v1,v2,v3));
2803   } else {
2804     Vec w,z;
2805     PetscCall(VecDuplicate(v1,&w));
2806     PetscCall(VecCopy(v1,w));
2807     PetscCall(VecConjugate(w));
2808     PetscCall(VecDuplicate(v3,&z));
2809     PetscCall(MatMultTranspose(mat,w,z));
2810     PetscCall(VecDestroy(&w));
2811     PetscCall(VecConjugate(z));
2812     if (v2 != v3) {
2813       PetscCall(VecWAXPY(v3,1.0,v2,z));
2814     } else {
2815       PetscCall(VecAXPY(v3,1.0,z));
2816     }
2817     PetscCall(VecDestroy(&z));
2818   }
2819   PetscCall(VecLockReadPop(v1));
2820   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3));
2821   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2822   PetscFunctionReturn(0);
2823 }
2824 
2825 /*@C
2826    MatGetFactorType - gets the type of factorization it is
2827 
2828    Not Collective
2829 
2830    Input Parameters:
2831 .  mat - the matrix
2832 
2833    Output Parameters:
2834 .  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2835 
2836    Level: intermediate
2837 
2838 .seealso: `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`
2839 @*/
2840 PetscErrorCode MatGetFactorType(Mat mat,MatFactorType *t)
2841 {
2842   PetscFunctionBegin;
2843   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2844   PetscValidType(mat,1);
2845   PetscValidPointer(t,2);
2846   *t = mat->factortype;
2847   PetscFunctionReturn(0);
2848 }
2849 
2850 /*@C
2851    MatSetFactorType - sets the type of factorization it is
2852 
2853    Logically Collective on Mat
2854 
2855    Input Parameters:
2856 +  mat - the matrix
2857 -  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2858 
2859    Level: intermediate
2860 
2861 .seealso: `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`
2862 @*/
2863 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2864 {
2865   PetscFunctionBegin;
2866   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2867   PetscValidType(mat,1);
2868   mat->factortype = t;
2869   PetscFunctionReturn(0);
2870 }
2871 
2872 /* ------------------------------------------------------------*/
2873 /*@C
2874    MatGetInfo - Returns information about matrix storage (number of
2875    nonzeros, memory, etc.).
2876 
2877    Collective on Mat if MAT_GLOBAL_MAX or MAT_GLOBAL_SUM is used as the flag
2878 
2879    Input Parameter:
2880 .  mat - the matrix
2881 
2882    Output Parameters:
2883 +  flag - flag indicating the type of parameters to be returned
2884    (MAT_LOCAL - local matrix, MAT_GLOBAL_MAX - maximum over all processors,
2885    MAT_GLOBAL_SUM - sum over all processors)
2886 -  info - matrix information context
2887 
2888    Notes:
2889    The MatInfo context contains a variety of matrix data, including
2890    number of nonzeros allocated and used, number of mallocs during
2891    matrix assembly, etc.  Additional information for factored matrices
2892    is provided (such as the fill ratio, number of mallocs during
2893    factorization, etc.).  Much of this info is printed to PETSC_STDOUT
2894    when using the runtime options
2895 $       -info -mat_view ::ascii_info
2896 
2897    Example for C/C++ Users:
2898    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2899    data within the MatInfo context.  For example,
2900 .vb
2901       MatInfo info;
2902       Mat     A;
2903       double  mal, nz_a, nz_u;
2904 
2905       MatGetInfo(A,MAT_LOCAL,&info);
2906       mal  = info.mallocs;
2907       nz_a = info.nz_allocated;
2908 .ve
2909 
2910    Example for Fortran Users:
2911    Fortran users should declare info as a double precision
2912    array of dimension MAT_INFO_SIZE, and then extract the parameters
2913    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2914    a complete list of parameter names.
2915 .vb
2916       double  precision info(MAT_INFO_SIZE)
2917       double  precision mal, nz_a
2918       Mat     A
2919       integer ierr
2920 
2921       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2922       mal = info(MAT_INFO_MALLOCS)
2923       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2924 .ve
2925 
2926     Level: intermediate
2927 
2928     Developer Note: fortran interface is not autogenerated as the f90
2929     interface definition cannot be generated correctly [due to MatInfo]
2930 
2931 .seealso: `MatStashGetInfo()`
2932 
2933 @*/
2934 PetscErrorCode MatGetInfo(Mat mat,MatInfoType flag,MatInfo *info)
2935 {
2936   PetscFunctionBegin;
2937   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2938   PetscValidType(mat,1);
2939   PetscValidPointer(info,3);
2940   PetscCheck(mat->ops->getinfo,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2941   MatCheckPreallocated(mat,1);
2942   PetscCall((*mat->ops->getinfo)(mat,flag,info));
2943   PetscFunctionReturn(0);
2944 }
2945 
2946 /*
2947    This is used by external packages where it is not easy to get the info from the actual
2948    matrix factorization.
2949 */
2950 PetscErrorCode MatGetInfo_External(Mat A,MatInfoType flag,MatInfo *info)
2951 {
2952   PetscFunctionBegin;
2953   PetscCall(PetscMemzero(info,sizeof(MatInfo)));
2954   PetscFunctionReturn(0);
2955 }
2956 
2957 /* ----------------------------------------------------------*/
2958 
2959 /*@C
2960    MatLUFactor - Performs in-place LU factorization of matrix.
2961 
2962    Collective on Mat
2963 
2964    Input Parameters:
2965 +  mat - the matrix
2966 .  row - row permutation
2967 .  col - column permutation
2968 -  info - options for factorization, includes
2969 $          fill - expected fill as ratio of original fill.
2970 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2971 $                   Run with the option -info to determine an optimal value to use
2972 
2973    Notes:
2974    Most users should employ the simplified KSP interface for linear solvers
2975    instead of working directly with matrix algebra routines such as this.
2976    See, e.g., KSPCreate().
2977 
2978    This changes the state of the matrix to a factored matrix; it cannot be used
2979    for example with MatSetValues() unless one first calls MatSetUnfactored().
2980 
2981    Level: developer
2982 
2983 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2984           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2985 
2986     Developer Note: fortran interface is not autogenerated as the f90
2987     interface definition cannot be generated correctly [due to MatFactorInfo]
2988 
2989 @*/
2990 PetscErrorCode MatLUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
2991 {
2992   MatFactorInfo  tinfo;
2993 
2994   PetscFunctionBegin;
2995   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2996   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
2997   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
2998   if (info) PetscValidPointer(info,4);
2999   PetscValidType(mat,1);
3000   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3001   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3002   PetscCheck(mat->ops->lufactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3003   MatCheckPreallocated(mat,1);
3004   if (!info) {
3005     PetscCall(MatFactorInfoInitialize(&tinfo));
3006     info = &tinfo;
3007   }
3008 
3009   PetscCall(PetscLogEventBegin(MAT_LUFactor,mat,row,col,0));
3010   PetscCall((*mat->ops->lufactor)(mat,row,col,info));
3011   PetscCall(PetscLogEventEnd(MAT_LUFactor,mat,row,col,0));
3012   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3013   PetscFunctionReturn(0);
3014 }
3015 
3016 /*@C
3017    MatILUFactor - Performs in-place ILU factorization of matrix.
3018 
3019    Collective on Mat
3020 
3021    Input Parameters:
3022 +  mat - the matrix
3023 .  row - row permutation
3024 .  col - column permutation
3025 -  info - structure containing
3026 $      levels - number of levels of fill.
3027 $      expected fill - as ratio of original fill.
3028 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3029                 missing diagonal entries)
3030 
3031    Notes:
3032    Probably really in-place only when level of fill is zero, otherwise allocates
3033    new space to store factored matrix and deletes previous memory.
3034 
3035    Most users should employ the simplified KSP interface for linear solvers
3036    instead of working directly with matrix algebra routines such as this.
3037    See, e.g., KSPCreate().
3038 
3039    Level: developer
3040 
3041 .seealso: `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3042 
3043     Developer Note: fortran interface is not autogenerated as the f90
3044     interface definition cannot be generated correctly [due to MatFactorInfo]
3045 
3046 @*/
3047 PetscErrorCode MatILUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
3048 {
3049   PetscFunctionBegin;
3050   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3051   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
3052   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3053   PetscValidPointer(info,4);
3054   PetscValidType(mat,1);
3055   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
3056   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3057   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3058   PetscCheck(mat->ops->ilufactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3059   MatCheckPreallocated(mat,1);
3060 
3061   PetscCall(PetscLogEventBegin(MAT_ILUFactor,mat,row,col,0));
3062   PetscCall((*mat->ops->ilufactor)(mat,row,col,info));
3063   PetscCall(PetscLogEventEnd(MAT_ILUFactor,mat,row,col,0));
3064   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3065   PetscFunctionReturn(0);
3066 }
3067 
3068 /*@C
3069    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3070    Call this routine before calling MatLUFactorNumeric().
3071 
3072    Collective on Mat
3073 
3074    Input Parameters:
3075 +  fact - the factor matrix obtained with MatGetFactor()
3076 .  mat - the matrix
3077 .  row, col - row and column permutations
3078 -  info - options for factorization, includes
3079 $          fill - expected fill as ratio of original fill.
3080 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3081 $                   Run with the option -info to determine an optimal value to use
3082 
3083    Notes:
3084     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
3085 
3086    Most users should employ the simplified KSP interface for linear solvers
3087    instead of working directly with matrix algebra routines such as this.
3088    See, e.g., KSPCreate().
3089 
3090    Level: developer
3091 
3092 .seealso: `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3093 
3094     Developer Note: fortran interface is not autogenerated as the f90
3095     interface definition cannot be generated correctly [due to MatFactorInfo]
3096 
3097 @*/
3098 PetscErrorCode MatLUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
3099 {
3100   MatFactorInfo  tinfo;
3101 
3102   PetscFunctionBegin;
3103   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3104   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
3105   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
3106   if (info) PetscValidPointer(info,5);
3107   PetscValidType(mat,2);
3108   PetscValidPointer(fact,1);
3109   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3110   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3111   if (!(fact)->ops->lufactorsymbolic) {
3112     MatSolverType stype;
3113     PetscCall(MatFactorGetSolverType(fact,&stype));
3114     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic LU using solver package %s",((PetscObject)mat)->type_name,stype);
3115   }
3116   MatCheckPreallocated(mat,2);
3117   if (!info) {
3118     PetscCall(MatFactorInfoInitialize(&tinfo));
3119     info = &tinfo;
3120   }
3121 
3122   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic,mat,row,col,0));
3123   PetscCall((fact->ops->lufactorsymbolic)(fact,mat,row,col,info));
3124   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic,mat,row,col,0));
3125   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3126   PetscFunctionReturn(0);
3127 }
3128 
3129 /*@C
3130    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3131    Call this routine after first calling MatLUFactorSymbolic().
3132 
3133    Collective on Mat
3134 
3135    Input Parameters:
3136 +  fact - the factor matrix obtained with MatGetFactor()
3137 .  mat - the matrix
3138 -  info - options for factorization
3139 
3140    Notes:
3141    See MatLUFactor() for in-place factorization.  See
3142    MatCholeskyFactorNumeric() for the symmetric, positive definite case.
3143 
3144    Most users should employ the simplified KSP interface for linear solvers
3145    instead of working directly with matrix algebra routines such as this.
3146    See, e.g., KSPCreate().
3147 
3148    Level: developer
3149 
3150 .seealso: `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3151 
3152     Developer Note: fortran interface is not autogenerated as the f90
3153     interface definition cannot be generated correctly [due to MatFactorInfo]
3154 
3155 @*/
3156 PetscErrorCode MatLUFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3157 {
3158   MatFactorInfo  tinfo;
3159 
3160   PetscFunctionBegin;
3161   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3162   PetscValidType(mat,2);
3163   PetscValidPointer(fact,1);
3164   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3165   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3166   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3167 
3168   PetscCheck((fact)->ops->lufactornumeric,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric LU",((PetscObject)mat)->type_name);
3169   MatCheckPreallocated(mat,2);
3170   if (!info) {
3171     PetscCall(MatFactorInfoInitialize(&tinfo));
3172     info = &tinfo;
3173   }
3174 
3175   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric,mat,fact,0,0));
3176   else PetscCall(PetscLogEventBegin(MAT_LUFactor,mat,fact,0,0));
3177   PetscCall((fact->ops->lufactornumeric)(fact,mat,info));
3178   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric,mat,fact,0,0));
3179   else PetscCall(PetscLogEventEnd(MAT_LUFactor,mat,fact,0,0));
3180   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3181   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3182   PetscFunctionReturn(0);
3183 }
3184 
3185 /*@C
3186    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3187    symmetric matrix.
3188 
3189    Collective on Mat
3190 
3191    Input Parameters:
3192 +  mat - the matrix
3193 .  perm - row and column permutations
3194 -  f - expected fill as ratio of original fill
3195 
3196    Notes:
3197    See MatLUFactor() for the nonsymmetric case.  See also
3198    MatCholeskyFactorSymbolic(), and MatCholeskyFactorNumeric().
3199 
3200    Most users should employ the simplified KSP interface for linear solvers
3201    instead of working directly with matrix algebra routines such as this.
3202    See, e.g., KSPCreate().
3203 
3204    Level: developer
3205 
3206 .seealso: `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3207           `MatGetOrdering()`
3208 
3209     Developer Note: fortran interface is not autogenerated as the f90
3210     interface definition cannot be generated correctly [due to MatFactorInfo]
3211 
3212 @*/
3213 PetscErrorCode MatCholeskyFactor(Mat mat,IS perm,const MatFactorInfo *info)
3214 {
3215   MatFactorInfo  tinfo;
3216 
3217   PetscFunctionBegin;
3218   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3219   PetscValidType(mat,1);
3220   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,2);
3221   if (info) PetscValidPointer(info,3);
3222   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3223   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3224   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3225   PetscCheck(mat->ops->choleskyfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"In-place factorization for Mat type %s is not supported, try out-of-place factorization. See MatCholeskyFactorSymbolic/Numeric",((PetscObject)mat)->type_name);
3226   MatCheckPreallocated(mat,1);
3227   if (!info) {
3228     PetscCall(MatFactorInfoInitialize(&tinfo));
3229     info = &tinfo;
3230   }
3231 
3232   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor,mat,perm,0,0));
3233   PetscCall((*mat->ops->choleskyfactor)(mat,perm,info));
3234   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor,mat,perm,0,0));
3235   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3236   PetscFunctionReturn(0);
3237 }
3238 
3239 /*@C
3240    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3241    of a symmetric matrix.
3242 
3243    Collective on Mat
3244 
3245    Input Parameters:
3246 +  fact - the factor matrix obtained with MatGetFactor()
3247 .  mat - the matrix
3248 .  perm - row and column permutations
3249 -  info - options for factorization, includes
3250 $          fill - expected fill as ratio of original fill.
3251 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3252 $                   Run with the option -info to determine an optimal value to use
3253 
3254    Notes:
3255    See MatLUFactorSymbolic() for the nonsymmetric case.  See also
3256    MatCholeskyFactor() and MatCholeskyFactorNumeric().
3257 
3258    Most users should employ the simplified KSP interface for linear solvers
3259    instead of working directly with matrix algebra routines such as this.
3260    See, e.g., KSPCreate().
3261 
3262    Level: developer
3263 
3264 .seealso: `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3265           `MatGetOrdering()`
3266 
3267     Developer Note: fortran interface is not autogenerated as the f90
3268     interface definition cannot be generated correctly [due to MatFactorInfo]
3269 
3270 @*/
3271 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
3272 {
3273   MatFactorInfo  tinfo;
3274 
3275   PetscFunctionBegin;
3276   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3277   PetscValidType(mat,2);
3278   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
3279   if (info) PetscValidPointer(info,4);
3280   PetscValidPointer(fact,1);
3281   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3282   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3283   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3284   if (!(fact)->ops->choleskyfactorsymbolic) {
3285     MatSolverType stype;
3286     PetscCall(MatFactorGetSolverType(fact,&stype));
3287     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s symbolic factor Cholesky using solver package %s",((PetscObject)mat)->type_name,stype);
3288   }
3289   MatCheckPreallocated(mat,2);
3290   if (!info) {
3291     PetscCall(MatFactorInfoInitialize(&tinfo));
3292     info = &tinfo;
3293   }
3294 
3295   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic,mat,perm,0,0));
3296   PetscCall((fact->ops->choleskyfactorsymbolic)(fact,mat,perm,info));
3297   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic,mat,perm,0,0));
3298   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3299   PetscFunctionReturn(0);
3300 }
3301 
3302 /*@C
3303    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3304    of a symmetric matrix. Call this routine after first calling
3305    MatCholeskyFactorSymbolic().
3306 
3307    Collective on Mat
3308 
3309    Input Parameters:
3310 +  fact - the factor matrix obtained with MatGetFactor()
3311 .  mat - the initial matrix
3312 .  info - options for factorization
3313 -  fact - the symbolic factor of mat
3314 
3315    Notes:
3316    Most users should employ the simplified KSP interface for linear solvers
3317    instead of working directly with matrix algebra routines such as this.
3318    See, e.g., KSPCreate().
3319 
3320    Level: developer
3321 
3322 .seealso: `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3323 
3324     Developer Note: fortran interface is not autogenerated as the f90
3325     interface definition cannot be generated correctly [due to MatFactorInfo]
3326 
3327 @*/
3328 PetscErrorCode MatCholeskyFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3329 {
3330   MatFactorInfo  tinfo;
3331 
3332   PetscFunctionBegin;
3333   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3334   PetscValidType(mat,2);
3335   PetscValidPointer(fact,1);
3336   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3337   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3338   PetscCheck((fact)->ops->choleskyfactornumeric,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric factor Cholesky",((PetscObject)mat)->type_name);
3339   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3340   MatCheckPreallocated(mat,2);
3341   if (!info) {
3342     PetscCall(MatFactorInfoInitialize(&tinfo));
3343     info = &tinfo;
3344   }
3345 
3346   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric,mat,fact,0,0));
3347   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor,mat,fact,0,0));
3348   PetscCall((fact->ops->choleskyfactornumeric)(fact,mat,info));
3349   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric,mat,fact,0,0));
3350   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor,mat,fact,0,0));
3351   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3352   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3353   PetscFunctionReturn(0);
3354 }
3355 
3356 /*@
3357    MatQRFactor - Performs in-place QR factorization of matrix.
3358 
3359    Collective on Mat
3360 
3361    Input Parameters:
3362 +  mat - the matrix
3363 .  col - column permutation
3364 -  info - options for factorization, includes
3365 $          fill - expected fill as ratio of original fill.
3366 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3367 $                   Run with the option -info to determine an optimal value to use
3368 
3369    Notes:
3370    Most users should employ the simplified KSP interface for linear solvers
3371    instead of working directly with matrix algebra routines such as this.
3372    See, e.g., KSPCreate().
3373 
3374    This changes the state of the matrix to a factored matrix; it cannot be used
3375    for example with MatSetValues() unless one first calls MatSetUnfactored().
3376 
3377    Level: developer
3378 
3379 .seealso: `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3380           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3381 
3382     Developer Note: fortran interface is not autogenerated as the f90
3383     interface definition cannot be generated correctly [due to MatFactorInfo]
3384 
3385 @*/
3386 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3387 {
3388   PetscFunctionBegin;
3389   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3390   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,2);
3391   if (info) PetscValidPointer(info,3);
3392   PetscValidType(mat,1);
3393   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3394   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3395   MatCheckPreallocated(mat,1);
3396   PetscCall(PetscLogEventBegin(MAT_QRFactor,mat,col,0,0));
3397   PetscUseMethod(mat,"MatQRFactor_C", (Mat,IS,const MatFactorInfo*), (mat, col, info));
3398   PetscCall(PetscLogEventEnd(MAT_QRFactor,mat,col,0,0));
3399   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3400   PetscFunctionReturn(0);
3401 }
3402 
3403 /*@
3404    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3405    Call this routine before calling MatQRFactorNumeric().
3406 
3407    Collective on Mat
3408 
3409    Input Parameters:
3410 +  fact - the factor matrix obtained with MatGetFactor()
3411 .  mat - the matrix
3412 .  col - column permutation
3413 -  info - options for factorization, includes
3414 $          fill - expected fill as ratio of original fill.
3415 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3416 $                   Run with the option -info to determine an optimal value to use
3417 
3418    Most users should employ the simplified KSP interface for linear solvers
3419    instead of working directly with matrix algebra routines such as this.
3420    See, e.g., KSPCreate().
3421 
3422    Level: developer
3423 
3424 .seealso: `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3425 
3426     Developer Note: fortran interface is not autogenerated as the f90
3427     interface definition cannot be generated correctly [due to MatFactorInfo]
3428 
3429 @*/
3430 PetscErrorCode MatQRFactorSymbolic(Mat fact,Mat mat,IS col,const MatFactorInfo *info)
3431 {
3432   MatFactorInfo  tinfo;
3433 
3434   PetscFunctionBegin;
3435   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3436   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3437   if (info) PetscValidPointer(info,4);
3438   PetscValidType(mat,2);
3439   PetscValidPointer(fact,1);
3440   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3441   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3442   MatCheckPreallocated(mat,2);
3443   if (!info) {
3444     PetscCall(MatFactorInfoInitialize(&tinfo));
3445     info = &tinfo;
3446   }
3447 
3448   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic,fact,mat,col,0));
3449   PetscUseMethod(fact,"MatQRFactorSymbolic_C", (Mat,Mat,IS,const MatFactorInfo*), (fact, mat, col, info));
3450   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic,fact,mat,col,0));
3451   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3452   PetscFunctionReturn(0);
3453 }
3454 
3455 /*@
3456    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3457    Call this routine after first calling MatQRFactorSymbolic().
3458 
3459    Collective on Mat
3460 
3461    Input Parameters:
3462 +  fact - the factor matrix obtained with MatGetFactor()
3463 .  mat - the matrix
3464 -  info - options for factorization
3465 
3466    Notes:
3467    See MatQRFactor() for in-place factorization.
3468 
3469    Most users should employ the simplified KSP interface for linear solvers
3470    instead of working directly with matrix algebra routines such as this.
3471    See, e.g., KSPCreate().
3472 
3473    Level: developer
3474 
3475 .seealso: `MatQRFactorSymbolic()`, `MatLUFactor()`
3476 
3477     Developer Note: fortran interface is not autogenerated as the f90
3478     interface definition cannot be generated correctly [due to MatFactorInfo]
3479 
3480 @*/
3481 PetscErrorCode MatQRFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3482 {
3483   MatFactorInfo  tinfo;
3484 
3485   PetscFunctionBegin;
3486   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3487   PetscValidType(mat,2);
3488   PetscValidPointer(fact,1);
3489   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3490   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3491   PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3492 
3493   MatCheckPreallocated(mat,2);
3494   if (!info) {
3495     PetscCall(MatFactorInfoInitialize(&tinfo));
3496     info = &tinfo;
3497   }
3498 
3499   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric,mat,fact,0,0));
3500   else  PetscCall(PetscLogEventBegin(MAT_QRFactor,mat,fact,0,0));
3501   PetscUseMethod(fact,"MatQRFactorNumeric_C", (Mat,Mat,const MatFactorInfo*), (fact, mat, info));
3502   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric,mat,fact,0,0));
3503   else PetscCall(PetscLogEventEnd(MAT_QRFactor,mat,fact,0,0));
3504   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3505   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3506   PetscFunctionReturn(0);
3507 }
3508 
3509 /* ----------------------------------------------------------------*/
3510 /*@
3511    MatSolve - Solves A x = b, given a factored matrix.
3512 
3513    Neighbor-wise Collective on Mat
3514 
3515    Input Parameters:
3516 +  mat - the factored matrix
3517 -  b - the right-hand-side vector
3518 
3519    Output Parameter:
3520 .  x - the result vector
3521 
3522    Notes:
3523    The vectors b and x cannot be the same.  I.e., one cannot
3524    call MatSolve(A,x,x).
3525 
3526    Notes:
3527    Most users should employ the simplified KSP interface for linear solvers
3528    instead of working directly with matrix algebra routines such as this.
3529    See, e.g., KSPCreate().
3530 
3531    Level: developer
3532 
3533 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3534 @*/
3535 PetscErrorCode MatSolve(Mat mat,Vec b,Vec x)
3536 {
3537   PetscFunctionBegin;
3538   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3539   PetscValidType(mat,1);
3540   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3541   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3542   PetscCheckSameComm(mat,1,b,2);
3543   PetscCheckSameComm(mat,1,x,3);
3544   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3545   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3546   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3547   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3548   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3549   MatCheckPreallocated(mat,1);
3550 
3551   PetscCall(PetscLogEventBegin(MAT_Solve,mat,b,x,0));
3552   if (mat->factorerrortype) {
3553     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
3554     PetscCall(VecSetInf(x));
3555   } else {
3556     PetscCheck(mat->ops->solve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3557     PetscCall((*mat->ops->solve)(mat,b,x));
3558   }
3559   PetscCall(PetscLogEventEnd(MAT_Solve,mat,b,x,0));
3560   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3561   PetscFunctionReturn(0);
3562 }
3563 
3564 static PetscErrorCode MatMatSolve_Basic(Mat A,Mat B,Mat X,PetscBool trans)
3565 {
3566   Vec            b,x;
3567   PetscInt       N,i;
3568   PetscErrorCode (*f)(Mat,Vec,Vec);
3569   PetscBool      Abound,Bneedconv = PETSC_FALSE,Xneedconv = PETSC_FALSE;
3570 
3571   PetscFunctionBegin;
3572   if (A->factorerrortype) {
3573     PetscCall(PetscInfo(A,"MatFactorError %d\n",A->factorerrortype));
3574     PetscCall(MatSetInf(X));
3575     PetscFunctionReturn(0);
3576   }
3577   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3578   PetscCheck(f,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
3579   PetscCall(MatBoundToCPU(A,&Abound));
3580   if (!Abound) {
3581     PetscCall(PetscObjectTypeCompareAny((PetscObject)B,&Bneedconv,MATSEQDENSE,MATMPIDENSE,""));
3582     PetscCall(PetscObjectTypeCompareAny((PetscObject)X,&Xneedconv,MATSEQDENSE,MATMPIDENSE,""));
3583   }
3584   if (Bneedconv) {
3585     PetscCall(MatConvert(B,MATDENSECUDA,MAT_INPLACE_MATRIX,&B));
3586   }
3587   if (Xneedconv) {
3588     PetscCall(MatConvert(X,MATDENSECUDA,MAT_INPLACE_MATRIX,&X));
3589   }
3590   PetscCall(MatGetSize(B,NULL,&N));
3591   for (i=0; i<N; i++) {
3592     PetscCall(MatDenseGetColumnVecRead(B,i,&b));
3593     PetscCall(MatDenseGetColumnVecWrite(X,i,&x));
3594     PetscCall((*f)(A,b,x));
3595     PetscCall(MatDenseRestoreColumnVecWrite(X,i,&x));
3596     PetscCall(MatDenseRestoreColumnVecRead(B,i,&b));
3597   }
3598   if (Bneedconv) {
3599     PetscCall(MatConvert(B,MATDENSE,MAT_INPLACE_MATRIX,&B));
3600   }
3601   if (Xneedconv) {
3602     PetscCall(MatConvert(X,MATDENSE,MAT_INPLACE_MATRIX,&X));
3603   }
3604   PetscFunctionReturn(0);
3605 }
3606 
3607 /*@
3608    MatMatSolve - Solves A X = B, given a factored matrix.
3609 
3610    Neighbor-wise Collective on Mat
3611 
3612    Input Parameters:
3613 +  A - the factored matrix
3614 -  B - the right-hand-side matrix MATDENSE (or sparse -- when using MUMPS)
3615 
3616    Output Parameter:
3617 .  X - the result matrix (dense matrix)
3618 
3619    Notes:
3620    If B is a MATDENSE matrix then one can call MatMatSolve(A,B,B) except with MKL_CPARDISO;
3621    otherwise, B and X cannot be the same.
3622 
3623    Notes:
3624    Most users should usually employ the simplified KSP interface for linear solvers
3625    instead of working directly with matrix algebra routines such as this.
3626    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3627    at a time.
3628 
3629    Level: developer
3630 
3631 .seealso: `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3632 @*/
3633 PetscErrorCode MatMatSolve(Mat A,Mat B,Mat X)
3634 {
3635   PetscFunctionBegin;
3636   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3637   PetscValidType(A,1);
3638   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3639   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3640   PetscCheckSameComm(A,1,B,2);
3641   PetscCheckSameComm(A,1,X,3);
3642   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3643   PetscCheck(A->rmap->N == B->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N);
3644   PetscCheck(X->cmap->N == B->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as rhs matrix");
3645   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3646   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3647   MatCheckPreallocated(A,1);
3648 
3649   PetscCall(PetscLogEventBegin(MAT_MatSolve,A,B,X,0));
3650   if (!A->ops->matsolve) {
3651     PetscCall(PetscInfo(A,"Mat type %s using basic MatMatSolve\n",((PetscObject)A)->type_name));
3652     PetscCall(MatMatSolve_Basic(A,B,X,PETSC_FALSE));
3653   } else {
3654     PetscCall((*A->ops->matsolve)(A,B,X));
3655   }
3656   PetscCall(PetscLogEventEnd(MAT_MatSolve,A,B,X,0));
3657   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3658   PetscFunctionReturn(0);
3659 }
3660 
3661 /*@
3662    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3663 
3664    Neighbor-wise Collective on Mat
3665 
3666    Input Parameters:
3667 +  A - the factored matrix
3668 -  B - the right-hand-side matrix  (dense matrix)
3669 
3670    Output Parameter:
3671 .  X - the result matrix (dense matrix)
3672 
3673    Notes:
3674    The matrices B and X cannot be the same.  I.e., one cannot
3675    call MatMatSolveTranspose(A,X,X).
3676 
3677    Notes:
3678    Most users should usually employ the simplified KSP interface for linear solvers
3679    instead of working directly with matrix algebra routines such as this.
3680    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3681    at a time.
3682 
3683    When using SuperLU_Dist or MUMPS as a parallel solver, PETSc will use their functionality to solve multiple right hand sides simultaneously.
3684 
3685    Level: developer
3686 
3687 .seealso: `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3688 @*/
3689 PetscErrorCode MatMatSolveTranspose(Mat A,Mat B,Mat X)
3690 {
3691   PetscFunctionBegin;
3692   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3693   PetscValidType(A,1);
3694   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3695   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3696   PetscCheckSameComm(A,1,B,2);
3697   PetscCheckSameComm(A,1,X,3);
3698   PetscCheck(X != B,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3699   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3700   PetscCheck(A->rmap->N == B->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N);
3701   PetscCheck(A->rmap->n == B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->n,B->rmap->n);
3702   PetscCheck(X->cmap->N >= B->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as rhs matrix");
3703   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3704   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3705   MatCheckPreallocated(A,1);
3706 
3707   PetscCall(PetscLogEventBegin(MAT_MatSolve,A,B,X,0));
3708   if (!A->ops->matsolvetranspose) {
3709     PetscCall(PetscInfo(A,"Mat type %s using basic MatMatSolveTranspose\n",((PetscObject)A)->type_name));
3710     PetscCall(MatMatSolve_Basic(A,B,X,PETSC_TRUE));
3711   } else {
3712     PetscCall((*A->ops->matsolvetranspose)(A,B,X));
3713   }
3714   PetscCall(PetscLogEventEnd(MAT_MatSolve,A,B,X,0));
3715   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3716   PetscFunctionReturn(0);
3717 }
3718 
3719 /*@
3720    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3721 
3722    Neighbor-wise Collective on Mat
3723 
3724    Input Parameters:
3725 +  A - the factored matrix
3726 -  Bt - the transpose of right-hand-side matrix
3727 
3728    Output Parameter:
3729 .  X - the result matrix (dense matrix)
3730 
3731    Notes:
3732    Most users should usually employ the simplified KSP interface for linear solvers
3733    instead of working directly with matrix algebra routines such as this.
3734    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3735    at a time.
3736 
3737    For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row format on the host processor and call MatMatTransposeSolve() to implement MUMPS' MatMatSolve().
3738 
3739    Level: developer
3740 
3741 .seealso: `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3742 @*/
3743 PetscErrorCode MatMatTransposeSolve(Mat A,Mat Bt,Mat X)
3744 {
3745   PetscFunctionBegin;
3746   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3747   PetscValidType(A,1);
3748   PetscValidHeaderSpecific(Bt,MAT_CLASSID,2);
3749   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3750   PetscCheckSameComm(A,1,Bt,2);
3751   PetscCheckSameComm(A,1,X,3);
3752 
3753   PetscCheck(X != Bt,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3754   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3755   PetscCheck(A->rmap->N == Bt->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,Bt->cmap->N);
3756   PetscCheck(X->cmap->N >= Bt->rmap->N,PetscObjectComm((PetscObject)X),PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as row number of the rhs matrix");
3757   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3758   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3759   MatCheckPreallocated(A,1);
3760 
3761   PetscCheck(A->ops->mattransposesolve,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
3762   PetscCall(PetscLogEventBegin(MAT_MatTrSolve,A,Bt,X,0));
3763   PetscCall((*A->ops->mattransposesolve)(A,Bt,X));
3764   PetscCall(PetscLogEventEnd(MAT_MatTrSolve,A,Bt,X,0));
3765   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3766   PetscFunctionReturn(0);
3767 }
3768 
3769 /*@
3770    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3771                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3772 
3773    Neighbor-wise Collective on Mat
3774 
3775    Input Parameters:
3776 +  mat - the factored matrix
3777 -  b - the right-hand-side vector
3778 
3779    Output Parameter:
3780 .  x - the result vector
3781 
3782    Notes:
3783    MatSolve() should be used for most applications, as it performs
3784    a forward solve followed by a backward solve.
3785 
3786    The vectors b and x cannot be the same,  i.e., one cannot
3787    call MatForwardSolve(A,x,x).
3788 
3789    For matrix in seqsbaij format with block size larger than 1,
3790    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3791    MatForwardSolve() solves U^T*D y = b, and
3792    MatBackwardSolve() solves U x = y.
3793    Thus they do not provide a symmetric preconditioner.
3794 
3795    Most users should employ the simplified KSP interface for linear solvers
3796    instead of working directly with matrix algebra routines such as this.
3797    See, e.g., KSPCreate().
3798 
3799    Level: developer
3800 
3801 .seealso: `MatSolve()`, `MatBackwardSolve()`
3802 @*/
3803 PetscErrorCode MatForwardSolve(Mat mat,Vec b,Vec x)
3804 {
3805   PetscFunctionBegin;
3806   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3807   PetscValidType(mat,1);
3808   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3809   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3810   PetscCheckSameComm(mat,1,b,2);
3811   PetscCheckSameComm(mat,1,x,3);
3812   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3813   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3814   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3815   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3816   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3817   MatCheckPreallocated(mat,1);
3818 
3819   PetscCheck(mat->ops->forwardsolve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3820   PetscCall(PetscLogEventBegin(MAT_ForwardSolve,mat,b,x,0));
3821   PetscCall((*mat->ops->forwardsolve)(mat,b,x));
3822   PetscCall(PetscLogEventEnd(MAT_ForwardSolve,mat,b,x,0));
3823   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3824   PetscFunctionReturn(0);
3825 }
3826 
3827 /*@
3828    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3829                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3830 
3831    Neighbor-wise Collective on Mat
3832 
3833    Input Parameters:
3834 +  mat - the factored matrix
3835 -  b - the right-hand-side vector
3836 
3837    Output Parameter:
3838 .  x - the result vector
3839 
3840    Notes:
3841    MatSolve() should be used for most applications, as it performs
3842    a forward solve followed by a backward solve.
3843 
3844    The vectors b and x cannot be the same.  I.e., one cannot
3845    call MatBackwardSolve(A,x,x).
3846 
3847    For matrix in seqsbaij format with block size larger than 1,
3848    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3849    MatForwardSolve() solves U^T*D y = b, and
3850    MatBackwardSolve() solves U x = y.
3851    Thus they do not provide a symmetric preconditioner.
3852 
3853    Most users should employ the simplified KSP interface for linear solvers
3854    instead of working directly with matrix algebra routines such as this.
3855    See, e.g., KSPCreate().
3856 
3857    Level: developer
3858 
3859 .seealso: `MatSolve()`, `MatForwardSolve()`
3860 @*/
3861 PetscErrorCode MatBackwardSolve(Mat mat,Vec b,Vec x)
3862 {
3863   PetscFunctionBegin;
3864   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3865   PetscValidType(mat,1);
3866   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3867   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3868   PetscCheckSameComm(mat,1,b,2);
3869   PetscCheckSameComm(mat,1,x,3);
3870   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3871   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3872   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3873   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3874   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3875   MatCheckPreallocated(mat,1);
3876 
3877   PetscCheck(mat->ops->backwardsolve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3878   PetscCall(PetscLogEventBegin(MAT_BackwardSolve,mat,b,x,0));
3879   PetscCall((*mat->ops->backwardsolve)(mat,b,x));
3880   PetscCall(PetscLogEventEnd(MAT_BackwardSolve,mat,b,x,0));
3881   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3882   PetscFunctionReturn(0);
3883 }
3884 
3885 /*@
3886    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3887 
3888    Neighbor-wise Collective on Mat
3889 
3890    Input Parameters:
3891 +  mat - the factored matrix
3892 .  b - the right-hand-side vector
3893 -  y - the vector to be added to
3894 
3895    Output Parameter:
3896 .  x - the result vector
3897 
3898    Notes:
3899    The vectors b and x cannot be the same.  I.e., one cannot
3900    call MatSolveAdd(A,x,y,x).
3901 
3902    Most users should employ the simplified KSP interface for linear solvers
3903    instead of working directly with matrix algebra routines such as this.
3904    See, e.g., KSPCreate().
3905 
3906    Level: developer
3907 
3908 .seealso: `MatSolve()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3909 @*/
3910 PetscErrorCode MatSolveAdd(Mat mat,Vec b,Vec y,Vec x)
3911 {
3912   PetscScalar    one = 1.0;
3913   Vec            tmp;
3914 
3915   PetscFunctionBegin;
3916   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3917   PetscValidType(mat,1);
3918   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3919   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3920   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
3921   PetscCheckSameComm(mat,1,b,2);
3922   PetscCheckSameComm(mat,1,y,3);
3923   PetscCheckSameComm(mat,1,x,4);
3924   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3925   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3926   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3927   PetscCheck(mat->rmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,y->map->N);
3928   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3929   PetscCheck(x->map->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,x->map->n,y->map->n);
3930   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3931    MatCheckPreallocated(mat,1);
3932 
3933   PetscCall(PetscLogEventBegin(MAT_SolveAdd,mat,b,x,y));
3934   if (mat->factorerrortype) {
3935 
3936     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
3937     PetscCall(VecSetInf(x));
3938   } else if (mat->ops->solveadd) {
3939     PetscCall((*mat->ops->solveadd)(mat,b,y,x));
3940   } else {
3941     /* do the solve then the add manually */
3942     if (x != y) {
3943       PetscCall(MatSolve(mat,b,x));
3944       PetscCall(VecAXPY(x,one,y));
3945     } else {
3946       PetscCall(VecDuplicate(x,&tmp));
3947       PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp));
3948       PetscCall(VecCopy(x,tmp));
3949       PetscCall(MatSolve(mat,b,x));
3950       PetscCall(VecAXPY(x,one,tmp));
3951       PetscCall(VecDestroy(&tmp));
3952     }
3953   }
3954   PetscCall(PetscLogEventEnd(MAT_SolveAdd,mat,b,x,y));
3955   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3956   PetscFunctionReturn(0);
3957 }
3958 
3959 /*@
3960    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3961 
3962    Neighbor-wise Collective on Mat
3963 
3964    Input Parameters:
3965 +  mat - the factored matrix
3966 -  b - the right-hand-side vector
3967 
3968    Output Parameter:
3969 .  x - the result vector
3970 
3971    Notes:
3972    The vectors b and x cannot be the same.  I.e., one cannot
3973    call MatSolveTranspose(A,x,x).
3974 
3975    Most users should employ the simplified KSP interface for linear solvers
3976    instead of working directly with matrix algebra routines such as this.
3977    See, e.g., KSPCreate().
3978 
3979    Level: developer
3980 
3981 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3982 @*/
3983 PetscErrorCode MatSolveTranspose(Mat mat,Vec b,Vec x)
3984 {
3985   PetscErrorCode (*f)(Mat,Vec,Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3986 
3987   PetscFunctionBegin;
3988   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3989   PetscValidType(mat,1);
3990   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3991   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3992   PetscCheckSameComm(mat,1,b,2);
3993   PetscCheckSameComm(mat,1,x,3);
3994   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3995   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
3996   PetscCheck(mat->cmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,b->map->N);
3997   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3998   MatCheckPreallocated(mat,1);
3999   PetscCall(PetscLogEventBegin(MAT_SolveTranspose,mat,b,x,0));
4000   if (mat->factorerrortype) {
4001     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
4002     PetscCall(VecSetInf(x));
4003   } else {
4004     PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s",((PetscObject)mat)->type_name);
4005     PetscCall((*f)(mat,b,x));
4006   }
4007   PetscCall(PetscLogEventEnd(MAT_SolveTranspose,mat,b,x,0));
4008   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4009   PetscFunctionReturn(0);
4010 }
4011 
4012 /*@
4013    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4014                       factored matrix.
4015 
4016    Neighbor-wise Collective on Mat
4017 
4018    Input Parameters:
4019 +  mat - the factored matrix
4020 .  b - the right-hand-side vector
4021 -  y - the vector to be added to
4022 
4023    Output Parameter:
4024 .  x - the result vector
4025 
4026    Notes:
4027    The vectors b and x cannot be the same.  I.e., one cannot
4028    call MatSolveTransposeAdd(A,x,y,x).
4029 
4030    Most users should employ the simplified KSP interface for linear solvers
4031    instead of working directly with matrix algebra routines such as this.
4032    See, e.g., KSPCreate().
4033 
4034    Level: developer
4035 
4036 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4037 @*/
4038 PetscErrorCode MatSolveTransposeAdd(Mat mat,Vec b,Vec y,Vec x)
4039 {
4040   PetscScalar    one = 1.0;
4041   Vec            tmp;
4042   PetscErrorCode (*f)(Mat,Vec,Vec,Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4043 
4044   PetscFunctionBegin;
4045   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4046   PetscValidType(mat,1);
4047   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
4048   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4049   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
4050   PetscCheckSameComm(mat,1,b,2);
4051   PetscCheckSameComm(mat,1,y,3);
4052   PetscCheckSameComm(mat,1,x,4);
4053   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
4054   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
4055   PetscCheck(mat->cmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,b->map->N);
4056   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
4057   PetscCheck(x->map->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,x->map->n,y->map->n);
4058   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4059   MatCheckPreallocated(mat,1);
4060 
4061   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd,mat,b,x,y));
4062   if (mat->factorerrortype) {
4063     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
4064     PetscCall(VecSetInf(x));
4065   } else if (f) {
4066     PetscCall((*f)(mat,b,y,x));
4067   } else {
4068     /* do the solve then the add manually */
4069     if (x != y) {
4070       PetscCall(MatSolveTranspose(mat,b,x));
4071       PetscCall(VecAXPY(x,one,y));
4072     } else {
4073       PetscCall(VecDuplicate(x,&tmp));
4074       PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp));
4075       PetscCall(VecCopy(x,tmp));
4076       PetscCall(MatSolveTranspose(mat,b,x));
4077       PetscCall(VecAXPY(x,one,tmp));
4078       PetscCall(VecDestroy(&tmp));
4079     }
4080   }
4081   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd,mat,b,x,y));
4082   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4083   PetscFunctionReturn(0);
4084 }
4085 /* ----------------------------------------------------------------*/
4086 
4087 /*@
4088    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4089 
4090    Neighbor-wise Collective on Mat
4091 
4092    Input Parameters:
4093 +  mat - the matrix
4094 .  b - the right hand side
4095 .  omega - the relaxation factor
4096 .  flag - flag indicating the type of SOR (see below)
4097 .  shift -  diagonal shift
4098 .  its - the number of iterations
4099 -  lits - the number of local iterations
4100 
4101    Output Parameter:
4102 .  x - the solution (can contain an initial guess, use option SOR_ZERO_INITIAL_GUESS to indicate no guess)
4103 
4104    SOR Flags:
4105 +     SOR_FORWARD_SWEEP - forward SOR
4106 .     SOR_BACKWARD_SWEEP - backward SOR
4107 .     SOR_SYMMETRIC_SWEEP - SSOR (symmetric SOR)
4108 .     SOR_LOCAL_FORWARD_SWEEP - local forward SOR
4109 .     SOR_LOCAL_BACKWARD_SWEEP - local forward SOR
4110 .     SOR_LOCAL_SYMMETRIC_SWEEP - local SSOR
4111 .     SOR_APPLY_UPPER, SOR_APPLY_LOWER - applies
4112          upper/lower triangular part of matrix to
4113          vector (with omega)
4114 -     SOR_ZERO_INITIAL_GUESS - zero initial guess
4115 
4116    Notes:
4117    SOR_LOCAL_FORWARD_SWEEP, SOR_LOCAL_BACKWARD_SWEEP, and
4118    SOR_LOCAL_SYMMETRIC_SWEEP perform separate independent smoothings
4119    on each processor.
4120 
4121    Application programmers will not generally use MatSOR() directly,
4122    but instead will employ the KSP/PC interface.
4123 
4124    Notes:
4125     for BAIJ, SBAIJ, and AIJ matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4126 
4127    Notes for Advanced Users:
4128    The flags are implemented as bitwise inclusive or operations.
4129    For example, use (SOR_ZERO_INITIAL_GUESS | SOR_SYMMETRIC_SWEEP)
4130    to specify a zero initial guess for SSOR.
4131 
4132    Most users should employ the simplified KSP interface for linear solvers
4133    instead of working directly with matrix algebra routines such as this.
4134    See, e.g., KSPCreate().
4135 
4136    Vectors x and b CANNOT be the same
4137 
4138    Developer Note: We should add block SOR support for AIJ matrices with block size set to great than one and no inodes
4139 
4140    Level: developer
4141 
4142 @*/
4143 PetscErrorCode MatSOR(Mat mat,Vec b,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec x)
4144 {
4145   PetscFunctionBegin;
4146   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4147   PetscValidType(mat,1);
4148   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4149   PetscValidHeaderSpecific(x,VEC_CLASSID,8);
4150   PetscCheckSameComm(mat,1,b,2);
4151   PetscCheckSameComm(mat,1,x,8);
4152   PetscCheck(mat->ops->sor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4153   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4154   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4155   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
4156   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
4157   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
4158   PetscCheck(its > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %" PetscInt_FMT " positive",its);
4159   PetscCheck(lits > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires local its %" PetscInt_FMT " positive",lits);
4160   PetscCheck(b != x,PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"b and x vector cannot be the same");
4161 
4162   MatCheckPreallocated(mat,1);
4163   PetscCall(PetscLogEventBegin(MAT_SOR,mat,b,x,0));
4164   PetscCall((*mat->ops->sor)(mat,b,omega,flag,shift,its,lits,x));
4165   PetscCall(PetscLogEventEnd(MAT_SOR,mat,b,x,0));
4166   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4167   PetscFunctionReturn(0);
4168 }
4169 
4170 /*
4171       Default matrix copy routine.
4172 */
4173 PetscErrorCode MatCopy_Basic(Mat A,Mat B,MatStructure str)
4174 {
4175   PetscInt          i,rstart = 0,rend = 0,nz;
4176   const PetscInt    *cwork;
4177   const PetscScalar *vwork;
4178 
4179   PetscFunctionBegin;
4180   if (B->assembled) PetscCall(MatZeroEntries(B));
4181   if (str == SAME_NONZERO_PATTERN) {
4182     PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
4183     for (i=rstart; i<rend; i++) {
4184       PetscCall(MatGetRow(A,i,&nz,&cwork,&vwork));
4185       PetscCall(MatSetValues(B,1,&i,nz,cwork,vwork,INSERT_VALUES));
4186       PetscCall(MatRestoreRow(A,i,&nz,&cwork,&vwork));
4187     }
4188   } else {
4189     PetscCall(MatAYPX(B,0.0,A,str));
4190   }
4191   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
4192   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
4193   PetscFunctionReturn(0);
4194 }
4195 
4196 /*@
4197    MatCopy - Copies a matrix to another matrix.
4198 
4199    Collective on Mat
4200 
4201    Input Parameters:
4202 +  A - the matrix
4203 -  str - SAME_NONZERO_PATTERN or DIFFERENT_NONZERO_PATTERN
4204 
4205    Output Parameter:
4206 .  B - where the copy is put
4207 
4208    Notes:
4209    If you use SAME_NONZERO_PATTERN then the two matrices must have the same nonzero pattern or the routine will crash.
4210 
4211    MatCopy() copies the matrix entries of a matrix to another existing
4212    matrix (after first zeroing the second matrix).  A related routine is
4213    MatConvert(), which first creates a new matrix and then copies the data.
4214 
4215    Level: intermediate
4216 
4217 .seealso: `MatConvert()`, `MatDuplicate()`
4218 @*/
4219 PetscErrorCode MatCopy(Mat A,Mat B,MatStructure str)
4220 {
4221   PetscInt       i;
4222 
4223   PetscFunctionBegin;
4224   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4225   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4226   PetscValidType(A,1);
4227   PetscValidType(B,2);
4228   PetscCheckSameComm(A,1,B,2);
4229   MatCheckPreallocated(B,2);
4230   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4231   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4232   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")",A->rmap->N,B->rmap->N,A->cmap->N,B->cmap->N);
4233   MatCheckPreallocated(A,1);
4234   if (A == B) PetscFunctionReturn(0);
4235 
4236   PetscCall(PetscLogEventBegin(MAT_Copy,A,B,0,0));
4237   if (A->ops->copy) {
4238     PetscCall((*A->ops->copy)(A,B,str));
4239   } else { /* generic conversion */
4240     PetscCall(MatCopy_Basic(A,B,str));
4241   }
4242 
4243   B->stencil.dim = A->stencil.dim;
4244   B->stencil.noc = A->stencil.noc;
4245   for (i=0; i<=A->stencil.dim; i++) {
4246     B->stencil.dims[i]   = A->stencil.dims[i];
4247     B->stencil.starts[i] = A->stencil.starts[i];
4248   }
4249 
4250   PetscCall(PetscLogEventEnd(MAT_Copy,A,B,0,0));
4251   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4252   PetscFunctionReturn(0);
4253 }
4254 
4255 /*@C
4256    MatConvert - Converts a matrix to another matrix, either of the same
4257    or different type.
4258 
4259    Collective on Mat
4260 
4261    Input Parameters:
4262 +  mat - the matrix
4263 .  newtype - new matrix type.  Use MATSAME to create a new matrix of the
4264    same type as the original matrix.
4265 -  reuse - denotes if the destination matrix is to be created or reused.
4266    Use MAT_INPLACE_MATRIX for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use
4267    MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX (can only be used after the first call was made with MAT_INITIAL_MATRIX, causes the matrix space in M to be reused).
4268 
4269    Output Parameter:
4270 .  M - pointer to place new matrix
4271 
4272    Notes:
4273    MatConvert() first creates a new matrix and then copies the data from
4274    the first matrix.  A related routine is MatCopy(), which copies the matrix
4275    entries of one matrix to another already existing matrix context.
4276 
4277    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4278    the MPI communicator of the generated matrix is always the same as the communicator
4279    of the input matrix.
4280 
4281    Level: intermediate
4282 
4283 .seealso: `MatCopy()`, `MatDuplicate()`
4284 @*/
4285 PetscErrorCode MatConvert(Mat mat,MatType newtype,MatReuse reuse,Mat *M)
4286 {
4287   PetscBool      sametype,issame,flg,issymmetric,ishermitian;
4288   char           convname[256],mtype[256];
4289   Mat            B;
4290 
4291   PetscFunctionBegin;
4292   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4293   PetscValidType(mat,1);
4294   PetscValidPointer(M,4);
4295   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4296   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4297   MatCheckPreallocated(mat,1);
4298 
4299   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matconvert_type",mtype,sizeof(mtype),&flg));
4300   if (flg) newtype = mtype;
4301 
4302   PetscCall(PetscObjectTypeCompare((PetscObject)mat,newtype,&sametype));
4303   PetscCall(PetscStrcmp(newtype,"same",&issame));
4304   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M),PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires same input and output matrix");
4305   PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M),PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4306 
4307   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4308     PetscCall(PetscInfo(mat,"Early return for inplace %s %d %d\n",((PetscObject)mat)->type_name,sametype,issame));
4309     PetscFunctionReturn(0);
4310   }
4311 
4312   /* Cache Mat options because some converter use MatHeaderReplace  */
4313   issymmetric = mat->symmetric;
4314   ishermitian = mat->hermitian;
4315 
4316   if ((sametype || issame) && (reuse==MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4317     PetscCall(PetscInfo(mat,"Calling duplicate for initial matrix %s %d %d\n",((PetscObject)mat)->type_name,sametype,issame));
4318     PetscCall((*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M));
4319   } else {
4320     PetscErrorCode (*conv)(Mat, MatType,MatReuse,Mat*)=NULL;
4321     const char     *prefix[3] = {"seq","mpi",""};
4322     PetscInt       i;
4323     /*
4324        Order of precedence:
4325        0) See if newtype is a superclass of the current matrix.
4326        1) See if a specialized converter is known to the current matrix.
4327        2) See if a specialized converter is known to the desired matrix class.
4328        3) See if a good general converter is registered for the desired class
4329           (as of 6/27/03 only MATMPIADJ falls into this category).
4330        4) See if a good general converter is known for the current matrix.
4331        5) Use a really basic converter.
4332     */
4333 
4334     /* 0) See if newtype is a superclass of the current matrix.
4335           i.e mat is mpiaij and newtype is aij */
4336     for (i=0; i<2; i++) {
4337       PetscCall(PetscStrncpy(convname,prefix[i],sizeof(convname)));
4338       PetscCall(PetscStrlcat(convname,newtype,sizeof(convname)));
4339       PetscCall(PetscStrcmp(convname,((PetscObject)mat)->type_name,&flg));
4340       PetscCall(PetscInfo(mat,"Check superclass %s %s -> %d\n",convname,((PetscObject)mat)->type_name,flg));
4341       if (flg) {
4342         if (reuse == MAT_INPLACE_MATRIX) {
4343           PetscCall(PetscInfo(mat,"Early return\n"));
4344           PetscFunctionReturn(0);
4345         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4346           PetscCall(PetscInfo(mat,"Calling MatDuplicate\n"));
4347           PetscCall((*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M));
4348           PetscFunctionReturn(0);
4349         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4350           PetscCall(PetscInfo(mat,"Calling MatCopy\n"));
4351           PetscCall(MatCopy(mat,*M,SAME_NONZERO_PATTERN));
4352           PetscFunctionReturn(0);
4353         }
4354       }
4355     }
4356     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4357     for (i=0; i<3; i++) {
4358       PetscCall(PetscStrncpy(convname,"MatConvert_",sizeof(convname)));
4359       PetscCall(PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname)));
4360       PetscCall(PetscStrlcat(convname,"_",sizeof(convname)));
4361       PetscCall(PetscStrlcat(convname,prefix[i],sizeof(convname)));
4362       PetscCall(PetscStrlcat(convname,issame ? ((PetscObject)mat)->type_name : newtype,sizeof(convname)));
4363       PetscCall(PetscStrlcat(convname,"_C",sizeof(convname)));
4364       PetscCall(PetscObjectQueryFunction((PetscObject)mat,convname,&conv));
4365       PetscCall(PetscInfo(mat,"Check specialized (1) %s (%s) -> %d\n",convname,((PetscObject)mat)->type_name,!!conv));
4366       if (conv) goto foundconv;
4367     }
4368 
4369     /* 2)  See if a specialized converter is known to the desired matrix class. */
4370     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&B));
4371     PetscCall(MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
4372     PetscCall(MatSetType(B,newtype));
4373     for (i=0; i<3; i++) {
4374       PetscCall(PetscStrncpy(convname,"MatConvert_",sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname,"_",sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname,prefix[i],sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname,newtype,sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname,"_C",sizeof(convname)));
4380       PetscCall(PetscObjectQueryFunction((PetscObject)B,convname,&conv));
4381       PetscCall(PetscInfo(mat,"Check specialized (2) %s (%s) -> %d\n",convname,((PetscObject)B)->type_name,!!conv));
4382       if (conv) {
4383         PetscCall(MatDestroy(&B));
4384         goto foundconv;
4385       }
4386     }
4387 
4388     /* 3) See if a good general converter is registered for the desired class */
4389     conv = B->ops->convertfrom;
4390     PetscCall(PetscInfo(mat,"Check convertfrom (%s) -> %d\n",((PetscObject)B)->type_name,!!conv));
4391     PetscCall(MatDestroy(&B));
4392     if (conv) goto foundconv;
4393 
4394     /* 4) See if a good general converter is known for the current matrix */
4395     if (mat->ops->convert) conv = mat->ops->convert;
4396     PetscCall(PetscInfo(mat,"Check general convert (%s) -> %d\n",((PetscObject)mat)->type_name,!!conv));
4397     if (conv) goto foundconv;
4398 
4399     /* 5) Use a really basic converter. */
4400     PetscCall(PetscInfo(mat,"Using MatConvert_Basic\n"));
4401     conv = MatConvert_Basic;
4402 
4403 foundconv:
4404     PetscCall(PetscLogEventBegin(MAT_Convert,mat,0,0,0));
4405     PetscCall((*conv)(mat,newtype,reuse,M));
4406     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4407       /* the block sizes must be same if the mappings are copied over */
4408       (*M)->rmap->bs = mat->rmap->bs;
4409       (*M)->cmap->bs = mat->cmap->bs;
4410       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4411       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4412       (*M)->rmap->mapping = mat->rmap->mapping;
4413       (*M)->cmap->mapping = mat->cmap->mapping;
4414     }
4415     (*M)->stencil.dim = mat->stencil.dim;
4416     (*M)->stencil.noc = mat->stencil.noc;
4417     for (i=0; i<=mat->stencil.dim; i++) {
4418       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4419       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4420     }
4421     PetscCall(PetscLogEventEnd(MAT_Convert,mat,0,0,0));
4422   }
4423   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4424 
4425   /* Copy Mat options */
4426   if (issymmetric) PetscCall(MatSetOption(*M,MAT_SYMMETRIC,PETSC_TRUE));
4427   if (ishermitian) PetscCall(MatSetOption(*M,MAT_HERMITIAN,PETSC_TRUE));
4428   PetscFunctionReturn(0);
4429 }
4430 
4431 /*@C
4432    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4433 
4434    Not Collective
4435 
4436    Input Parameter:
4437 .  mat - the matrix, must be a factored matrix
4438 
4439    Output Parameter:
4440 .   type - the string name of the package (do not free this string)
4441 
4442    Notes:
4443       In Fortran you pass in a empty string and the package name will be copied into it.
4444     (Make sure the string is long enough)
4445 
4446    Level: intermediate
4447 
4448 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4449 @*/
4450 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4451 {
4452   PetscErrorCode (*conv)(Mat,MatSolverType*);
4453 
4454   PetscFunctionBegin;
4455   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4456   PetscValidType(mat,1);
4457   PetscValidPointer(type,2);
4458   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
4459   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorGetSolverType_C",&conv));
4460   if (conv) PetscCall((*conv)(mat,type));
4461   else *type = MATSOLVERPETSC;
4462   PetscFunctionReturn(0);
4463 }
4464 
4465 typedef struct _MatSolverTypeForSpecifcType* MatSolverTypeForSpecifcType;
4466 struct _MatSolverTypeForSpecifcType {
4467   MatType                        mtype;
4468   /* no entry for MAT_FACTOR_NONE */
4469   PetscErrorCode                 (*createfactor[MAT_FACTOR_NUM_TYPES-1])(Mat,MatFactorType,Mat*);
4470   MatSolverTypeForSpecifcType next;
4471 };
4472 
4473 typedef struct _MatSolverTypeHolder* MatSolverTypeHolder;
4474 struct _MatSolverTypeHolder {
4475   char                        *name;
4476   MatSolverTypeForSpecifcType handlers;
4477   MatSolverTypeHolder         next;
4478 };
4479 
4480 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4481 
4482 /*@C
4483    MatSolverTypeRegister - Registers a MatSolverType that works for a particular matrix type
4484 
4485    Input Parameters:
4486 +    package - name of the package, for example petsc or superlu
4487 .    mtype - the matrix type that works with this package
4488 .    ftype - the type of factorization supported by the package
4489 -    createfactor - routine that will create the factored matrix ready to be used
4490 
4491     Level: intermediate
4492 
4493 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4494 @*/
4495 PetscErrorCode MatSolverTypeRegister(MatSolverType package,MatType mtype,MatFactorType ftype,PetscErrorCode (*createfactor)(Mat,MatFactorType,Mat*))
4496 {
4497   MatSolverTypeHolder         next = MatSolverTypeHolders,prev = NULL;
4498   PetscBool                   flg;
4499   MatSolverTypeForSpecifcType inext,iprev = NULL;
4500 
4501   PetscFunctionBegin;
4502   PetscCall(MatInitializePackage());
4503   if (!next) {
4504     PetscCall(PetscNew(&MatSolverTypeHolders));
4505     PetscCall(PetscStrallocpy(package,&MatSolverTypeHolders->name));
4506     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4507     PetscCall(PetscStrallocpy(mtype,(char **)&MatSolverTypeHolders->handlers->mtype));
4508     MatSolverTypeHolders->handlers->createfactor[(int)ftype-1] = createfactor;
4509     PetscFunctionReturn(0);
4510   }
4511   while (next) {
4512     PetscCall(PetscStrcasecmp(package,next->name,&flg));
4513     if (flg) {
4514       PetscCheck(next->handlers,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatSolverTypeHolder is missing handlers");
4515       inext = next->handlers;
4516       while (inext) {
4517         PetscCall(PetscStrcasecmp(mtype,inext->mtype,&flg));
4518         if (flg) {
4519           inext->createfactor[(int)ftype-1] = createfactor;
4520           PetscFunctionReturn(0);
4521         }
4522         iprev = inext;
4523         inext = inext->next;
4524       }
4525       PetscCall(PetscNew(&iprev->next));
4526       PetscCall(PetscStrallocpy(mtype,(char **)&iprev->next->mtype));
4527       iprev->next->createfactor[(int)ftype-1] = createfactor;
4528       PetscFunctionReturn(0);
4529     }
4530     prev = next;
4531     next = next->next;
4532   }
4533   PetscCall(PetscNew(&prev->next));
4534   PetscCall(PetscStrallocpy(package,&prev->next->name));
4535   PetscCall(PetscNew(&prev->next->handlers));
4536   PetscCall(PetscStrallocpy(mtype,(char **)&prev->next->handlers->mtype));
4537   prev->next->handlers->createfactor[(int)ftype-1] = createfactor;
4538   PetscFunctionReturn(0);
4539 }
4540 
4541 /*@C
4542    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4543 
4544    Input Parameters:
4545 +    type - name of the package, for example petsc or superlu
4546 .    ftype - the type of factorization supported by the type
4547 -    mtype - the matrix type that works with this type
4548 
4549    Output Parameters:
4550 +   foundtype - PETSC_TRUE if the type was registered
4551 .   foundmtype - PETSC_TRUE if the type supports the requested mtype
4552 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4553 
4554     Level: intermediate
4555 
4556 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4557 @*/
4558 PetscErrorCode MatSolverTypeGet(MatSolverType type,MatType mtype,MatFactorType ftype,PetscBool *foundtype,PetscBool *foundmtype,PetscErrorCode (**createfactor)(Mat,MatFactorType,Mat*))
4559 {
4560   MatSolverTypeHolder         next = MatSolverTypeHolders;
4561   PetscBool                   flg;
4562   MatSolverTypeForSpecifcType inext;
4563 
4564   PetscFunctionBegin;
4565   if (foundtype) *foundtype = PETSC_FALSE;
4566   if (foundmtype) *foundmtype = PETSC_FALSE;
4567   if (createfactor) *createfactor = NULL;
4568 
4569   if (type) {
4570     while (next) {
4571       PetscCall(PetscStrcasecmp(type,next->name,&flg));
4572       if (flg) {
4573         if (foundtype) *foundtype = PETSC_TRUE;
4574         inext = next->handlers;
4575         while (inext) {
4576           PetscCall(PetscStrbeginswith(mtype,inext->mtype,&flg));
4577           if (flg) {
4578             if (foundmtype) *foundmtype = PETSC_TRUE;
4579             if (createfactor)  *createfactor  = inext->createfactor[(int)ftype-1];
4580             PetscFunctionReturn(0);
4581           }
4582           inext = inext->next;
4583         }
4584       }
4585       next = next->next;
4586     }
4587   } else {
4588     while (next) {
4589       inext = next->handlers;
4590       while (inext) {
4591         PetscCall(PetscStrcmp(mtype,inext->mtype,&flg));
4592         if (flg && inext->createfactor[(int)ftype-1]) {
4593           if (foundtype) *foundtype = PETSC_TRUE;
4594           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4595           if (createfactor) *createfactor = inext->createfactor[(int)ftype-1];
4596           PetscFunctionReturn(0);
4597         }
4598         inext = inext->next;
4599       }
4600       next = next->next;
4601     }
4602     /* try with base classes inext->mtype */
4603     next = MatSolverTypeHolders;
4604     while (next) {
4605       inext = next->handlers;
4606       while (inext) {
4607         PetscCall(PetscStrbeginswith(mtype,inext->mtype,&flg));
4608         if (flg && inext->createfactor[(int)ftype-1]) {
4609           if (foundtype) *foundtype = PETSC_TRUE;
4610           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4611           if (createfactor) *createfactor = inext->createfactor[(int)ftype-1];
4612           PetscFunctionReturn(0);
4613         }
4614         inext = inext->next;
4615       }
4616       next = next->next;
4617     }
4618   }
4619   PetscFunctionReturn(0);
4620 }
4621 
4622 PetscErrorCode MatSolverTypeDestroy(void)
4623 {
4624   MatSolverTypeHolder         next = MatSolverTypeHolders,prev;
4625   MatSolverTypeForSpecifcType inext,iprev;
4626 
4627   PetscFunctionBegin;
4628   while (next) {
4629     PetscCall(PetscFree(next->name));
4630     inext = next->handlers;
4631     while (inext) {
4632       PetscCall(PetscFree(inext->mtype));
4633       iprev = inext;
4634       inext = inext->next;
4635       PetscCall(PetscFree(iprev));
4636     }
4637     prev = next;
4638     next = next->next;
4639     PetscCall(PetscFree(prev));
4640   }
4641   MatSolverTypeHolders = NULL;
4642   PetscFunctionReturn(0);
4643 }
4644 
4645 /*@C
4646    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in MatLUFactorSymbolic(), MatCholeskyFactorSymbolic()
4647 
4648    Logically Collective on Mat
4649 
4650    Input Parameters:
4651 .  mat - the matrix
4652 
4653    Output Parameters:
4654 .  flg - PETSC_TRUE if uses the ordering
4655 
4656    Notes:
4657       Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4658       packages do not, thus we want to skip generating the ordering when it is not needed or used.
4659 
4660    Level: developer
4661 
4662 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4663 @*/
4664 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4665 {
4666   PetscFunctionBegin;
4667   *flg = mat->canuseordering;
4668   PetscFunctionReturn(0);
4669 }
4670 
4671 /*@C
4672    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4673 
4674    Logically Collective on Mat
4675 
4676    Input Parameters:
4677 .  mat - the matrix
4678 
4679    Output Parameters:
4680 .  otype - the preferred type
4681 
4682    Level: developer
4683 
4684 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4685 @*/
4686 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4687 {
4688   PetscFunctionBegin;
4689   *otype = mat->preferredordering[ftype];
4690   PetscCheck(*otype,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatFactor did not have a preferred ordering");
4691   PetscFunctionReturn(0);
4692 }
4693 
4694 /*@C
4695    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4696 
4697    Collective on Mat
4698 
4699    Input Parameters:
4700 +  mat - the matrix
4701 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4702 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4703 
4704    Output Parameters:
4705 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4706 
4707    Options Database Key:
4708 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4709                                   One can choose host to save device memory). Currently only supported with SEQAIJCUSPARSE matrices.
4710 
4711    Notes:
4712       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4713      such as pastix, superlu, mumps etc.
4714 
4715       PETSc must have been ./configure to use the external solver, using the option --download-package
4716 
4717       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4718       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4719       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4720 
4721    Developer Notes:
4722       This should actually be called MatCreateFactor() since it creates a new factor object
4723 
4724    Level: intermediate
4725 
4726 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`
4727 @*/
4728 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type,MatFactorType ftype,Mat *f)
4729 {
4730   PetscBool      foundtype,foundmtype;
4731   PetscErrorCode (*conv)(Mat,MatFactorType,Mat*);
4732 
4733   PetscFunctionBegin;
4734   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4735   PetscValidType(mat,1);
4736 
4737   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4738   MatCheckPreallocated(mat,1);
4739 
4740   PetscCall(MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,&foundtype,&foundmtype,&conv));
4741   if (!foundtype) {
4742     if (type) {
4743       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);
4744     } else {
4745       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);
4746     }
4747   }
4748   PetscCheck(foundmtype,PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"MatSolverType %s does not support matrix type %s",type,((PetscObject)mat)->type_name);
4749   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);
4750 
4751   PetscCall((*conv)(mat,ftype,f));
4752   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f,mat->factorprefix));
4753   PetscFunctionReturn(0);
4754 }
4755 
4756 /*@C
4757    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4758 
4759    Not Collective
4760 
4761    Input Parameters:
4762 +  mat - the matrix
4763 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4764 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4765 
4766    Output Parameter:
4767 .    flg - PETSC_TRUE if the factorization is available
4768 
4769    Notes:
4770       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4771      such as pastix, superlu, mumps etc.
4772 
4773       PETSc must have been ./configure to use the external solver, using the option --download-package
4774 
4775    Developer Notes:
4776       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4777 
4778    Level: intermediate
4779 
4780 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`
4781 @*/
4782 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type,MatFactorType ftype,PetscBool  *flg)
4783 {
4784   PetscErrorCode (*gconv)(Mat,MatFactorType,Mat*);
4785 
4786   PetscFunctionBegin;
4787   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4788   PetscValidType(mat,1);
4789   PetscValidBoolPointer(flg,4);
4790 
4791   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4792   MatCheckPreallocated(mat,1);
4793 
4794   PetscCall(MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,NULL,NULL,&gconv));
4795   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4796   PetscFunctionReturn(0);
4797 }
4798 
4799 /*@
4800    MatDuplicate - Duplicates a matrix including the non-zero structure.
4801 
4802    Collective on Mat
4803 
4804    Input Parameters:
4805 +  mat - the matrix
4806 -  op - One of MAT_DO_NOT_COPY_VALUES, MAT_COPY_VALUES, or MAT_SHARE_NONZERO_PATTERN.
4807         See the manual page for MatDuplicateOption for an explanation of these options.
4808 
4809    Output Parameter:
4810 .  M - pointer to place new matrix
4811 
4812    Level: intermediate
4813 
4814    Notes:
4815     You cannot change the nonzero pattern for the parent or child matrix if you use MAT_SHARE_NONZERO_PATTERN.
4816     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.
4817     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.
4818 
4819 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4820 @*/
4821 PetscErrorCode MatDuplicate(Mat mat,MatDuplicateOption op,Mat *M)
4822 {
4823   Mat            B;
4824   VecType        vtype;
4825   PetscInt       i;
4826   PetscObject    dm;
4827   void           (*viewf)(void);
4828 
4829   PetscFunctionBegin;
4830   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4831   PetscValidType(mat,1);
4832   PetscValidPointer(M,3);
4833   PetscCheck(op != MAT_COPY_VALUES || mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MAT_COPY_VALUES not allowed for unassembled matrix");
4834   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4835   MatCheckPreallocated(mat,1);
4836 
4837   *M = NULL;
4838   PetscCheck(mat->ops->duplicate,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not written for matrix type %s",((PetscObject)mat)->type_name);
4839   PetscCall(PetscLogEventBegin(MAT_Convert,mat,0,0,0));
4840   PetscCall((*mat->ops->duplicate)(mat,op,M));
4841   PetscCall(PetscLogEventEnd(MAT_Convert,mat,0,0,0));
4842   B    = *M;
4843 
4844   PetscCall(MatGetOperation(mat,MATOP_VIEW,&viewf));
4845   if (viewf) PetscCall(MatSetOperation(B,MATOP_VIEW,viewf));
4846   PetscCall(MatGetVecType(mat,&vtype));
4847   PetscCall(MatSetVecType(B,vtype));
4848 
4849   B->stencil.dim = mat->stencil.dim;
4850   B->stencil.noc = mat->stencil.noc;
4851   for (i=0; i<=mat->stencil.dim; i++) {
4852     B->stencil.dims[i]   = mat->stencil.dims[i];
4853     B->stencil.starts[i] = mat->stencil.starts[i];
4854   }
4855 
4856   B->nooffproczerorows = mat->nooffproczerorows;
4857   B->nooffprocentries  = mat->nooffprocentries;
4858 
4859   PetscCall(PetscObjectQuery((PetscObject) mat, "__PETSc_dm", &dm));
4860   if (dm) {
4861     PetscCall(PetscObjectCompose((PetscObject) B, "__PETSc_dm", dm));
4862   }
4863   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4864   PetscFunctionReturn(0);
4865 }
4866 
4867 /*@
4868    MatGetDiagonal - Gets the diagonal of a matrix.
4869 
4870    Logically Collective on Mat
4871 
4872    Input Parameters:
4873 +  mat - the matrix
4874 -  v - the vector for storing the diagonal
4875 
4876    Output Parameter:
4877 .  v - the diagonal of the matrix
4878 
4879    Level: intermediate
4880 
4881    Note:
4882    Currently only correct in parallel for square matrices.
4883 
4884 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4885 @*/
4886 PetscErrorCode MatGetDiagonal(Mat mat,Vec v)
4887 {
4888   PetscFunctionBegin;
4889   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4890   PetscValidType(mat,1);
4891   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4892   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4893   PetscCheck(mat->ops->getdiagonal,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4894   MatCheckPreallocated(mat,1);
4895 
4896   PetscCall((*mat->ops->getdiagonal)(mat,v));
4897   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4898   PetscFunctionReturn(0);
4899 }
4900 
4901 /*@C
4902    MatGetRowMin - Gets the minimum value (of the real part) of each
4903         row of the matrix
4904 
4905    Logically Collective on Mat
4906 
4907    Input Parameter:
4908 .  mat - the matrix
4909 
4910    Output Parameters:
4911 +  v - the vector for storing the maximums
4912 -  idx - the indices of the column found for each row (optional)
4913 
4914    Level: intermediate
4915 
4916    Notes:
4917     The result of this call are the same as if one converted the matrix to dense format
4918       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4919 
4920     This code is only implemented for a couple of matrix formats.
4921 
4922 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`,
4923           `MatGetRowMax()`
4924 @*/
4925 PetscErrorCode MatGetRowMin(Mat mat,Vec v,PetscInt idx[])
4926 {
4927   PetscFunctionBegin;
4928   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4929   PetscValidType(mat,1);
4930   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4931   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4932 
4933   if (!mat->cmap->N) {
4934     PetscCall(VecSet(v,PETSC_MAX_REAL));
4935     if (idx) {
4936       PetscInt i,m = mat->rmap->n;
4937       for (i=0; i<m; i++) idx[i] = -1;
4938     }
4939   } else {
4940     PetscCheck(mat->ops->getrowmin,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4941     MatCheckPreallocated(mat,1);
4942   }
4943   PetscCall((*mat->ops->getrowmin)(mat,v,idx));
4944   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4945   PetscFunctionReturn(0);
4946 }
4947 
4948 /*@C
4949    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4950         row of the matrix
4951 
4952    Logically Collective on Mat
4953 
4954    Input Parameter:
4955 .  mat - the matrix
4956 
4957    Output Parameters:
4958 +  v - the vector for storing the minimums
4959 -  idx - the indices of the column found for each row (or NULL if not needed)
4960 
4961    Level: intermediate
4962 
4963    Notes:
4964     if a row is completely empty or has only 0.0 values then the idx[] value for that
4965     row is 0 (the first column).
4966 
4967     This code is only implemented for a couple of matrix formats.
4968 
4969 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4970 @*/
4971 PetscErrorCode MatGetRowMinAbs(Mat mat,Vec v,PetscInt idx[])
4972 {
4973   PetscFunctionBegin;
4974   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4975   PetscValidType(mat,1);
4976   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4977   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4978   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4979 
4980   if (!mat->cmap->N) {
4981     PetscCall(VecSet(v,0.0));
4982     if (idx) {
4983       PetscInt i,m = mat->rmap->n;
4984       for (i=0; i<m; i++) idx[i] = -1;
4985     }
4986   } else {
4987     PetscCheck(mat->ops->getrowminabs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4988     MatCheckPreallocated(mat,1);
4989     if (idx) PetscCall(PetscArrayzero(idx,mat->rmap->n));
4990     PetscCall((*mat->ops->getrowminabs)(mat,v,idx));
4991   }
4992   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4993   PetscFunctionReturn(0);
4994 }
4995 
4996 /*@C
4997    MatGetRowMax - Gets the maximum value (of the real part) of each
4998         row of the matrix
4999 
5000    Logically Collective on Mat
5001 
5002    Input Parameter:
5003 .  mat - the matrix
5004 
5005    Output Parameters:
5006 +  v - the vector for storing the maximums
5007 -  idx - the indices of the column found for each row (optional)
5008 
5009    Level: intermediate
5010 
5011    Notes:
5012     The result of this call are the same as if one converted the matrix to dense format
5013       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5014 
5015     This code is only implemented for a couple of matrix formats.
5016 
5017 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5018 @*/
5019 PetscErrorCode MatGetRowMax(Mat mat,Vec v,PetscInt idx[])
5020 {
5021   PetscFunctionBegin;
5022   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5023   PetscValidType(mat,1);
5024   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5025   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5026 
5027   if (!mat->cmap->N) {
5028     PetscCall(VecSet(v,PETSC_MIN_REAL));
5029     if (idx) {
5030       PetscInt i,m = mat->rmap->n;
5031       for (i=0; i<m; i++) idx[i] = -1;
5032     }
5033   } else {
5034     PetscCheck(mat->ops->getrowmax,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5035     MatCheckPreallocated(mat,1);
5036     PetscCall((*mat->ops->getrowmax)(mat,v,idx));
5037   }
5038   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5039   PetscFunctionReturn(0);
5040 }
5041 
5042 /*@C
5043    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5044         row of the matrix
5045 
5046    Logically Collective on Mat
5047 
5048    Input Parameter:
5049 .  mat - the matrix
5050 
5051    Output Parameters:
5052 +  v - the vector for storing the maximums
5053 -  idx - the indices of the column found for each row (or NULL if not needed)
5054 
5055    Level: intermediate
5056 
5057    Notes:
5058     if a row is completely empty or has only 0.0 values then the idx[] value for that
5059     row is 0 (the first column).
5060 
5061     This code is only implemented for a couple of matrix formats.
5062 
5063 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`
5064 @*/
5065 PetscErrorCode MatGetRowMaxAbs(Mat mat,Vec v,PetscInt idx[])
5066 {
5067   PetscFunctionBegin;
5068   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5069   PetscValidType(mat,1);
5070   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5071   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5072 
5073   if (!mat->cmap->N) {
5074     PetscCall(VecSet(v,0.0));
5075     if (idx) {
5076       PetscInt i,m = mat->rmap->n;
5077       for (i=0; i<m; i++) idx[i] = -1;
5078     }
5079   } else {
5080     PetscCheck(mat->ops->getrowmaxabs,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5081     MatCheckPreallocated(mat,1);
5082     if (idx) PetscCall(PetscArrayzero(idx,mat->rmap->n));
5083     PetscCall((*mat->ops->getrowmaxabs)(mat,v,idx));
5084   }
5085   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5086   PetscFunctionReturn(0);
5087 }
5088 
5089 /*@
5090    MatGetRowSum - Gets the sum of each row of the matrix
5091 
5092    Logically or Neighborhood Collective on Mat
5093 
5094    Input Parameters:
5095 .  mat - the matrix
5096 
5097    Output Parameter:
5098 .  v - the vector for storing the sum of rows
5099 
5100    Level: intermediate
5101 
5102    Notes:
5103     This code is slow since it is not currently specialized for different formats
5104 
5105 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`
5106 @*/
5107 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5108 {
5109   Vec            ones;
5110 
5111   PetscFunctionBegin;
5112   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5113   PetscValidType(mat,1);
5114   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5115   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5116   MatCheckPreallocated(mat,1);
5117   PetscCall(MatCreateVecs(mat,&ones,NULL));
5118   PetscCall(VecSet(ones,1.));
5119   PetscCall(MatMult(mat,ones,v));
5120   PetscCall(VecDestroy(&ones));
5121   PetscFunctionReturn(0);
5122 }
5123 
5124 /*@
5125    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5126 
5127    Collective on Mat
5128 
5129    Input Parameters:
5130 +  mat - the matrix to transpose
5131 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5132 
5133    Output Parameter:
5134 .  B - the transpose
5135 
5136    Notes:
5137      If you use MAT_INPLACE_MATRIX then you must pass in &mat for B
5138 
5139      MAT_REUSE_MATRIX causes the B matrix from a previous call to this function with MAT_INITIAL_MATRIX to be used
5140 
5141      Consider using MatCreateTranspose() instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5142 
5143    Level: intermediate
5144 
5145 .seealso: `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5146 @*/
5147 PetscErrorCode MatTranspose(Mat mat,MatReuse reuse,Mat *B)
5148 {
5149   PetscFunctionBegin;
5150   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5151   PetscValidType(mat,1);
5152   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5153   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5154   PetscCheck(mat->ops->transpose,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5155   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires last matrix to match first");
5156   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Perhaps you mean MAT_INPLACE_MATRIX");
5157   MatCheckPreallocated(mat,1);
5158 
5159   PetscCall(PetscLogEventBegin(MAT_Transpose,mat,0,0,0));
5160   PetscCall((*mat->ops->transpose)(mat,reuse,B));
5161   PetscCall(PetscLogEventEnd(MAT_Transpose,mat,0,0,0));
5162   if (B) PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5163   PetscFunctionReturn(0);
5164 }
5165 
5166 /*@
5167    MatIsTranspose - Test whether a matrix is another one's transpose,
5168         or its own, in which case it tests symmetry.
5169 
5170    Collective on Mat
5171 
5172    Input Parameters:
5173 +  A - the matrix to test
5174 -  B - the matrix to test against, this can equal the first parameter
5175 
5176    Output Parameters:
5177 .  flg - the result
5178 
5179    Notes:
5180    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5181    has a running time of the order of the number of nonzeros; the parallel
5182    test involves parallel copies of the block-offdiagonal parts of the matrix.
5183 
5184    Level: intermediate
5185 
5186 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5187 @*/
5188 PetscErrorCode MatIsTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5189 {
5190   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5191 
5192   PetscFunctionBegin;
5193   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5194   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5195   PetscValidBoolPointer(flg,4);
5196   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsTranspose_C",&f));
5197   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsTranspose_C",&g));
5198   *flg = PETSC_FALSE;
5199   if (f && g) {
5200     PetscCheck(f == g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for symmetry test");
5201     PetscCall((*f)(A,B,tol,flg));
5202   } else {
5203     MatType mattype;
5204 
5205     PetscCall(MatGetType(f ? B : A,&mattype));
5206     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for transpose",mattype);
5207   }
5208   PetscFunctionReturn(0);
5209 }
5210 
5211 /*@
5212    MatHermitianTranspose - Computes an in-place or out-of-place transpose of a matrix in complex conjugate.
5213 
5214    Collective on Mat
5215 
5216    Input Parameters:
5217 +  mat - the matrix to transpose and complex conjugate
5218 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5219 
5220    Output Parameter:
5221 .  B - the Hermitian
5222 
5223    Level: intermediate
5224 
5225 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5226 @*/
5227 PetscErrorCode MatHermitianTranspose(Mat mat,MatReuse reuse,Mat *B)
5228 {
5229   PetscFunctionBegin;
5230   PetscCall(MatTranspose(mat,reuse,B));
5231 #if defined(PETSC_USE_COMPLEX)
5232   PetscCall(MatConjugate(*B));
5233 #endif
5234   PetscFunctionReturn(0);
5235 }
5236 
5237 /*@
5238    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5239 
5240    Collective on Mat
5241 
5242    Input Parameters:
5243 +  A - the matrix to test
5244 -  B - the matrix to test against, this can equal the first parameter
5245 
5246    Output Parameters:
5247 .  flg - the result
5248 
5249    Notes:
5250    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5251    has a running time of the order of the number of nonzeros; the parallel
5252    test involves parallel copies of the block-offdiagonal parts of the matrix.
5253 
5254    Level: intermediate
5255 
5256 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5257 @*/
5258 PetscErrorCode MatIsHermitianTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5259 {
5260   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5261 
5262   PetscFunctionBegin;
5263   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5264   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5265   PetscValidBoolPointer(flg,4);
5266   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsHermitianTranspose_C",&f));
5267   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsHermitianTranspose_C",&g));
5268   if (f && g) {
5269     PetscCheck(f != g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for Hermitian test");
5270     PetscCall((*f)(A,B,tol,flg));
5271   }
5272   PetscFunctionReturn(0);
5273 }
5274 
5275 /*@
5276    MatPermute - Creates a new matrix with rows and columns permuted from the
5277    original.
5278 
5279    Collective on Mat
5280 
5281    Input Parameters:
5282 +  mat - the matrix to permute
5283 .  row - row permutation, each processor supplies only the permutation for its rows
5284 -  col - column permutation, each processor supplies only the permutation for its columns
5285 
5286    Output Parameters:
5287 .  B - the permuted matrix
5288 
5289    Level: advanced
5290 
5291    Note:
5292    The index sets map from row/col of permuted matrix to row/col of original matrix.
5293    The index sets should be on the same communicator as Mat and have the same local sizes.
5294 
5295    Developer Note:
5296      If you want to implement MatPermute for a matrix type, and your approach doesn't
5297      exploit the fact that row and col are permutations, consider implementing the
5298      more general MatCreateSubMatrix() instead.
5299 
5300 .seealso: `MatGetOrdering()`, `ISAllGather()`
5301 
5302 @*/
5303 PetscErrorCode MatPermute(Mat mat,IS row,IS col,Mat *B)
5304 {
5305   PetscFunctionBegin;
5306   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5307   PetscValidType(mat,1);
5308   PetscValidHeaderSpecific(row,IS_CLASSID,2);
5309   PetscValidHeaderSpecific(col,IS_CLASSID,3);
5310   PetscValidPointer(B,4);
5311   PetscCheckSameComm(mat,1,row,2);
5312   if (row != col) PetscCheckSameComm(row,2,col,3);
5313   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5314   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5315   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatPermute not available for Mat type %s",((PetscObject)mat)->type_name);
5316   MatCheckPreallocated(mat,1);
5317 
5318   if (mat->ops->permute) {
5319     PetscCall((*mat->ops->permute)(mat,row,col,B));
5320     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5321   } else {
5322     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5323   }
5324   PetscFunctionReturn(0);
5325 }
5326 
5327 /*@
5328    MatEqual - Compares two matrices.
5329 
5330    Collective on Mat
5331 
5332    Input Parameters:
5333 +  A - the first matrix
5334 -  B - the second matrix
5335 
5336    Output Parameter:
5337 .  flg - PETSC_TRUE if the matrices are equal; PETSC_FALSE otherwise.
5338 
5339    Level: intermediate
5340 
5341 @*/
5342 PetscErrorCode MatEqual(Mat A,Mat B,PetscBool *flg)
5343 {
5344   PetscFunctionBegin;
5345   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5346   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5347   PetscValidType(A,1);
5348   PetscValidType(B,2);
5349   PetscValidBoolPointer(flg,3);
5350   PetscCheckSameComm(A,1,B,2);
5351   MatCheckPreallocated(A,1);
5352   MatCheckPreallocated(B,2);
5353   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5354   PetscCheck(B->assembled,PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5355   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);
5356   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5357     PetscCall((*A->ops->equal)(A,B,flg));
5358   } else {
5359     PetscCall(MatMultEqual(A,B,10,flg));
5360   }
5361   PetscFunctionReturn(0);
5362 }
5363 
5364 /*@
5365    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5366    matrices that are stored as vectors.  Either of the two scaling
5367    matrices can be NULL.
5368 
5369    Collective on Mat
5370 
5371    Input Parameters:
5372 +  mat - the matrix to be scaled
5373 .  l - the left scaling vector (or NULL)
5374 -  r - the right scaling vector (or NULL)
5375 
5376    Notes:
5377    MatDiagonalScale() computes A = LAR, where
5378    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5379    The L scales the rows of the matrix, the R scales the columns of the matrix.
5380 
5381    Level: intermediate
5382 
5383 .seealso: `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5384 @*/
5385 PetscErrorCode MatDiagonalScale(Mat mat,Vec l,Vec r)
5386 {
5387   PetscFunctionBegin;
5388   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5389   PetscValidType(mat,1);
5390   if (l) {PetscValidHeaderSpecific(l,VEC_CLASSID,2);PetscCheckSameComm(mat,1,l,2);}
5391   if (r) {PetscValidHeaderSpecific(r,VEC_CLASSID,3);PetscCheckSameComm(mat,1,r,3);}
5392   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5393   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5394   MatCheckPreallocated(mat,1);
5395   if (!l && !r) PetscFunctionReturn(0);
5396 
5397   PetscCheck(mat->ops->diagonalscale,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5398   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5399   PetscCall((*mat->ops->diagonalscale)(mat,l,r));
5400   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5401   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5402   if (l != r && mat->symmetric) mat->symmetric = PETSC_FALSE;
5403   PetscFunctionReturn(0);
5404 }
5405 
5406 /*@
5407     MatScale - Scales all elements of a matrix by a given number.
5408 
5409     Logically Collective on Mat
5410 
5411     Input Parameters:
5412 +   mat - the matrix to be scaled
5413 -   a  - the scaling value
5414 
5415     Output Parameter:
5416 .   mat - the scaled matrix
5417 
5418     Level: intermediate
5419 
5420 .seealso: `MatDiagonalScale()`
5421 @*/
5422 PetscErrorCode MatScale(Mat mat,PetscScalar a)
5423 {
5424   PetscFunctionBegin;
5425   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5426   PetscValidType(mat,1);
5427   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5428   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5429   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5430   PetscValidLogicalCollectiveScalar(mat,a,2);
5431   MatCheckPreallocated(mat,1);
5432 
5433   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5434   if (a != (PetscScalar)1.0) {
5435     PetscCall((*mat->ops->scale)(mat,a));
5436     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5437   }
5438   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5439   PetscFunctionReturn(0);
5440 }
5441 
5442 /*@
5443    MatNorm - Calculates various norms of a matrix.
5444 
5445    Collective on Mat
5446 
5447    Input Parameters:
5448 +  mat - the matrix
5449 -  type - the type of norm, NORM_1, NORM_FROBENIUS, NORM_INFINITY
5450 
5451    Output Parameter:
5452 .  nrm - the resulting norm
5453 
5454    Level: intermediate
5455 
5456 @*/
5457 PetscErrorCode MatNorm(Mat mat,NormType type,PetscReal *nrm)
5458 {
5459   PetscFunctionBegin;
5460   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5461   PetscValidType(mat,1);
5462   PetscValidRealPointer(nrm,3);
5463 
5464   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5465   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5466   PetscCheck(mat->ops->norm,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5467   MatCheckPreallocated(mat,1);
5468 
5469   PetscCall((*mat->ops->norm)(mat,type,nrm));
5470   PetscFunctionReturn(0);
5471 }
5472 
5473 /*
5474      This variable is used to prevent counting of MatAssemblyBegin() that
5475    are called from within a MatAssemblyEnd().
5476 */
5477 static PetscInt MatAssemblyEnd_InUse = 0;
5478 /*@
5479    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5480    be called after completing all calls to MatSetValues().
5481 
5482    Collective on Mat
5483 
5484    Input Parameters:
5485 +  mat - the matrix
5486 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5487 
5488    Notes:
5489    MatSetValues() generally caches the values.  The matrix is ready to
5490    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5491    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5492    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5493    using the matrix.
5494 
5495    ALL processes that share a matrix MUST call MatAssemblyBegin() and MatAssemblyEnd() the SAME NUMBER of times, and each time with the
5496    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
5497    a global collective operation requring all processes that share the matrix.
5498 
5499    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5500    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5501    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5502 
5503    Level: beginner
5504 
5505 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5506 @*/
5507 PetscErrorCode MatAssemblyBegin(Mat mat,MatAssemblyType type)
5508 {
5509   PetscFunctionBegin;
5510   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5511   PetscValidType(mat,1);
5512   MatCheckPreallocated(mat,1);
5513   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5514   if (mat->assembled) {
5515     mat->was_assembled = PETSC_TRUE;
5516     mat->assembled     = PETSC_FALSE;
5517   }
5518 
5519   if (!MatAssemblyEnd_InUse) {
5520     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin,mat,0,0,0));
5521     if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5522     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin,mat,0,0,0));
5523   } else if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5524   PetscFunctionReturn(0);
5525 }
5526 
5527 /*@
5528    MatAssembled - Indicates if a matrix has been assembled and is ready for
5529      use; for example, in matrix-vector product.
5530 
5531    Not Collective
5532 
5533    Input Parameter:
5534 .  mat - the matrix
5535 
5536    Output Parameter:
5537 .  assembled - PETSC_TRUE or PETSC_FALSE
5538 
5539    Level: advanced
5540 
5541 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5542 @*/
5543 PetscErrorCode MatAssembled(Mat mat,PetscBool *assembled)
5544 {
5545   PetscFunctionBegin;
5546   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5547   PetscValidBoolPointer(assembled,2);
5548   *assembled = mat->assembled;
5549   PetscFunctionReturn(0);
5550 }
5551 
5552 /*@
5553    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5554    be called after MatAssemblyBegin().
5555 
5556    Collective on Mat
5557 
5558    Input Parameters:
5559 +  mat - the matrix
5560 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5561 
5562    Options Database Keys:
5563 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatEndAssembly()
5564 .  -mat_view ::ascii_info_detail - Prints more detailed info
5565 .  -mat_view - Prints matrix in ASCII format
5566 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5567 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
5568 .  -display <name> - Sets display name (default is host)
5569 .  -draw_pause <sec> - Sets number of seconds to pause after display
5570 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab)
5571 .  -viewer_socket_machine <machine> - Machine to use for socket
5572 .  -viewer_socket_port <port> - Port number to use for socket
5573 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5574 
5575    Notes:
5576    MatSetValues() generally caches the values.  The matrix is ready to
5577    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5578    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5579    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5580    using the matrix.
5581 
5582    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5583    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5584    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5585 
5586    Level: beginner
5587 
5588 .seealso: `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5589 @*/
5590 PetscErrorCode MatAssemblyEnd(Mat mat,MatAssemblyType type)
5591 {
5592   static PetscInt inassm = 0;
5593   PetscBool       flg    = PETSC_FALSE;
5594 
5595   PetscFunctionBegin;
5596   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5597   PetscValidType(mat,1);
5598 
5599   inassm++;
5600   MatAssemblyEnd_InUse++;
5601   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5602     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd,mat,0,0,0));
5603     if (mat->ops->assemblyend) PetscCall((*mat->ops->assemblyend)(mat,type));
5604     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd,mat,0,0,0));
5605   } else if (mat->ops->assemblyend) PetscCall((*mat->ops->assemblyend)(mat,type));
5606 
5607   /* Flush assembly is not a true assembly */
5608   if (type != MAT_FLUSH_ASSEMBLY) {
5609     mat->num_ass++;
5610     mat->assembled        = PETSC_TRUE;
5611     mat->ass_nonzerostate = mat->nonzerostate;
5612   }
5613 
5614   mat->insertmode = NOT_SET_VALUES;
5615   MatAssemblyEnd_InUse--;
5616   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5617   if (!mat->symmetric_eternal) {
5618     mat->symmetric_set              = PETSC_FALSE;
5619     mat->hermitian_set              = PETSC_FALSE;
5620     mat->structurally_symmetric_set = PETSC_FALSE;
5621   }
5622   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5623     PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5624 
5625     if (mat->checksymmetryonassembly) {
5626       PetscCall(MatIsSymmetric(mat,mat->checksymmetrytol,&flg));
5627       if (flg) {
5628         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5629       } else {
5630         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is not symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5631       }
5632     }
5633     if (mat->nullsp && mat->checknullspaceonassembly) {
5634       PetscCall(MatNullSpaceTest(mat->nullsp,mat,NULL));
5635     }
5636   }
5637   inassm--;
5638   PetscFunctionReturn(0);
5639 }
5640 
5641 /*@
5642    MatSetOption - Sets a parameter option for a matrix. Some options
5643    may be specific to certain storage formats.  Some options
5644    determine how values will be inserted (or added). Sorted,
5645    row-oriented input will generally assemble the fastest. The default
5646    is row-oriented.
5647 
5648    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5649 
5650    Input Parameters:
5651 +  mat - the matrix
5652 .  option - the option, one of those listed below (and possibly others),
5653 -  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5654 
5655   Options Describing Matrix Structure:
5656 +    MAT_SPD - symmetric positive definite
5657 .    MAT_SYMMETRIC - symmetric in terms of both structure and value
5658 .    MAT_HERMITIAN - transpose is the complex conjugation
5659 .    MAT_STRUCTURALLY_SYMMETRIC - symmetric nonzero structure
5660 -    MAT_SYMMETRY_ETERNAL - if you would like the symmetry/Hermitian flag
5661                             you set to be kept with all future use of the matrix
5662                             including after MatAssemblyBegin/End() which could
5663                             potentially change the symmetry structure, i.e. you
5664                             KNOW the matrix will ALWAYS have the property you set.
5665                             Note that setting this flag alone implies nothing about whether the matrix is symmetric/Hermitian;
5666                             the relevant flags must be set independently.
5667 
5668    Options For Use with MatSetValues():
5669    Insert a logically dense subblock, which can be
5670 .    MAT_ROW_ORIENTED - row-oriented (default)
5671 
5672    Note these options reflect the data you pass in with MatSetValues(); it has
5673    nothing to do with how the data is stored internally in the matrix
5674    data structure.
5675 
5676    When (re)assembling a matrix, we can restrict the input for
5677    efficiency/debugging purposes.  These options include
5678 +    MAT_NEW_NONZERO_LOCATIONS - additional insertions will be allowed if they generate a new nonzero (slow)
5679 .    MAT_FORCE_DIAGONAL_ENTRIES - forces diagonal entries to be allocated
5680 .    MAT_IGNORE_OFF_PROC_ENTRIES - drops off-processor entries
5681 .    MAT_NEW_NONZERO_LOCATION_ERR - generates an error for new matrix entry
5682 .    MAT_USE_HASH_TABLE - uses a hash table to speed up matrix assembly
5683 .    MAT_NO_OFF_PROC_ENTRIES - you know each process will only set values for its own rows, will generate an error if
5684         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5685         performance for very large process counts.
5686 -    MAT_SUBSET_OFF_PROC_ENTRIES - you know that the first assembly after setting this flag will set a superset
5687         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5688         functions, instead sending only neighbor messages.
5689 
5690    Notes:
5691    Except for MAT_UNUSED_NONZERO_LOCATION_ERR and  MAT_ROW_ORIENTED all processes that share the matrix must pass the same value in flg!
5692 
5693    Some options are relevant only for particular matrix types and
5694    are thus ignored by others.  Other options are not supported by
5695    certain matrix types and will generate an error message if set.
5696 
5697    If using a Fortran 77 module to compute a matrix, one may need to
5698    use the column-oriented option (or convert to the row-oriented
5699    format).
5700 
5701    MAT_NEW_NONZERO_LOCATIONS set to PETSC_FALSE indicates that any add or insertion
5702    that would generate a new entry in the nonzero structure is instead
5703    ignored.  Thus, if memory has not alredy been allocated for this particular
5704    data, then the insertion is ignored. For dense matrices, in which
5705    the entire array is allocated, no entries are ever ignored.
5706    Set after the first MatAssemblyEnd(). If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5707 
5708    MAT_NEW_NONZERO_LOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5709    that would generate a new entry in the nonzero structure instead produces
5710    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
5711 
5712    MAT_NEW_NONZERO_ALLOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5713    that would generate a new entry that has not been preallocated will
5714    instead produce an error. (Currently supported for AIJ and BAIJ formats
5715    only.) This is a useful flag when debugging matrix memory preallocation.
5716    If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5717 
5718    MAT_IGNORE_OFF_PROC_ENTRIES set to PETSC_TRUE indicates entries destined for
5719    other processors should be dropped, rather than stashed.
5720    This is useful if you know that the "owning" processor is also
5721    always generating the correct matrix entries, so that PETSc need
5722    not transfer duplicate entries generated on another processor.
5723 
5724    MAT_USE_HASH_TABLE indicates that a hash table be used to improve the
5725    searches during matrix assembly. When this flag is set, the hash table
5726    is created during the first Matrix Assembly. This hash table is
5727    used the next time through, during MatSetVaules()/MatSetVaulesBlocked()
5728    to improve the searching of indices. MAT_NEW_NONZERO_LOCATIONS flag
5729    should be used with MAT_USE_HASH_TABLE flag. This option is currently
5730    supported by MATMPIBAIJ format only.
5731 
5732    MAT_KEEP_NONZERO_PATTERN indicates when MatZeroRows() is called the zeroed entries
5733    are kept in the nonzero structure
5734 
5735    MAT_IGNORE_ZERO_ENTRIES - for AIJ/IS matrices this will stop zero values from creating
5736    a zero location in the matrix
5737 
5738    MAT_USE_INODES - indicates using inode version of the code - works with AIJ matrix types
5739 
5740    MAT_NO_OFF_PROC_ZERO_ROWS - you know each process will only zero its own rows. This avoids all reductions in the
5741         zero row routines and thus improves performance for very large process counts.
5742 
5743    MAT_IGNORE_LOWER_TRIANGULAR - For SBAIJ matrices will ignore any insertions you make in the lower triangular
5744         part of the matrix (since they should match the upper triangular part).
5745 
5746    MAT_SORTED_FULL - each process provides exactly its local rows; all column indices for a given row are passed in a
5747                      single call to MatSetValues(), preallocation is perfect, row oriented, INSERT_VALUES is used. Common
5748                      with finite difference schemes with non-periodic boundary conditions.
5749 
5750    Level: intermediate
5751 
5752 .seealso: `MatOption`, `Mat`
5753 
5754 @*/
5755 PetscErrorCode MatSetOption(Mat mat,MatOption op,PetscBool flg)
5756 {
5757   PetscFunctionBegin;
5758   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5759   if (op > 0) {
5760     PetscValidLogicalCollectiveEnum(mat,op,2);
5761     PetscValidLogicalCollectiveBool(mat,flg,3);
5762   }
5763 
5764   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);
5765 
5766   switch (op) {
5767   case MAT_FORCE_DIAGONAL_ENTRIES:
5768     mat->force_diagonals = flg;
5769     PetscFunctionReturn(0);
5770   case MAT_NO_OFF_PROC_ENTRIES:
5771     mat->nooffprocentries = flg;
5772     PetscFunctionReturn(0);
5773   case MAT_SUBSET_OFF_PROC_ENTRIES:
5774     mat->assembly_subset = flg;
5775     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5776 #if !defined(PETSC_HAVE_MPIUNI)
5777       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5778 #endif
5779       mat->stash.first_assembly_done = PETSC_FALSE;
5780     }
5781     PetscFunctionReturn(0);
5782   case MAT_NO_OFF_PROC_ZERO_ROWS:
5783     mat->nooffproczerorows = flg;
5784     PetscFunctionReturn(0);
5785   case MAT_SPD:
5786     mat->spd_set = PETSC_TRUE;
5787     mat->spd     = flg;
5788     if (flg) {
5789       mat->symmetric                  = PETSC_TRUE;
5790       mat->structurally_symmetric     = PETSC_TRUE;
5791       mat->symmetric_set              = PETSC_TRUE;
5792       mat->structurally_symmetric_set = PETSC_TRUE;
5793     }
5794     break;
5795   case MAT_SYMMETRIC:
5796     mat->symmetric = flg;
5797     if (flg) mat->structurally_symmetric = PETSC_TRUE;
5798     mat->symmetric_set              = PETSC_TRUE;
5799     mat->structurally_symmetric_set = flg;
5800 #if !defined(PETSC_USE_COMPLEX)
5801     mat->hermitian     = flg;
5802     mat->hermitian_set = PETSC_TRUE;
5803 #endif
5804     break;
5805   case MAT_HERMITIAN:
5806     mat->hermitian = flg;
5807     if (flg) mat->structurally_symmetric = PETSC_TRUE;
5808     mat->hermitian_set              = PETSC_TRUE;
5809     mat->structurally_symmetric_set = flg;
5810 #if !defined(PETSC_USE_COMPLEX)
5811     mat->symmetric     = flg;
5812     mat->symmetric_set = PETSC_TRUE;
5813 #endif
5814     break;
5815   case MAT_STRUCTURALLY_SYMMETRIC:
5816     mat->structurally_symmetric     = flg;
5817     mat->structurally_symmetric_set = PETSC_TRUE;
5818     break;
5819   case MAT_SYMMETRY_ETERNAL:
5820     mat->symmetric_eternal = flg;
5821     break;
5822   case MAT_STRUCTURE_ONLY:
5823     mat->structure_only = flg;
5824     break;
5825   case MAT_SORTED_FULL:
5826     mat->sortedfull = flg;
5827     break;
5828   default:
5829     break;
5830   }
5831   if (mat->ops->setoption) PetscCall((*mat->ops->setoption)(mat,op,flg));
5832   PetscFunctionReturn(0);
5833 }
5834 
5835 /*@
5836    MatGetOption - Gets a parameter option that has been set for a matrix.
5837 
5838    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5839 
5840    Input Parameters:
5841 +  mat - the matrix
5842 -  option - the option, this only responds to certain options, check the code for which ones
5843 
5844    Output Parameter:
5845 .  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5846 
5847     Notes:
5848     Can only be called after MatSetSizes() and MatSetType() have been set.
5849 
5850    Level: intermediate
5851 
5852 .seealso: `MatOption`, `MatSetOption()`
5853 
5854 @*/
5855 PetscErrorCode MatGetOption(Mat mat,MatOption op,PetscBool *flg)
5856 {
5857   PetscFunctionBegin;
5858   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5859   PetscValidType(mat,1);
5860 
5861   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);
5862   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()");
5863 
5864   switch (op) {
5865   case MAT_NO_OFF_PROC_ENTRIES:
5866     *flg = mat->nooffprocentries;
5867     break;
5868   case MAT_NO_OFF_PROC_ZERO_ROWS:
5869     *flg = mat->nooffproczerorows;
5870     break;
5871   case MAT_SYMMETRIC:
5872     *flg = mat->symmetric;
5873     break;
5874   case MAT_HERMITIAN:
5875     *flg = mat->hermitian;
5876     break;
5877   case MAT_STRUCTURALLY_SYMMETRIC:
5878     *flg = mat->structurally_symmetric;
5879     break;
5880   case MAT_SYMMETRY_ETERNAL:
5881     *flg = mat->symmetric_eternal;
5882     break;
5883   case MAT_SPD:
5884     *flg = mat->spd;
5885     break;
5886   default:
5887     break;
5888   }
5889   PetscFunctionReturn(0);
5890 }
5891 
5892 /*@
5893    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5894    this routine retains the old nonzero structure.
5895 
5896    Logically Collective on Mat
5897 
5898    Input Parameters:
5899 .  mat - the matrix
5900 
5901    Level: intermediate
5902 
5903    Notes:
5904     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.
5905    See the Performance chapter of the users manual for information on preallocating matrices.
5906 
5907 .seealso: `MatZeroRows()`
5908 @*/
5909 PetscErrorCode MatZeroEntries(Mat mat)
5910 {
5911   PetscFunctionBegin;
5912   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5913   PetscValidType(mat,1);
5914   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5915   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");
5916   PetscCheck(mat->ops->zeroentries,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5917   MatCheckPreallocated(mat,1);
5918 
5919   PetscCall(PetscLogEventBegin(MAT_ZeroEntries,mat,0,0,0));
5920   PetscCall((*mat->ops->zeroentries)(mat));
5921   PetscCall(PetscLogEventEnd(MAT_ZeroEntries,mat,0,0,0));
5922   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5923   PetscFunctionReturn(0);
5924 }
5925 
5926 /*@
5927    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5928    of a set of rows and columns of a matrix.
5929 
5930    Collective on Mat
5931 
5932    Input Parameters:
5933 +  mat - the matrix
5934 .  numRows - the number of rows to remove
5935 .  rows - the global row indices
5936 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5937 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5938 -  b - optional vector of right hand side, that will be adjusted by provided solution
5939 
5940    Notes:
5941    This does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5942 
5943    The user can set a value in the diagonal entry (or for the AIJ and
5944    row formats can optionally remove the main diagonal entry from the
5945    nonzero structure as well, by passing 0.0 as the final argument).
5946 
5947    For the parallel case, all processes that share the matrix (i.e.,
5948    those in the communicator used for matrix creation) MUST call this
5949    routine, regardless of whether any rows being zeroed are owned by
5950    them.
5951 
5952    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5953    list only rows local to itself).
5954 
5955    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
5956 
5957    Level: intermediate
5958 
5959 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5960           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5961 @*/
5962 PetscErrorCode MatZeroRowsColumns(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
5963 {
5964   PetscFunctionBegin;
5965   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5966   PetscValidType(mat,1);
5967   if (numRows) PetscValidIntPointer(rows,3);
5968   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5969   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5970   PetscCheck(mat->ops->zerorowscolumns,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5971   MatCheckPreallocated(mat,1);
5972 
5973   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,rows,diag,x,b));
5974   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5975   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5976   PetscFunctionReturn(0);
5977 }
5978 
5979 /*@
5980    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5981    of a set of rows and columns of a matrix.
5982 
5983    Collective on Mat
5984 
5985    Input Parameters:
5986 +  mat - the matrix
5987 .  is - the rows to zero
5988 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5989 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5990 -  b - optional vector of right hand side, that will be adjusted by provided solution
5991 
5992    Notes:
5993    This does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5994 
5995    The user can set a value in the diagonal entry (or for the AIJ and
5996    row formats can optionally remove the main diagonal entry from the
5997    nonzero structure as well, by passing 0.0 as the final argument).
5998 
5999    For the parallel case, all processes that share the matrix (i.e.,
6000    those in the communicator used for matrix creation) MUST call this
6001    routine, regardless of whether any rows being zeroed are owned by
6002    them.
6003 
6004    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6005    list only rows local to itself).
6006 
6007    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
6008 
6009    Level: intermediate
6010 
6011 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6012           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6013 @*/
6014 PetscErrorCode MatZeroRowsColumnsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6015 {
6016   PetscInt       numRows;
6017   const PetscInt *rows;
6018 
6019   PetscFunctionBegin;
6020   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6021   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6022   PetscValidType(mat,1);
6023   PetscValidType(is,2);
6024   PetscCall(ISGetLocalSize(is,&numRows));
6025   PetscCall(ISGetIndices(is,&rows));
6026   PetscCall(MatZeroRowsColumns(mat,numRows,rows,diag,x,b));
6027   PetscCall(ISRestoreIndices(is,&rows));
6028   PetscFunctionReturn(0);
6029 }
6030 
6031 /*@
6032    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6033    of a set of rows of a matrix.
6034 
6035    Collective on Mat
6036 
6037    Input Parameters:
6038 +  mat - the matrix
6039 .  numRows - the number of rows to remove
6040 .  rows - the global row indices
6041 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6042 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6043 -  b - optional vector of right hand side, that will be adjusted by provided solution
6044 
6045    Notes:
6046    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6047    but does not release memory.  For the dense and block diagonal
6048    formats this does not alter the nonzero structure.
6049 
6050    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6051    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6052    merely zeroed.
6053 
6054    The user can set a value in the diagonal entry (or for the AIJ and
6055    row formats can optionally remove the main diagonal entry from the
6056    nonzero structure as well, by passing 0.0 as the final argument).
6057 
6058    For the parallel case, all processes that share the matrix (i.e.,
6059    those in the communicator used for matrix creation) MUST call this
6060    routine, regardless of whether any rows being zeroed are owned by
6061    them.
6062 
6063    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6064    list only rows local to itself).
6065 
6066    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6067    owns that are to be zeroed. This saves a global synchronization in the implementation.
6068 
6069    Level: intermediate
6070 
6071 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6072           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6073 @*/
6074 PetscErrorCode MatZeroRows(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6075 {
6076   PetscFunctionBegin;
6077   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6078   PetscValidType(mat,1);
6079   if (numRows) PetscValidIntPointer(rows,3);
6080   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6081   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6082   PetscCheck(mat->ops->zerorows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6083   MatCheckPreallocated(mat,1);
6084 
6085   PetscCall((*mat->ops->zerorows)(mat,numRows,rows,diag,x,b));
6086   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
6087   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6088   PetscFunctionReturn(0);
6089 }
6090 
6091 /*@
6092    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6093    of a set of rows of a matrix.
6094 
6095    Collective on Mat
6096 
6097    Input Parameters:
6098 +  mat - the matrix
6099 .  is - index set of rows to remove (if NULL then no row is removed)
6100 .  diag - value put in all diagonals of eliminated rows
6101 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6102 -  b - optional vector of right hand side, that will be adjusted by provided solution
6103 
6104    Notes:
6105    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6106    but does not release memory.  For the dense and block diagonal
6107    formats this does not alter the nonzero structure.
6108 
6109    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6110    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6111    merely zeroed.
6112 
6113    The user can set a value in the diagonal entry (or for the AIJ and
6114    row formats can optionally remove the main diagonal entry from the
6115    nonzero structure as well, by passing 0.0 as the final argument).
6116 
6117    For the parallel case, all processes that share the matrix (i.e.,
6118    those in the communicator used for matrix creation) MUST call this
6119    routine, regardless of whether any rows being zeroed are owned by
6120    them.
6121 
6122    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6123    list only rows local to itself).
6124 
6125    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6126    owns that are to be zeroed. This saves a global synchronization in the implementation.
6127 
6128    Level: intermediate
6129 
6130 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6131           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6132 @*/
6133 PetscErrorCode MatZeroRowsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6134 {
6135   PetscInt       numRows = 0;
6136   const PetscInt *rows = NULL;
6137 
6138   PetscFunctionBegin;
6139   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6140   PetscValidType(mat,1);
6141   if (is) {
6142     PetscValidHeaderSpecific(is,IS_CLASSID,2);
6143     PetscCall(ISGetLocalSize(is,&numRows));
6144     PetscCall(ISGetIndices(is,&rows));
6145   }
6146   PetscCall(MatZeroRows(mat,numRows,rows,diag,x,b));
6147   if (is) {
6148     PetscCall(ISRestoreIndices(is,&rows));
6149   }
6150   PetscFunctionReturn(0);
6151 }
6152 
6153 /*@
6154    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6155    of a set of rows of a matrix. These rows must be local to the process.
6156 
6157    Collective on Mat
6158 
6159    Input Parameters:
6160 +  mat - the matrix
6161 .  numRows - the number of rows to remove
6162 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6163 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6164 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6165 -  b - optional vector of right hand side, that will be adjusted by provided solution
6166 
6167    Notes:
6168    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6169    but does not release memory.  For the dense and block diagonal
6170    formats this does not alter the nonzero structure.
6171 
6172    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6173    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6174    merely zeroed.
6175 
6176    The user can set a value in the diagonal entry (or for the AIJ and
6177    row formats can optionally remove the main diagonal entry from the
6178    nonzero structure as well, by passing 0.0 as the final argument).
6179 
6180    For the parallel case, all processes that share the matrix (i.e.,
6181    those in the communicator used for matrix creation) MUST call this
6182    routine, regardless of whether any rows being zeroed are owned by
6183    them.
6184 
6185    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6186    list only rows local to itself).
6187 
6188    The grid coordinates are across the entire grid, not just the local portion
6189 
6190    In Fortran idxm and idxn should be declared as
6191 $     MatStencil idxm(4,m)
6192    and the values inserted using
6193 $    idxm(MatStencil_i,1) = i
6194 $    idxm(MatStencil_j,1) = j
6195 $    idxm(MatStencil_k,1) = k
6196 $    idxm(MatStencil_c,1) = c
6197    etc
6198 
6199    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6200    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6201    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6202    DM_BOUNDARY_PERIODIC boundary type.
6203 
6204    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
6205    a single value per point) you can skip filling those indices.
6206 
6207    Level: intermediate
6208 
6209 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6210           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6211 @*/
6212 PetscErrorCode MatZeroRowsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6213 {
6214   PetscInt       dim     = mat->stencil.dim;
6215   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6216   PetscInt       *dims   = mat->stencil.dims+1;
6217   PetscInt       *starts = mat->stencil.starts;
6218   PetscInt       *dxm    = (PetscInt*) rows;
6219   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6220 
6221   PetscFunctionBegin;
6222   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6223   PetscValidType(mat,1);
6224   if (numRows) PetscValidPointer(rows,3);
6225 
6226   PetscCall(PetscMalloc1(numRows, &jdxm));
6227   for (i = 0; i < numRows; ++i) {
6228     /* Skip unused dimensions (they are ordered k, j, i, c) */
6229     for (j = 0; j < 3-sdim; ++j) dxm++;
6230     /* Local index in X dir */
6231     tmp = *dxm++ - starts[0];
6232     /* Loop over remaining dimensions */
6233     for (j = 0; j < dim-1; ++j) {
6234       /* If nonlocal, set index to be negative */
6235       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6236       /* Update local index */
6237       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6238     }
6239     /* Skip component slot if necessary */
6240     if (mat->stencil.noc) dxm++;
6241     /* Local row number */
6242     if (tmp >= 0) {
6243       jdxm[numNewRows++] = tmp;
6244     }
6245   }
6246   PetscCall(MatZeroRowsLocal(mat,numNewRows,jdxm,diag,x,b));
6247   PetscCall(PetscFree(jdxm));
6248   PetscFunctionReturn(0);
6249 }
6250 
6251 /*@
6252    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6253    of a set of rows and columns of a matrix.
6254 
6255    Collective on Mat
6256 
6257    Input Parameters:
6258 +  mat - the matrix
6259 .  numRows - the number of rows/columns to remove
6260 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6261 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6262 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6263 -  b - optional vector of right hand side, that will be adjusted by provided solution
6264 
6265    Notes:
6266    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6267    but does not release memory.  For the dense and block diagonal
6268    formats this does not alter the nonzero structure.
6269 
6270    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6271    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6272    merely zeroed.
6273 
6274    The user can set a value in the diagonal entry (or for the AIJ and
6275    row formats can optionally remove the main diagonal entry from the
6276    nonzero structure as well, by passing 0.0 as the final argument).
6277 
6278    For the parallel case, all processes that share the matrix (i.e.,
6279    those in the communicator used for matrix creation) MUST call this
6280    routine, regardless of whether any rows being zeroed are owned by
6281    them.
6282 
6283    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6284    list only rows local to itself, but the row/column numbers are given in local numbering).
6285 
6286    The grid coordinates are across the entire grid, not just the local portion
6287 
6288    In Fortran idxm and idxn should be declared as
6289 $     MatStencil idxm(4,m)
6290    and the values inserted using
6291 $    idxm(MatStencil_i,1) = i
6292 $    idxm(MatStencil_j,1) = j
6293 $    idxm(MatStencil_k,1) = k
6294 $    idxm(MatStencil_c,1) = c
6295    etc
6296 
6297    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6298    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6299    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6300    DM_BOUNDARY_PERIODIC boundary type.
6301 
6302    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
6303    a single value per point) you can skip filling those indices.
6304 
6305    Level: intermediate
6306 
6307 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6308           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6309 @*/
6310 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6311 {
6312   PetscInt       dim     = mat->stencil.dim;
6313   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6314   PetscInt       *dims   = mat->stencil.dims+1;
6315   PetscInt       *starts = mat->stencil.starts;
6316   PetscInt       *dxm    = (PetscInt*) rows;
6317   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6318 
6319   PetscFunctionBegin;
6320   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6321   PetscValidType(mat,1);
6322   if (numRows) PetscValidPointer(rows,3);
6323 
6324   PetscCall(PetscMalloc1(numRows, &jdxm));
6325   for (i = 0; i < numRows; ++i) {
6326     /* Skip unused dimensions (they are ordered k, j, i, c) */
6327     for (j = 0; j < 3-sdim; ++j) dxm++;
6328     /* Local index in X dir */
6329     tmp = *dxm++ - starts[0];
6330     /* Loop over remaining dimensions */
6331     for (j = 0; j < dim-1; ++j) {
6332       /* If nonlocal, set index to be negative */
6333       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6334       /* Update local index */
6335       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6336     }
6337     /* Skip component slot if necessary */
6338     if (mat->stencil.noc) dxm++;
6339     /* Local row number */
6340     if (tmp >= 0) {
6341       jdxm[numNewRows++] = tmp;
6342     }
6343   }
6344   PetscCall(MatZeroRowsColumnsLocal(mat,numNewRows,jdxm,diag,x,b));
6345   PetscCall(PetscFree(jdxm));
6346   PetscFunctionReturn(0);
6347 }
6348 
6349 /*@C
6350    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6351    of a set of rows of a matrix; using local numbering of rows.
6352 
6353    Collective on Mat
6354 
6355    Input Parameters:
6356 +  mat - the matrix
6357 .  numRows - the number of rows to remove
6358 .  rows - the local row indices
6359 .  diag - value put in all diagonals of eliminated rows
6360 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6361 -  b - optional vector of right hand side, that will be adjusted by provided solution
6362 
6363    Notes:
6364    Before calling MatZeroRowsLocal(), the user must first set the
6365    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6366 
6367    For the AIJ matrix formats this removes the old nonzero structure,
6368    but does not release memory.  For the dense and block diagonal
6369    formats this does not alter the nonzero structure.
6370 
6371    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6372    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6373    merely zeroed.
6374 
6375    The user can set a value in the diagonal entry (or for the AIJ and
6376    row formats can optionally remove the main diagonal entry from the
6377    nonzero structure as well, by passing 0.0 as the final argument).
6378 
6379    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6380    owns that are to be zeroed. This saves a global synchronization in the implementation.
6381 
6382    Level: intermediate
6383 
6384 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6385           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6386 @*/
6387 PetscErrorCode MatZeroRowsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6388 {
6389   PetscFunctionBegin;
6390   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6391   PetscValidType(mat,1);
6392   if (numRows) PetscValidIntPointer(rows,3);
6393   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6394   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6395   MatCheckPreallocated(mat,1);
6396 
6397   if (mat->ops->zerorowslocal) {
6398     PetscCall((*mat->ops->zerorowslocal)(mat,numRows,rows,diag,x,b));
6399   } else {
6400     IS             is, newis;
6401     const PetscInt *newRows;
6402 
6403     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6404     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6405     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping,is,&newis));
6406     PetscCall(ISGetIndices(newis,&newRows));
6407     PetscCall((*mat->ops->zerorows)(mat,numRows,newRows,diag,x,b));
6408     PetscCall(ISRestoreIndices(newis,&newRows));
6409     PetscCall(ISDestroy(&newis));
6410     PetscCall(ISDestroy(&is));
6411   }
6412   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6413   PetscFunctionReturn(0);
6414 }
6415 
6416 /*@
6417    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6418    of a set of rows of a matrix; using local numbering of rows.
6419 
6420    Collective on Mat
6421 
6422    Input Parameters:
6423 +  mat - the matrix
6424 .  is - index set of rows to remove
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 MatZeroRowsLocalIS(), the user must first set the
6431    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6432 
6433    For the AIJ matrix formats this removes the old nonzero structure,
6434    but does not release memory.  For the dense and block diagonal
6435    formats this does not alter the nonzero structure.
6436 
6437    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6438    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6439    merely zeroed.
6440 
6441    The user can set a value in the diagonal entry (or for the AIJ and
6442    row formats can optionally remove the main diagonal entry from the
6443    nonzero structure as well, by passing 0.0 as the final argument).
6444 
6445    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6446    owns that are to be zeroed. This saves a global synchronization in the implementation.
6447 
6448    Level: intermediate
6449 
6450 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6451           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6452 @*/
6453 PetscErrorCode MatZeroRowsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6454 {
6455   PetscInt       numRows;
6456   const PetscInt *rows;
6457 
6458   PetscFunctionBegin;
6459   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6460   PetscValidType(mat,1);
6461   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6462   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6463   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6464   MatCheckPreallocated(mat,1);
6465 
6466   PetscCall(ISGetLocalSize(is,&numRows));
6467   PetscCall(ISGetIndices(is,&rows));
6468   PetscCall(MatZeroRowsLocal(mat,numRows,rows,diag,x,b));
6469   PetscCall(ISRestoreIndices(is,&rows));
6470   PetscFunctionReturn(0);
6471 }
6472 
6473 /*@
6474    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6475    of a set of rows and columns of a matrix; using local numbering of rows.
6476 
6477    Collective on Mat
6478 
6479    Input Parameters:
6480 +  mat - the matrix
6481 .  numRows - the number of rows to remove
6482 .  rows - the global row indices
6483 .  diag - value put in all diagonals of eliminated rows
6484 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6485 -  b - optional vector of right hand side, that will be adjusted by provided solution
6486 
6487    Notes:
6488    Before calling MatZeroRowsColumnsLocal(), the user must first set the
6489    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6490 
6491    The user can set a value in the diagonal entry (or for the AIJ and
6492    row formats can optionally remove the main diagonal entry from the
6493    nonzero structure as well, by passing 0.0 as the final argument).
6494 
6495    Level: intermediate
6496 
6497 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6498           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6499 @*/
6500 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6501 {
6502   IS             is, newis;
6503   const PetscInt *newRows;
6504 
6505   PetscFunctionBegin;
6506   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6507   PetscValidType(mat,1);
6508   if (numRows) PetscValidIntPointer(rows,3);
6509   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6510   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6511   MatCheckPreallocated(mat,1);
6512 
6513   PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6514   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6515   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping,is,&newis));
6516   PetscCall(ISGetIndices(newis,&newRows));
6517   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,newRows,diag,x,b));
6518   PetscCall(ISRestoreIndices(newis,&newRows));
6519   PetscCall(ISDestroy(&newis));
6520   PetscCall(ISDestroy(&is));
6521   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6522   PetscFunctionReturn(0);
6523 }
6524 
6525 /*@
6526    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6527    of a set of rows and columns of a matrix; using local numbering of rows.
6528 
6529    Collective on Mat
6530 
6531    Input Parameters:
6532 +  mat - the matrix
6533 .  is - index set of rows to remove
6534 .  diag - value put in all diagonals of eliminated rows
6535 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6536 -  b - optional vector of right hand side, that will be adjusted by provided solution
6537 
6538    Notes:
6539    Before calling MatZeroRowsColumnsLocalIS(), the user must first set the
6540    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6541 
6542    The user can set a value in the diagonal entry (or for the AIJ and
6543    row formats can optionally remove the main diagonal entry from the
6544    nonzero structure as well, by passing 0.0 as the final argument).
6545 
6546    Level: intermediate
6547 
6548 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6549           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6550 @*/
6551 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6552 {
6553   PetscInt       numRows;
6554   const PetscInt *rows;
6555 
6556   PetscFunctionBegin;
6557   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6558   PetscValidType(mat,1);
6559   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6560   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6561   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6562   MatCheckPreallocated(mat,1);
6563 
6564   PetscCall(ISGetLocalSize(is,&numRows));
6565   PetscCall(ISGetIndices(is,&rows));
6566   PetscCall(MatZeroRowsColumnsLocal(mat,numRows,rows,diag,x,b));
6567   PetscCall(ISRestoreIndices(is,&rows));
6568   PetscFunctionReturn(0);
6569 }
6570 
6571 /*@C
6572    MatGetSize - Returns the numbers of rows and columns in a matrix.
6573 
6574    Not Collective
6575 
6576    Input Parameter:
6577 .  mat - the matrix
6578 
6579    Output Parameters:
6580 +  m - the number of global rows
6581 -  n - the number of global columns
6582 
6583    Note: both output parameters can be NULL on input.
6584 
6585    Level: beginner
6586 
6587 .seealso: `MatGetLocalSize()`
6588 @*/
6589 PetscErrorCode MatGetSize(Mat mat,PetscInt *m,PetscInt *n)
6590 {
6591   PetscFunctionBegin;
6592   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6593   if (m) *m = mat->rmap->N;
6594   if (n) *n = mat->cmap->N;
6595   PetscFunctionReturn(0);
6596 }
6597 
6598 /*@C
6599    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6600    of a matrix. For all matrices this is the local size of the left and right vectors as returned by MatCreateVecs().
6601 
6602    Not Collective
6603 
6604    Input Parameter:
6605 .  mat - the matrix
6606 
6607    Output Parameters:
6608 +  m - the number of local rows, use `NULL` to not obtain this value
6609 -  n - the number of local columns, use `NULL` to not obtain this value
6610 
6611    Level: beginner
6612 
6613 .seealso: `MatGetSize()`
6614 @*/
6615 PetscErrorCode MatGetLocalSize(Mat mat,PetscInt *m,PetscInt *n)
6616 {
6617   PetscFunctionBegin;
6618   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6619   if (m) PetscValidIntPointer(m,2);
6620   if (n) PetscValidIntPointer(n,3);
6621   if (m) *m = mat->rmap->n;
6622   if (n) *n = mat->cmap->n;
6623   PetscFunctionReturn(0);
6624 }
6625 
6626 /*@C
6627    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6628    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6629 
6630    Not Collective, unless matrix has not been allocated, then collective on Mat
6631 
6632    Input Parameter:
6633 .  mat - the matrix
6634 
6635    Output Parameters:
6636 +  m - the global index of the first local column, use `NULL` to not obtain this value
6637 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6638 
6639    Level: developer
6640 
6641 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6642 
6643 @*/
6644 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat,PetscInt *m,PetscInt *n)
6645 {
6646   PetscFunctionBegin;
6647   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6648   PetscValidType(mat,1);
6649   if (m) PetscValidIntPointer(m,2);
6650   if (n) PetscValidIntPointer(n,3);
6651   MatCheckPreallocated(mat,1);
6652   if (m) *m = mat->cmap->rstart;
6653   if (n) *n = mat->cmap->rend;
6654   PetscFunctionReturn(0);
6655 }
6656 
6657 /*@C
6658    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6659    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
6660    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6661 
6662    Not Collective
6663 
6664    Input Parameter:
6665 .  mat - the matrix
6666 
6667    Output Parameters:
6668 +  m - the global index of the first local row, use `NULL` to not obtain this value
6669 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6670 
6671    Note:
6672   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6673   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6674   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6675 
6676    Level: beginner
6677 
6678 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6679           `PetscLayout`
6680 
6681 @*/
6682 PetscErrorCode MatGetOwnershipRange(Mat mat,PetscInt *m,PetscInt *n)
6683 {
6684   PetscFunctionBegin;
6685   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6686   PetscValidType(mat,1);
6687   if (m) PetscValidIntPointer(m,2);
6688   if (n) PetscValidIntPointer(n,3);
6689   MatCheckPreallocated(mat,1);
6690   if (m) *m = mat->rmap->rstart;
6691   if (n) *n = mat->rmap->rend;
6692   PetscFunctionReturn(0);
6693 }
6694 
6695 /*@C
6696    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6697    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
6698    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6699 
6700    Not Collective, unless matrix has not been allocated, then collective on Mat
6701 
6702    Input Parameters:
6703 .  mat - the matrix
6704 
6705    Output Parameters:
6706 .  ranges - start of each processors portion plus one more than the total length at the end
6707 
6708    Level: beginner
6709 
6710 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6711 
6712 @*/
6713 PetscErrorCode MatGetOwnershipRanges(Mat mat,const PetscInt **ranges)
6714 {
6715   PetscFunctionBegin;
6716   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6717   PetscValidType(mat,1);
6718   MatCheckPreallocated(mat,1);
6719   PetscCall(PetscLayoutGetRanges(mat->rmap,ranges));
6720   PetscFunctionReturn(0);
6721 }
6722 
6723 /*@C
6724    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6725    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6726 
6727    Not Collective, unless matrix has not been allocated, then collective on Mat
6728 
6729    Input Parameters:
6730 .  mat - the matrix
6731 
6732    Output Parameters:
6733 .  ranges - start of each processors portion plus one more then the total length at the end
6734 
6735    Level: beginner
6736 
6737 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6738 
6739 @*/
6740 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat,const PetscInt **ranges)
6741 {
6742   PetscFunctionBegin;
6743   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6744   PetscValidType(mat,1);
6745   MatCheckPreallocated(mat,1);
6746   PetscCall(PetscLayoutGetRanges(mat->cmap,ranges));
6747   PetscFunctionReturn(0);
6748 }
6749 
6750 /*@C
6751    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6752    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6753    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6754 
6755    Not Collective
6756 
6757    Input Parameter:
6758 .  A - matrix
6759 
6760    Output Parameters:
6761 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6762 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6763 
6764    Level: intermediate
6765 
6766 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6767 @*/
6768 PetscErrorCode MatGetOwnershipIS(Mat A,IS *rows,IS *cols)
6769 {
6770   PetscErrorCode (*f)(Mat,IS*,IS*);
6771 
6772   PetscFunctionBegin;
6773   MatCheckPreallocated(A,1);
6774   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatGetOwnershipIS_C",&f));
6775   if (f) {
6776     PetscCall((*f)(A,rows,cols));
6777   } else {   /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6778     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->rmap->n,A->rmap->rstart,1,rows));
6779     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->cmap->N,0,1,cols));
6780   }
6781   PetscFunctionReturn(0);
6782 }
6783 
6784 /*@C
6785    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix.
6786    Uses levels of fill only, not drop tolerance. Use MatLUFactorNumeric()
6787    to complete the factorization.
6788 
6789    Collective on Mat
6790 
6791    Input Parameters:
6792 +  mat - the matrix
6793 .  row - row permutation
6794 .  column - column permutation
6795 -  info - structure containing
6796 $      levels - number of levels of fill.
6797 $      expected fill - as ratio of original fill.
6798 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6799                 missing diagonal entries)
6800 
6801    Output Parameters:
6802 .  fact - new matrix that has been symbolically factored
6803 
6804    Notes:
6805     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
6806 
6807    Most users should employ the simplified KSP interface for linear solvers
6808    instead of working directly with matrix algebra routines such as this.
6809    See, e.g., KSPCreate().
6810 
6811    Level: developer
6812 
6813 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6814           `MatGetOrdering()`, `MatFactorInfo`
6815 
6816     Note: this uses the definition of level of fill as in Y. Saad, 2003
6817 
6818     Developer Note: fortran interface is not autogenerated as the f90
6819     interface definition cannot be generated correctly [due to MatFactorInfo]
6820 
6821    References:
6822 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6823 @*/
6824 PetscErrorCode MatILUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
6825 {
6826   PetscFunctionBegin;
6827   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6828   PetscValidType(mat,2);
6829   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
6830   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
6831   PetscValidPointer(info,5);
6832   PetscValidPointer(fact,1);
6833   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels of fill negative %" PetscInt_FMT,(PetscInt)info->levels);
6834   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6835   if (!fact->ops->ilufactorsymbolic) {
6836     MatSolverType stype;
6837     PetscCall(MatFactorGetSolverType(fact,&stype));
6838     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ILU using solver type %s",((PetscObject)mat)->type_name,stype);
6839   }
6840   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6841   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6842   MatCheckPreallocated(mat,2);
6843 
6844   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic,mat,row,col,0));
6845   PetscCall((fact->ops->ilufactorsymbolic)(fact,mat,row,col,info));
6846   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic,mat,row,col,0));
6847   PetscFunctionReturn(0);
6848 }
6849 
6850 /*@C
6851    MatICCFactorSymbolic - Performs symbolic incomplete
6852    Cholesky factorization for a symmetric matrix.  Use
6853    MatCholeskyFactorNumeric() to complete the factorization.
6854 
6855    Collective on Mat
6856 
6857    Input Parameters:
6858 +  mat - the matrix
6859 .  perm - row and column permutation
6860 -  info - structure containing
6861 $      levels - number of levels of fill.
6862 $      expected fill - as ratio of original fill.
6863 
6864    Output Parameter:
6865 .  fact - the factored matrix
6866 
6867    Notes:
6868    Most users should employ the KSP interface for linear solvers
6869    instead of working directly with matrix algebra routines such as this.
6870    See, e.g., KSPCreate().
6871 
6872    Level: developer
6873 
6874 .seealso: `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6875 
6876     Note: this uses the definition of level of fill as in Y. Saad, 2003
6877 
6878     Developer Note: fortran interface is not autogenerated as the f90
6879     interface definition cannot be generated correctly [due to MatFactorInfo]
6880 
6881    References:
6882 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6883 @*/
6884 PetscErrorCode MatICCFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
6885 {
6886   PetscFunctionBegin;
6887   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6888   PetscValidType(mat,2);
6889   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
6890   PetscValidPointer(info,4);
6891   PetscValidPointer(fact,1);
6892   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6893   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels negative %" PetscInt_FMT,(PetscInt) info->levels);
6894   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6895   if (!(fact)->ops->iccfactorsymbolic) {
6896     MatSolverType stype;
6897     PetscCall(MatFactorGetSolverType(fact,&stype));
6898     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ICC using solver type %s",((PetscObject)mat)->type_name,stype);
6899   }
6900   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6901   MatCheckPreallocated(mat,2);
6902 
6903   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic,mat,perm,0,0));
6904   PetscCall((fact->ops->iccfactorsymbolic)(fact,mat,perm,info));
6905   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic,mat,perm,0,0));
6906   PetscFunctionReturn(0);
6907 }
6908 
6909 /*@C
6910    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6911    points to an array of valid matrices, they may be reused to store the new
6912    submatrices.
6913 
6914    Collective on Mat
6915 
6916    Input Parameters:
6917 +  mat - the matrix
6918 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6919 .  irow, icol - index sets of rows and columns to extract
6920 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6921 
6922    Output Parameter:
6923 .  submat - the array of submatrices
6924 
6925    Notes:
6926    MatCreateSubMatrices() can extract ONLY sequential submatrices
6927    (from both sequential and parallel matrices). Use MatCreateSubMatrix()
6928    to extract a parallel submatrix.
6929 
6930    Some matrix types place restrictions on the row and column
6931    indices, such as that they be sorted or that they be equal to each other.
6932 
6933    The index sets may not have duplicate entries.
6934 
6935    When extracting submatrices from a parallel matrix, each processor can
6936    form a different submatrix by setting the rows and columns of its
6937    individual index sets according to the local submatrix desired.
6938 
6939    When finished using the submatrices, the user should destroy
6940    them with MatDestroySubMatrices().
6941 
6942    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
6943    original matrix has not changed from that last call to MatCreateSubMatrices().
6944 
6945    This routine creates the matrices in submat; you should NOT create them before
6946    calling it. It also allocates the array of matrix pointers submat.
6947 
6948    For BAIJ matrices the index sets must respect the block structure, that is if they
6949    request one row/column in a block, they must request all rows/columns that are in
6950    that block. For example, if the block size is 2 you cannot request just row 0 and
6951    column 0.
6952 
6953    Fortran Note:
6954    The Fortran interface is slightly different from that given below; it
6955    requires one to pass in  as submat a Mat (integer) array of size at least n+1.
6956 
6957    Level: advanced
6958 
6959 .seealso: `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6960 @*/
6961 PetscErrorCode MatCreateSubMatrices(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
6962 {
6963   PetscInt       i;
6964   PetscBool      eq;
6965 
6966   PetscFunctionBegin;
6967   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6968   PetscValidType(mat,1);
6969   if (n) {
6970     PetscValidPointer(irow,3);
6971     for (i=0; i<n; i++) PetscValidHeaderSpecific(irow[i],IS_CLASSID,3);
6972     PetscValidPointer(icol,4);
6973     for (i=0; i<n; i++) PetscValidHeaderSpecific(icol[i],IS_CLASSID,4);
6974   }
6975   PetscValidPointer(submat,6);
6976   if (n && scall == MAT_REUSE_MATRIX) {
6977     PetscValidPointer(*submat,6);
6978     for (i=0; i<n; i++) PetscValidHeaderSpecific((*submat)[i],MAT_CLASSID,6);
6979   }
6980   PetscCheck(mat->ops->createsubmatrices,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6981   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6982   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6983   MatCheckPreallocated(mat,1);
6984   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
6985   PetscCall((*mat->ops->createsubmatrices)(mat,n,irow,icol,scall,submat));
6986   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
6987   for (i=0; i<n; i++) {
6988     (*submat)[i]->factortype = MAT_FACTOR_NONE;  /* in case in place factorization was previously done on submatrix */
6989     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
6990     if (eq) {
6991       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
6992     }
6993 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6994     if (mat->boundtocpu && mat->bindingpropagates) {
6995       PetscCall(MatBindToCPU((*submat)[i],PETSC_TRUE));
6996       PetscCall(MatSetBindingPropagates((*submat)[i],PETSC_TRUE));
6997     }
6998 #endif
6999   }
7000   PetscFunctionReturn(0);
7001 }
7002 
7003 /*@C
7004    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of IS that may live on subcomms).
7005 
7006    Collective on Mat
7007 
7008    Input Parameters:
7009 +  mat - the matrix
7010 .  n   - the number of submatrixes to be extracted
7011 .  irow, icol - index sets of rows and columns to extract
7012 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
7013 
7014    Output Parameter:
7015 .  submat - the array of submatrices
7016 
7017    Level: advanced
7018 
7019 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7020 @*/
7021 PetscErrorCode MatCreateSubMatricesMPI(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
7022 {
7023   PetscInt       i;
7024   PetscBool      eq;
7025 
7026   PetscFunctionBegin;
7027   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7028   PetscValidType(mat,1);
7029   if (n) {
7030     PetscValidPointer(irow,3);
7031     PetscValidHeaderSpecific(*irow,IS_CLASSID,3);
7032     PetscValidPointer(icol,4);
7033     PetscValidHeaderSpecific(*icol,IS_CLASSID,4);
7034   }
7035   PetscValidPointer(submat,6);
7036   if (n && scall == MAT_REUSE_MATRIX) {
7037     PetscValidPointer(*submat,6);
7038     PetscValidHeaderSpecific(**submat,MAT_CLASSID,6);
7039   }
7040   PetscCheck(mat->ops->createsubmatricesmpi,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7041   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7042   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7043   MatCheckPreallocated(mat,1);
7044 
7045   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
7046   PetscCall((*mat->ops->createsubmatricesmpi)(mat,n,irow,icol,scall,submat));
7047   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
7048   for (i=0; i<n; i++) {
7049     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
7050     if (eq) {
7051       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
7052     }
7053   }
7054   PetscFunctionReturn(0);
7055 }
7056 
7057 /*@C
7058    MatDestroyMatrices - Destroys an array of matrices.
7059 
7060    Collective on Mat
7061 
7062    Input Parameters:
7063 +  n - the number of local matrices
7064 -  mat - the matrices (note that this is a pointer to the array of matrices)
7065 
7066    Level: advanced
7067 
7068     Notes:
7069     Frees not only the matrices, but also the array that contains the matrices
7070            In Fortran will not free the array.
7071 
7072 .seealso: `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7073 @*/
7074 PetscErrorCode MatDestroyMatrices(PetscInt n,Mat *mat[])
7075 {
7076   PetscInt       i;
7077 
7078   PetscFunctionBegin;
7079   if (!*mat) PetscFunctionReturn(0);
7080   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7081   PetscValidPointer(mat,2);
7082 
7083   for (i=0; i<n; i++) {
7084     PetscCall(MatDestroy(&(*mat)[i]));
7085   }
7086 
7087   /* memory is allocated even if n = 0 */
7088   PetscCall(PetscFree(*mat));
7089   PetscFunctionReturn(0);
7090 }
7091 
7092 /*@C
7093    MatDestroySubMatrices - Destroys a set of matrices obtained with MatCreateSubMatrices().
7094 
7095    Collective on Mat
7096 
7097    Input Parameters:
7098 +  n - the number of local matrices
7099 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7100                        sequence of MatCreateSubMatrices())
7101 
7102    Level: advanced
7103 
7104     Notes:
7105     Frees not only the matrices, but also the array that contains the matrices
7106            In Fortran will not free the array.
7107 
7108 .seealso: `MatCreateSubMatrices()`
7109 @*/
7110 PetscErrorCode MatDestroySubMatrices(PetscInt n,Mat *mat[])
7111 {
7112   Mat            mat0;
7113 
7114   PetscFunctionBegin;
7115   if (!*mat) PetscFunctionReturn(0);
7116   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7117   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7118   PetscValidPointer(mat,2);
7119 
7120   mat0 = (*mat)[0];
7121   if (mat0 && mat0->ops->destroysubmatrices) {
7122     PetscCall((mat0->ops->destroysubmatrices)(n,mat));
7123   } else {
7124     PetscCall(MatDestroyMatrices(n,mat));
7125   }
7126   PetscFunctionReturn(0);
7127 }
7128 
7129 /*@C
7130    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7131 
7132    Collective on Mat
7133 
7134    Input Parameters:
7135 .  mat - the matrix
7136 
7137    Output Parameter:
7138 .  matstruct - the sequential matrix with the nonzero structure of mat
7139 
7140   Level: intermediate
7141 
7142 .seealso: `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7143 @*/
7144 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat,Mat *matstruct)
7145 {
7146   PetscFunctionBegin;
7147   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7148   PetscValidPointer(matstruct,2);
7149 
7150   PetscValidType(mat,1);
7151   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7152   MatCheckPreallocated(mat,1);
7153 
7154   PetscCheck(mat->ops->getseqnonzerostructure,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)mat)->type_name);
7155   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7156   PetscCall((*mat->ops->getseqnonzerostructure)(mat,matstruct));
7157   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7158   PetscFunctionReturn(0);
7159 }
7160 
7161 /*@C
7162    MatDestroySeqNonzeroStructure - Destroys matrix obtained with MatGetSeqNonzeroStructure().
7163 
7164    Collective on Mat
7165 
7166    Input Parameters:
7167 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7168                        sequence of MatGetSequentialNonzeroStructure())
7169 
7170    Level: advanced
7171 
7172     Notes:
7173     Frees not only the matrices, but also the array that contains the matrices
7174 
7175 .seealso: `MatGetSeqNonzeroStructure()`
7176 @*/
7177 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7178 {
7179   PetscFunctionBegin;
7180   PetscValidPointer(mat,1);
7181   PetscCall(MatDestroy(mat));
7182   PetscFunctionReturn(0);
7183 }
7184 
7185 /*@
7186    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7187    replaces the index sets by larger ones that represent submatrices with
7188    additional overlap.
7189 
7190    Collective on Mat
7191 
7192    Input Parameters:
7193 +  mat - the matrix
7194 .  n   - the number of index sets
7195 .  is  - the array of index sets (these index sets will changed during the call)
7196 -  ov  - the additional overlap requested
7197 
7198    Options Database:
7199 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7200 
7201    Level: developer
7202 
7203    Developer Note:
7204    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.
7205 
7206 .seealso: `MatCreateSubMatrices()`
7207 @*/
7208 PetscErrorCode MatIncreaseOverlap(Mat mat,PetscInt n,IS is[],PetscInt ov)
7209 {
7210   PetscInt       i,bs,cbs;
7211 
7212   PetscFunctionBegin;
7213   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7214   PetscValidType(mat,1);
7215   PetscValidLogicalCollectiveInt(mat,n,2);
7216   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7217   if (n) {
7218     PetscValidPointer(is,3);
7219     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i],IS_CLASSID,3);
7220   }
7221   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7222   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7223   MatCheckPreallocated(mat,1);
7224 
7225   if (!ov || !n) PetscFunctionReturn(0);
7226   PetscCheck(mat->ops->increaseoverlap,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7227   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7228   PetscCall((*mat->ops->increaseoverlap)(mat,n,is,ov));
7229   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7230   PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
7231   if (bs == cbs) {
7232     for (i=0; i<n; i++) {
7233       PetscCall(ISSetBlockSize(is[i],bs));
7234     }
7235   }
7236   PetscFunctionReturn(0);
7237 }
7238 
7239 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat,IS*,PetscInt);
7240 
7241 /*@
7242    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7243    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7244    additional overlap.
7245 
7246    Collective on Mat
7247 
7248    Input Parameters:
7249 +  mat - the matrix
7250 .  n   - the number of index sets
7251 .  is  - the array of index sets (these index sets will changed during the call)
7252 -  ov  - the additional overlap requested
7253 
7254    Options Database:
7255 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7256 
7257    Level: developer
7258 
7259 .seealso: `MatCreateSubMatrices()`
7260 @*/
7261 PetscErrorCode MatIncreaseOverlapSplit(Mat mat,PetscInt n,IS is[],PetscInt ov)
7262 {
7263   PetscInt       i;
7264 
7265   PetscFunctionBegin;
7266   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7267   PetscValidType(mat,1);
7268   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7269   if (n) {
7270     PetscValidPointer(is,3);
7271     PetscValidHeaderSpecific(*is,IS_CLASSID,3);
7272   }
7273   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7274   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7275   MatCheckPreallocated(mat,1);
7276   if (!ov) PetscFunctionReturn(0);
7277   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7278   for (i=0; i<n; i++) {
7279     PetscCall(MatIncreaseOverlapSplit_Single(mat,&is[i],ov));
7280   }
7281   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7282   PetscFunctionReturn(0);
7283 }
7284 
7285 /*@
7286    MatGetBlockSize - Returns the matrix block size.
7287 
7288    Not Collective
7289 
7290    Input Parameter:
7291 .  mat - the matrix
7292 
7293    Output Parameter:
7294 .  bs - block size
7295 
7296    Notes:
7297     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7298 
7299    If the block size has not been set yet this routine returns 1.
7300 
7301    Level: intermediate
7302 
7303 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7304 @*/
7305 PetscErrorCode MatGetBlockSize(Mat mat,PetscInt *bs)
7306 {
7307   PetscFunctionBegin;
7308   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7309   PetscValidIntPointer(bs,2);
7310   *bs = PetscAbs(mat->rmap->bs);
7311   PetscFunctionReturn(0);
7312 }
7313 
7314 /*@
7315    MatGetBlockSizes - Returns the matrix block row and column sizes.
7316 
7317    Not Collective
7318 
7319    Input Parameter:
7320 .  mat - the matrix
7321 
7322    Output Parameters:
7323 +  rbs - row block size
7324 -  cbs - column block size
7325 
7326    Notes:
7327     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7328     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7329 
7330    If a block size has not been set yet this routine returns 1.
7331 
7332    Level: intermediate
7333 
7334 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7335 @*/
7336 PetscErrorCode MatGetBlockSizes(Mat mat,PetscInt *rbs, PetscInt *cbs)
7337 {
7338   PetscFunctionBegin;
7339   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7340   if (rbs) PetscValidIntPointer(rbs,2);
7341   if (cbs) PetscValidIntPointer(cbs,3);
7342   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7343   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7344   PetscFunctionReturn(0);
7345 }
7346 
7347 /*@
7348    MatSetBlockSize - Sets the matrix block size.
7349 
7350    Logically Collective on Mat
7351 
7352    Input Parameters:
7353 +  mat - the matrix
7354 -  bs - block size
7355 
7356    Notes:
7357     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7358     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7359 
7360     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block size
7361     is compatible with the matrix local sizes.
7362 
7363    Level: intermediate
7364 
7365 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7366 @*/
7367 PetscErrorCode MatSetBlockSize(Mat mat,PetscInt bs)
7368 {
7369   PetscFunctionBegin;
7370   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7371   PetscValidLogicalCollectiveInt(mat,bs,2);
7372   PetscCall(MatSetBlockSizes(mat,bs,bs));
7373   PetscFunctionReturn(0);
7374 }
7375 
7376 typedef struct {
7377   PetscInt         n;
7378   IS               *is;
7379   Mat              *mat;
7380   PetscObjectState nonzerostate;
7381   Mat              C;
7382 } EnvelopeData;
7383 
7384 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7385 {
7386   for (PetscInt i=0; i<edata->n; i++) {
7387     PetscCall(ISDestroy(&edata->is[i]));
7388   }
7389   PetscCall(PetscFree(edata->is));
7390   PetscCall(PetscFree(edata));
7391   return 0;
7392 }
7393 
7394 /*
7395    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7396          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7397 
7398    Collective on mat
7399 
7400    Input Parameter:
7401 .  mat - the matrix
7402 
7403    Notes:
7404      There can be zeros within the blocks
7405 
7406      The blocks can overlap between processes, including laying on more than two processes
7407 
7408 */
7409 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7410 {
7411   PetscInt                    n,*sizes,*starts,i = 0,env = 0, tbs = 0, lblocks = 0,rstart,II,ln = 0,cnt = 0,cstart,cend;
7412   PetscInt                    *diag,*odiag,sc;
7413   VecScatter                  scatter;
7414   PetscScalar                 *seqv;
7415   const PetscScalar           *parv;
7416   const PetscInt              *ia,*ja;
7417   PetscBool                   set,flag,done;
7418   Mat                         AA = mat,A;
7419   MPI_Comm                    comm;
7420   PetscMPIInt                 rank,size,tag;
7421   MPI_Status                  status;
7422   PetscContainer              container;
7423   EnvelopeData                *edata;
7424   Vec                         seq,par;
7425   IS                          isglobal;
7426 
7427   PetscFunctionBegin;
7428   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7429   PetscCall(MatIsSymmetricKnown(mat,&set,&flag));
7430   if (!set || !flag) {
7431     /* TOO: only needs nonzero structure of transpose */
7432     PetscCall(MatTranspose(mat,MAT_INITIAL_MATRIX,&AA));
7433     PetscCall(MatAXPY(AA,1.0,mat,DIFFERENT_NONZERO_PATTERN));
7434   }
7435   PetscCall(MatAIJGetLocalMat(AA,&A));
7436   PetscCall(MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7437   PetscCheck(done,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unable to get IJ structure from matrix");
7438 
7439   PetscCall(MatGetLocalSize(mat,&n,NULL));
7440   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag));
7441   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
7442   PetscCallMPI(MPI_Comm_size(comm,&size));
7443   PetscCallMPI(MPI_Comm_rank(comm,&rank));
7444 
7445   PetscCall(PetscMalloc2(n,&sizes,n,&starts));
7446 
7447   if (rank > 0) {
7448     PetscCallMPI(MPI_Recv(&env,1,MPIU_INT,rank-1,tag,comm,&status));
7449     PetscCallMPI(MPI_Recv(&tbs,1,MPIU_INT,rank-1,tag,comm,&status));
7450   }
7451   PetscCall(MatGetOwnershipRange(mat,&rstart,NULL));
7452   for (i=0; i<n; i++) {
7453     env = PetscMax(env,ja[ia[i+1]-1]);
7454     II = rstart + i;
7455     if (env == II) {
7456       starts[lblocks]  = tbs;
7457       sizes[lblocks++] = 1 + II - tbs;
7458       tbs = 1 + II;
7459     }
7460   }
7461   if (rank < size-1) {
7462     PetscCallMPI(MPI_Send(&env,1,MPIU_INT,rank+1,tag,comm));
7463     PetscCallMPI(MPI_Send(&tbs,1,MPIU_INT,rank+1,tag,comm));
7464   }
7465 
7466   PetscCall(MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7467   if (!set || !flag) {
7468     PetscCall(MatDestroy(&AA));
7469   }
7470   PetscCall(MatDestroy(&A));
7471 
7472   PetscCall(PetscNew(&edata));
7473   PetscCall(MatGetNonzeroState(mat,&edata->nonzerostate));
7474   edata->n = lblocks;
7475   /* create IS needed for extracting blocks from the original matrix */
7476   PetscCall(PetscMalloc1(lblocks,&edata->is));
7477   for (PetscInt i=0; i<lblocks; i++) {
7478     PetscCall(ISCreateStride(PETSC_COMM_SELF,sizes[i],starts[i],1,&edata->is[i]));
7479   }
7480 
7481   /* Create the resulting inverse matrix structure with preallocation information */
7482   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&edata->C));
7483   PetscCall(MatSetSizes(edata->C,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
7484   PetscCall(MatSetBlockSizesFromMats(edata->C,mat,mat));
7485   PetscCall(MatSetType(edata->C,MATAIJ));
7486 
7487   /* Communicate the start and end of each row, from each block to the correct rank */
7488   /* TODO: Use PetscSF instead of VecScatter */
7489   for (PetscInt i=0; i<lblocks; i++) ln += sizes[i];
7490   PetscCall(VecCreateSeq(PETSC_COMM_SELF,2*ln,&seq));
7491   PetscCall(VecGetArrayWrite(seq,&seqv));
7492   for (PetscInt i=0; i<lblocks; i++) {
7493     for (PetscInt j=0; j<sizes[i]; j++) {
7494       seqv[cnt]   = starts[i];
7495       seqv[cnt+1] = starts[i] + sizes[i];
7496       cnt += 2;
7497     }
7498   }
7499   PetscCall(VecRestoreArrayWrite(seq,&seqv));
7500   PetscCallMPI(MPI_Scan(&cnt,&sc,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
7501   sc -= cnt;
7502   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat),2*mat->rmap->n,2*mat->rmap->N,&par));
7503   PetscCall(ISCreateStride(PETSC_COMM_SELF,cnt,sc,1,&isglobal));
7504   PetscCall(VecScatterCreate(seq, NULL  ,par, isglobal,&scatter));
7505   PetscCall(ISDestroy(&isglobal));
7506   PetscCall(VecScatterBegin(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7507   PetscCall(VecScatterEnd(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7508   PetscCall(VecScatterDestroy(&scatter));
7509   PetscCall(VecDestroy(&seq));
7510   PetscCall(MatGetOwnershipRangeColumn(mat,&cstart,&cend));
7511   PetscCall(PetscMalloc2(mat->rmap->n,&diag,mat->rmap->n,&odiag));
7512   PetscCall(VecGetArrayRead(par,&parv));
7513   cnt = 0;
7514   PetscCall(MatGetSize(mat,NULL,&n));
7515   for (PetscInt i=0; i<mat->rmap->n; i++) {
7516     PetscInt start,end,d = 0,od = 0;
7517 
7518     start = (PetscInt)PetscRealPart(parv[cnt]);
7519     end   = (PetscInt)PetscRealPart(parv[cnt+1]);
7520     cnt  += 2;
7521 
7522     if (start < cstart) {od += cstart - start + n - cend; d += cend - cstart;}
7523     else if (start < cend) {od += n - cend; d += cend - start;}
7524     else od += n - start;
7525     if (end <= cstart) {od -= cstart - end + n - cend; d -= cend - cstart;}
7526     else if (end < cend) {od -= n - cend; d -= cend - end;}
7527     else od -= n - end;
7528 
7529     odiag[i] = od;
7530     diag[i]  = d;
7531   }
7532   PetscCall(VecRestoreArrayRead(par,&parv));
7533   PetscCall(VecDestroy(&par));
7534   PetscCall(MatXAIJSetPreallocation(edata->C,mat->rmap->bs,diag,odiag,NULL,NULL));
7535   PetscCall(PetscFree2(diag,odiag));
7536   PetscCall(PetscFree2(sizes,starts));
7537 
7538   PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&container));
7539   PetscCall(PetscContainerSetPointer(container,edata));
7540   PetscCall(PetscContainerSetUserDestroy(container,(PetscErrorCode (*)(void*))EnvelopeDataDestroy));
7541   PetscCall(PetscObjectCompose((PetscObject)mat,"EnvelopeData",(PetscObject)container));
7542   PetscCall(PetscObjectDereference((PetscObject)container));
7543   PetscFunctionReturn(0);
7544 }
7545 
7546 /*@
7547   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7548 
7549   Collective on Mat
7550 
7551   Input Parameters:
7552 . A - the matrix
7553 
7554   Output Parameters:
7555 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7556 
7557   Notes:
7558      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7559 
7560   Level: advanced
7561 
7562 .seealso: MatInvertBlockDiagonal(), MatComputeBlockDiagonal()
7563 @*/
7564 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A,MatReuse reuse, Mat *C)
7565 {
7566   PetscContainer    container;
7567   EnvelopeData      *edata;
7568   PetscObjectState  nonzerostate;
7569 
7570   PetscFunctionBegin;
7571   PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7572   if (!container) {
7573     PetscCall(MatComputeVariableBlockEnvelope(A));
7574     PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7575   }
7576   PetscCall(PetscContainerGetPointer(container,(void**)&edata));
7577   PetscCall(MatGetNonzeroState(A,&nonzerostate));
7578   PetscCheck(nonzerostate <= edata->nonzerostate,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Cannot handle changes to matrix nonzero structure");
7579   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"C matrix must be the same as previously output");
7580 
7581   PetscCall(MatCreateSubMatrices(A,edata->n,edata->is,edata->is,MAT_INITIAL_MATRIX,&edata->mat));
7582   *C   = edata->C;
7583 
7584   for (PetscInt i=0; i<edata->n; i++) {
7585     Mat         D;
7586     PetscScalar *dvalues;
7587 
7588     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE,MAT_INITIAL_MATRIX,&D));
7589     PetscCall(MatSetOption(*C,MAT_ROW_ORIENTED,PETSC_FALSE));
7590     PetscCall(MatSeqDenseInvert(D));
7591     PetscCall(MatDenseGetArray(D,&dvalues));
7592     PetscCall(MatSetValuesIS(*C,edata->is[i],edata->is[i],dvalues,INSERT_VALUES));
7593     PetscCall(MatDestroy(&D));
7594   }
7595   PetscCall(MatDestroySubMatrices(edata->n,&edata->mat));
7596   PetscCall(MatAssemblyBegin(*C,MAT_FINAL_ASSEMBLY));
7597   PetscCall(MatAssemblyEnd(*C,MAT_FINAL_ASSEMBLY));
7598   PetscFunctionReturn(0);
7599 }
7600 
7601 /*@
7602    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7603 
7604    Logically Collective on Mat
7605 
7606    Input Parameters:
7607 +  mat - the matrix
7608 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7609 -  bsizes - the block sizes
7610 
7611    Notes:
7612     Currently used by PCVPBJACOBI for AIJ matrices
7613 
7614     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.
7615 
7616    Level: intermediate
7617 
7618 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7619 @*/
7620 PetscErrorCode MatSetVariableBlockSizes(Mat mat,PetscInt nblocks,PetscInt *bsizes)
7621 {
7622   PetscInt       i,ncnt = 0, nlocal;
7623 
7624   PetscFunctionBegin;
7625   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7626   PetscCheck(nblocks >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Number of local blocks must be great than or equal to zero");
7627   PetscCall(MatGetLocalSize(mat,&nlocal,NULL));
7628   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
7629   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);
7630   PetscCall(PetscFree(mat->bsizes));
7631   mat->nblocks = nblocks;
7632   PetscCall(PetscMalloc1(nblocks,&mat->bsizes));
7633   PetscCall(PetscArraycpy(mat->bsizes,bsizes,nblocks));
7634   PetscFunctionReturn(0);
7635 }
7636 
7637 /*@C
7638    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7639 
7640    Logically Collective on Mat
7641 
7642    Input Parameter:
7643 .  mat - the matrix
7644 
7645    Output Parameters:
7646 +  nblocks - the number of blocks on this process
7647 -  bsizes - the block sizes
7648 
7649    Notes: Currently not supported from Fortran
7650 
7651    Level: intermediate
7652 
7653 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7654 @*/
7655 PetscErrorCode MatGetVariableBlockSizes(Mat mat,PetscInt *nblocks,const PetscInt **bsizes)
7656 {
7657   PetscFunctionBegin;
7658   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7659   *nblocks = mat->nblocks;
7660   *bsizes  = mat->bsizes;
7661   PetscFunctionReturn(0);
7662 }
7663 
7664 /*@
7665    MatSetBlockSizes - Sets the matrix block row and column sizes.
7666 
7667    Logically Collective on Mat
7668 
7669    Input Parameters:
7670 +  mat - the matrix
7671 .  rbs - row block size
7672 -  cbs - column block size
7673 
7674    Notes:
7675     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7676     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7677     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7678 
7679     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block sizes
7680     are compatible with the matrix local sizes.
7681 
7682     The row and column block size determine the blocksize of the "row" and "column" vectors returned by MatCreateVecs().
7683 
7684    Level: intermediate
7685 
7686 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7687 @*/
7688 PetscErrorCode MatSetBlockSizes(Mat mat,PetscInt rbs,PetscInt cbs)
7689 {
7690   PetscFunctionBegin;
7691   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7692   PetscValidLogicalCollectiveInt(mat,rbs,2);
7693   PetscValidLogicalCollectiveInt(mat,cbs,3);
7694   if (mat->ops->setblocksizes) PetscCall((*mat->ops->setblocksizes)(mat,rbs,cbs));
7695   if (mat->rmap->refcnt) {
7696     ISLocalToGlobalMapping l2g = NULL;
7697     PetscLayout            nmap = NULL;
7698 
7699     PetscCall(PetscLayoutDuplicate(mat->rmap,&nmap));
7700     if (mat->rmap->mapping) {
7701       PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping,&l2g));
7702     }
7703     PetscCall(PetscLayoutDestroy(&mat->rmap));
7704     mat->rmap = nmap;
7705     mat->rmap->mapping = l2g;
7706   }
7707   if (mat->cmap->refcnt) {
7708     ISLocalToGlobalMapping l2g = NULL;
7709     PetscLayout            nmap = NULL;
7710 
7711     PetscCall(PetscLayoutDuplicate(mat->cmap,&nmap));
7712     if (mat->cmap->mapping) {
7713       PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping,&l2g));
7714     }
7715     PetscCall(PetscLayoutDestroy(&mat->cmap));
7716     mat->cmap = nmap;
7717     mat->cmap->mapping = l2g;
7718   }
7719   PetscCall(PetscLayoutSetBlockSize(mat->rmap,rbs));
7720   PetscCall(PetscLayoutSetBlockSize(mat->cmap,cbs));
7721   PetscFunctionReturn(0);
7722 }
7723 
7724 /*@
7725    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7726 
7727    Logically Collective on Mat
7728 
7729    Input Parameters:
7730 +  mat - the matrix
7731 .  fromRow - matrix from which to copy row block size
7732 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7733 
7734    Level: developer
7735 
7736 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7737 @*/
7738 PetscErrorCode MatSetBlockSizesFromMats(Mat mat,Mat fromRow,Mat fromCol)
7739 {
7740   PetscFunctionBegin;
7741   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7742   PetscValidHeaderSpecific(fromRow,MAT_CLASSID,2);
7743   PetscValidHeaderSpecific(fromCol,MAT_CLASSID,3);
7744   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap,fromRow->rmap->bs));
7745   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap,fromCol->cmap->bs));
7746   PetscFunctionReturn(0);
7747 }
7748 
7749 /*@
7750    MatResidual - Default routine to calculate the residual.
7751 
7752    Collective on Mat
7753 
7754    Input Parameters:
7755 +  mat - the matrix
7756 .  b   - the right-hand-side
7757 -  x   - the approximate solution
7758 
7759    Output Parameter:
7760 .  r - location to store the residual
7761 
7762    Level: developer
7763 
7764 .seealso: `PCMGSetResidual()`
7765 @*/
7766 PetscErrorCode MatResidual(Mat mat,Vec b,Vec x,Vec r)
7767 {
7768   PetscFunctionBegin;
7769   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7770   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
7771   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
7772   PetscValidHeaderSpecific(r,VEC_CLASSID,4);
7773   PetscValidType(mat,1);
7774   MatCheckPreallocated(mat,1);
7775   PetscCall(PetscLogEventBegin(MAT_Residual,mat,0,0,0));
7776   if (!mat->ops->residual) {
7777     PetscCall(MatMult(mat,x,r));
7778     PetscCall(VecAYPX(r,-1.0,b));
7779   } else {
7780     PetscCall((*mat->ops->residual)(mat,b,x,r));
7781   }
7782   PetscCall(PetscLogEventEnd(MAT_Residual,mat,0,0,0));
7783   PetscFunctionReturn(0);
7784 }
7785 
7786 /*@C
7787     MatGetRowIJ - Returns the compressed row storage i and j indices for sequential matrices.
7788 
7789    Collective on Mat
7790 
7791     Input Parameters:
7792 +   mat - the matrix
7793 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7794 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be   symmetrized
7795 -   inodecompressed - PETSC_TRUE or PETSC_FALSE  indicating if the nonzero structure of the
7796                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7797                  always used.
7798 
7799     Output Parameters:
7800 +   n - number of rows in the (possibly compressed) matrix
7801 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7802 .   ja - the column indices
7803 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7804            are responsible for handling the case when done == PETSC_FALSE and ia and ja are not set
7805 
7806     Level: developer
7807 
7808     Notes:
7809     You CANNOT change any of the ia[] or ja[] values.
7810 
7811     Use MatRestoreRowIJ() when you are finished accessing the ia[] and ja[] values.
7812 
7813     Fortran Notes:
7814     In Fortran use
7815 $
7816 $      PetscInt ia(1), ja(1)
7817 $      PetscOffset iia, jja
7818 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7819 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7820 
7821      or
7822 $
7823 $    PetscInt, pointer :: ia(:),ja(:)
7824 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7825 $    ! Access the ith and jth entries via ia(i) and ja(j)
7826 
7827 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7828 @*/
7829 PetscErrorCode MatGetRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7830 {
7831   PetscFunctionBegin;
7832   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7833   PetscValidType(mat,1);
7834   if (n) PetscValidIntPointer(n,5);
7835   if (ia) PetscValidPointer(ia,6);
7836   if (ja) PetscValidPointer(ja,7);
7837   if (done) PetscValidBoolPointer(done,8);
7838   MatCheckPreallocated(mat,1);
7839   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7840   else {
7841     if (done) *done = PETSC_TRUE;
7842     PetscCall(PetscLogEventBegin(MAT_GetRowIJ,mat,0,0,0));
7843     PetscCall((*mat->ops->getrowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7844     PetscCall(PetscLogEventEnd(MAT_GetRowIJ,mat,0,0,0));
7845   }
7846   PetscFunctionReturn(0);
7847 }
7848 
7849 /*@C
7850     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7851 
7852     Collective on Mat
7853 
7854     Input Parameters:
7855 +   mat - the matrix
7856 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7857 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7858                 symmetrized
7859 .   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7860                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7861                  always used.
7862 .   n - number of columns in the (possibly compressed) matrix
7863 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7864 -   ja - the row indices
7865 
7866     Output Parameters:
7867 .   done - PETSC_TRUE or PETSC_FALSE, indicating whether the values have been returned
7868 
7869     Level: developer
7870 
7871 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7872 @*/
7873 PetscErrorCode MatGetColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7874 {
7875   PetscFunctionBegin;
7876   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7877   PetscValidType(mat,1);
7878   PetscValidIntPointer(n,5);
7879   if (ia) PetscValidPointer(ia,6);
7880   if (ja) PetscValidPointer(ja,7);
7881   PetscValidBoolPointer(done,8);
7882   MatCheckPreallocated(mat,1);
7883   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7884   else {
7885     *done = PETSC_TRUE;
7886     PetscCall((*mat->ops->getcolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7887   }
7888   PetscFunctionReturn(0);
7889 }
7890 
7891 /*@C
7892     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with
7893     MatGetRowIJ().
7894 
7895     Collective on Mat
7896 
7897     Input Parameters:
7898 +   mat - the matrix
7899 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7900 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7901                 symmetrized
7902 .   inodecompressed -  PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7903                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7904                  always used.
7905 .   n - size of (possibly compressed) matrix
7906 .   ia - the row pointers
7907 -   ja - the column indices
7908 
7909     Output Parameters:
7910 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7911 
7912     Note:
7913     This routine zeros out n, ia, and ja. This is to prevent accidental
7914     us of the array after it has been restored. If you pass NULL, it will
7915     not zero the pointers.  Use of ia or ja after MatRestoreRowIJ() is invalid.
7916 
7917     Level: developer
7918 
7919 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7920 @*/
7921 PetscErrorCode MatRestoreRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7922 {
7923   PetscFunctionBegin;
7924   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7925   PetscValidType(mat,1);
7926   if (ia) PetscValidPointer(ia,6);
7927   if (ja) PetscValidPointer(ja,7);
7928   if (done) PetscValidBoolPointer(done,8);
7929   MatCheckPreallocated(mat,1);
7930 
7931   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7932   else {
7933     if (done) *done = PETSC_TRUE;
7934     PetscCall((*mat->ops->restorerowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7935     if (n)  *n = 0;
7936     if (ia) *ia = NULL;
7937     if (ja) *ja = NULL;
7938   }
7939   PetscFunctionReturn(0);
7940 }
7941 
7942 /*@C
7943     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with
7944     MatGetColumnIJ().
7945 
7946     Collective on Mat
7947 
7948     Input Parameters:
7949 +   mat - the matrix
7950 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7951 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7952                 symmetrized
7953 -   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7954                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7955                  always used.
7956 
7957     Output Parameters:
7958 +   n - size of (possibly compressed) matrix
7959 .   ia - the column pointers
7960 .   ja - the row indices
7961 -   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7962 
7963     Level: developer
7964 
7965 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7966 @*/
7967 PetscErrorCode MatRestoreColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7968 {
7969   PetscFunctionBegin;
7970   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7971   PetscValidType(mat,1);
7972   if (ia) PetscValidPointer(ia,6);
7973   if (ja) PetscValidPointer(ja,7);
7974   PetscValidBoolPointer(done,8);
7975   MatCheckPreallocated(mat,1);
7976 
7977   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7978   else {
7979     *done = PETSC_TRUE;
7980     PetscCall((*mat->ops->restorecolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7981     if (n)  *n = 0;
7982     if (ia) *ia = NULL;
7983     if (ja) *ja = NULL;
7984   }
7985   PetscFunctionReturn(0);
7986 }
7987 
7988 /*@C
7989     MatColoringPatch -Used inside matrix coloring routines that
7990     use MatGetRowIJ() and/or MatGetColumnIJ().
7991 
7992     Collective on Mat
7993 
7994     Input Parameters:
7995 +   mat - the matrix
7996 .   ncolors - max color value
7997 .   n   - number of entries in colorarray
7998 -   colorarray - array indicating color for each column
7999 
8000     Output Parameters:
8001 .   iscoloring - coloring generated using colorarray information
8002 
8003     Level: developer
8004 
8005 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
8006 
8007 @*/
8008 PetscErrorCode MatColoringPatch(Mat mat,PetscInt ncolors,PetscInt n,ISColoringValue colorarray[],ISColoring *iscoloring)
8009 {
8010   PetscFunctionBegin;
8011   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8012   PetscValidType(mat,1);
8013   PetscValidIntPointer(colorarray,4);
8014   PetscValidPointer(iscoloring,5);
8015   MatCheckPreallocated(mat,1);
8016 
8017   if (!mat->ops->coloringpatch) {
8018     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat),ncolors,n,colorarray,PETSC_OWN_POINTER,iscoloring));
8019   } else {
8020     PetscCall((*mat->ops->coloringpatch)(mat,ncolors,n,colorarray,iscoloring));
8021   }
8022   PetscFunctionReturn(0);
8023 }
8024 
8025 /*@
8026    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8027 
8028    Logically Collective on Mat
8029 
8030    Input Parameter:
8031 .  mat - the factored matrix to be reset
8032 
8033    Notes:
8034    This routine should be used only with factored matrices formed by in-place
8035    factorization via ILU(0) (or by in-place LU factorization for the MATSEQDENSE
8036    format).  This option can save memory, for example, when solving nonlinear
8037    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8038    ILU(0) preconditioner.
8039 
8040    Note that one can specify in-place ILU(0) factorization by calling
8041 .vb
8042      PCType(pc,PCILU);
8043      PCFactorSeUseInPlace(pc);
8044 .ve
8045    or by using the options -pc_type ilu -pc_factor_in_place
8046 
8047    In-place factorization ILU(0) can also be used as a local
8048    solver for the blocks within the block Jacobi or additive Schwarz
8049    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8050    for details on setting local solver options.
8051 
8052    Most users should employ the simplified KSP interface for linear solvers
8053    instead of working directly with matrix algebra routines such as this.
8054    See, e.g., KSPCreate().
8055 
8056    Level: developer
8057 
8058 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8059 
8060 @*/
8061 PetscErrorCode MatSetUnfactored(Mat mat)
8062 {
8063   PetscFunctionBegin;
8064   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8065   PetscValidType(mat,1);
8066   MatCheckPreallocated(mat,1);
8067   mat->factortype = MAT_FACTOR_NONE;
8068   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
8069   PetscCall((*mat->ops->setunfactored)(mat));
8070   PetscFunctionReturn(0);
8071 }
8072 
8073 /*MC
8074     MatDenseGetArrayF90 - Accesses a matrix array from Fortran90.
8075 
8076     Synopsis:
8077     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8078 
8079     Not collective
8080 
8081     Input Parameter:
8082 .   x - matrix
8083 
8084     Output Parameters:
8085 +   xx_v - the Fortran90 pointer to the array
8086 -   ierr - error code
8087 
8088     Example of Usage:
8089 .vb
8090       PetscScalar, pointer xx_v(:,:)
8091       ....
8092       call MatDenseGetArrayF90(x,xx_v,ierr)
8093       a = xx_v(3)
8094       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8095 .ve
8096 
8097     Level: advanced
8098 
8099 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8100 
8101 M*/
8102 
8103 /*MC
8104     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8105     accessed with MatDenseGetArrayF90().
8106 
8107     Synopsis:
8108     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8109 
8110     Not collective
8111 
8112     Input Parameters:
8113 +   x - matrix
8114 -   xx_v - the Fortran90 pointer to the array
8115 
8116     Output Parameter:
8117 .   ierr - error code
8118 
8119     Example of Usage:
8120 .vb
8121        PetscScalar, pointer xx_v(:,:)
8122        ....
8123        call MatDenseGetArrayF90(x,xx_v,ierr)
8124        a = xx_v(3)
8125        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8126 .ve
8127 
8128     Level: advanced
8129 
8130 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8131 
8132 M*/
8133 
8134 /*MC
8135     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran90.
8136 
8137     Synopsis:
8138     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8139 
8140     Not collective
8141 
8142     Input Parameter:
8143 .   x - matrix
8144 
8145     Output Parameters:
8146 +   xx_v - the Fortran90 pointer to the array
8147 -   ierr - error code
8148 
8149     Example of Usage:
8150 .vb
8151       PetscScalar, pointer xx_v(:)
8152       ....
8153       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8154       a = xx_v(3)
8155       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8156 .ve
8157 
8158     Level: advanced
8159 
8160 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8161 
8162 M*/
8163 
8164 /*MC
8165     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8166     accessed with MatSeqAIJGetArrayF90().
8167 
8168     Synopsis:
8169     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8170 
8171     Not collective
8172 
8173     Input Parameters:
8174 +   x - matrix
8175 -   xx_v - the Fortran90 pointer to the array
8176 
8177     Output Parameter:
8178 .   ierr - error code
8179 
8180     Example of Usage:
8181 .vb
8182        PetscScalar, pointer xx_v(:)
8183        ....
8184        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8185        a = xx_v(3)
8186        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8187 .ve
8188 
8189     Level: advanced
8190 
8191 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8192 
8193 M*/
8194 
8195 /*@
8196     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8197                       as the original matrix.
8198 
8199     Collective on Mat
8200 
8201     Input Parameters:
8202 +   mat - the original matrix
8203 .   isrow - parallel IS containing the rows this processor should obtain
8204 .   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.
8205 -   cll - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
8206 
8207     Output Parameter:
8208 .   newmat - the new submatrix, of the same type as the old
8209 
8210     Level: advanced
8211 
8212     Notes:
8213     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8214 
8215     Some matrix types place restrictions on the row and column indices, such
8216     as that they be sorted or that they be equal to each other.
8217 
8218     The index sets may not have duplicate entries.
8219 
8220       The first time this is called you should use a cll of MAT_INITIAL_MATRIX,
8221    the MatCreateSubMatrix() routine will create the newmat for you. Any additional calls
8222    to this routine with a mat of the same nonzero structure and with a call of MAT_REUSE_MATRIX
8223    will reuse the matrix generated the first time.  You should call MatDestroy() on newmat when
8224    you are finished using it.
8225 
8226     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8227     the input matrix.
8228 
8229     If iscol is NULL then all columns are obtained (not supported in Fortran).
8230 
8231    Example usage:
8232    Consider the following 8x8 matrix with 34 non-zero values, that is
8233    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8234    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8235    as follows:
8236 
8237 .vb
8238             1  2  0  |  0  3  0  |  0  4
8239     Proc0   0  5  6  |  7  0  0  |  8  0
8240             9  0 10  | 11  0  0  | 12  0
8241     -------------------------------------
8242            13  0 14  | 15 16 17  |  0  0
8243     Proc1   0 18  0  | 19 20 21  |  0  0
8244             0  0  0  | 22 23  0  | 24  0
8245     -------------------------------------
8246     Proc2  25 26 27  |  0  0 28  | 29  0
8247            30  0  0  | 31 32 33  |  0 34
8248 .ve
8249 
8250     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8251 
8252 .vb
8253             2  0  |  0  3  0  |  0
8254     Proc0   5  6  |  7  0  0  |  8
8255     -------------------------------
8256     Proc1  18  0  | 19 20 21  |  0
8257     -------------------------------
8258     Proc2  26 27  |  0  0 28  | 29
8259             0  0  | 31 32 33  |  0
8260 .ve
8261 
8262 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8263 @*/
8264 PetscErrorCode MatCreateSubMatrix(Mat mat,IS isrow,IS iscol,MatReuse cll,Mat *newmat)
8265 {
8266   PetscMPIInt    size;
8267   Mat            *local;
8268   IS             iscoltmp;
8269   PetscBool      flg;
8270 
8271   PetscFunctionBegin;
8272   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8273   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
8274   if (iscol) PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
8275   PetscValidPointer(newmat,5);
8276   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat,MAT_CLASSID,5);
8277   PetscValidType(mat,1);
8278   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8279   PetscCheck(cll != MAT_IGNORE_MATRIX,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Cannot use MAT_IGNORE_MATRIX");
8280 
8281   MatCheckPreallocated(mat,1);
8282   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8283 
8284   if (!iscol || isrow == iscol) {
8285     PetscBool   stride;
8286     PetscMPIInt grabentirematrix = 0,grab;
8287     PetscCall(PetscObjectTypeCompare((PetscObject)isrow,ISSTRIDE,&stride));
8288     if (stride) {
8289       PetscInt first,step,n,rstart,rend;
8290       PetscCall(ISStrideGetInfo(isrow,&first,&step));
8291       if (step == 1) {
8292         PetscCall(MatGetOwnershipRange(mat,&rstart,&rend));
8293         if (rstart == first) {
8294           PetscCall(ISGetLocalSize(isrow,&n));
8295           if (n == rend-rstart) {
8296             grabentirematrix = 1;
8297           }
8298         }
8299       }
8300     }
8301     PetscCall(MPIU_Allreduce(&grabentirematrix,&grab,1,MPI_INT,MPI_MIN,PetscObjectComm((PetscObject)mat)));
8302     if (grab) {
8303       PetscCall(PetscInfo(mat,"Getting entire matrix as submatrix\n"));
8304       if (cll == MAT_INITIAL_MATRIX) {
8305         *newmat = mat;
8306         PetscCall(PetscObjectReference((PetscObject)mat));
8307       }
8308       PetscFunctionReturn(0);
8309     }
8310   }
8311 
8312   if (!iscol) {
8313     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat),mat->cmap->n,mat->cmap->rstart,1,&iscoltmp));
8314   } else {
8315     iscoltmp = iscol;
8316   }
8317 
8318   /* if original matrix is on just one processor then use submatrix generated */
8319   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8320     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_REUSE_MATRIX,&newmat));
8321     goto setproperties;
8322   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8323     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_INITIAL_MATRIX,&local));
8324     *newmat = *local;
8325     PetscCall(PetscFree(local));
8326     goto setproperties;
8327   } else if (!mat->ops->createsubmatrix) {
8328     /* Create a new matrix type that implements the operation using the full matrix */
8329     PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8330     switch (cll) {
8331     case MAT_INITIAL_MATRIX:
8332       PetscCall(MatCreateSubMatrixVirtual(mat,isrow,iscoltmp,newmat));
8333       break;
8334     case MAT_REUSE_MATRIX:
8335       PetscCall(MatSubMatrixVirtualUpdate(*newmat,mat,isrow,iscoltmp));
8336       break;
8337     default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8338     }
8339     PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8340     goto setproperties;
8341   }
8342 
8343   PetscCheck(mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8344   PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8345   PetscCall((*mat->ops->createsubmatrix)(mat,isrow,iscoltmp,cll,newmat));
8346   PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8347 
8348 setproperties:
8349   PetscCall(ISEqualUnsorted(isrow,iscoltmp,&flg));
8350   if (flg) PetscCall(MatPropagateSymmetryOptions(mat,*newmat));
8351   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8352   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8353   PetscFunctionReturn(0);
8354 }
8355 
8356 /*@
8357    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8358 
8359    Not Collective
8360 
8361    Input Parameters:
8362 +  A - the matrix we wish to propagate options from
8363 -  B - the matrix we wish to propagate options to
8364 
8365    Level: beginner
8366 
8367    Notes: Propagates the options associated to MAT_SYMMETRY_ETERNAL, MAT_STRUCTURALLY_SYMMETRIC, MAT_HERMITIAN, MAT_SPD and MAT_SYMMETRIC
8368 
8369 .seealso: `MatSetOption()`
8370 @*/
8371 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8372 {
8373   PetscFunctionBegin;
8374   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8375   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
8376   if (A->symmetric_eternal) { /* symmetric_eternal does not have a corresponding *set flag */
8377     PetscCall(MatSetOption(B,MAT_SYMMETRY_ETERNAL,A->symmetric_eternal));
8378   }
8379   if (A->structurally_symmetric_set) PetscCall(MatSetOption(B,MAT_STRUCTURALLY_SYMMETRIC,A->structurally_symmetric));
8380   if (A->hermitian_set) PetscCall(MatSetOption(B,MAT_HERMITIAN,A->hermitian));
8381   if (A->spd_set) PetscCall(MatSetOption(B,MAT_SPD,A->spd));
8382   if (A->symmetric_set) PetscCall(MatSetOption(B,MAT_SYMMETRIC,A->symmetric));
8383   PetscFunctionReturn(0);
8384 }
8385 
8386 /*@
8387    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8388    used during the assembly process to store values that belong to
8389    other processors.
8390 
8391    Not Collective
8392 
8393    Input Parameters:
8394 +  mat   - the matrix
8395 .  size  - the initial size of the stash.
8396 -  bsize - the initial size of the block-stash(if used).
8397 
8398    Options Database Keys:
8399 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8400 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8401 
8402    Level: intermediate
8403 
8404    Notes:
8405      The block-stash is used for values set with MatSetValuesBlocked() while
8406      the stash is used for values set with MatSetValues()
8407 
8408      Run with the option -info and look for output of the form
8409      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8410      to determine the appropriate value, MM, to use for size and
8411      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8412      to determine the value, BMM to use for bsize
8413 
8414 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8415 
8416 @*/
8417 PetscErrorCode MatStashSetInitialSize(Mat mat,PetscInt size, PetscInt bsize)
8418 {
8419   PetscFunctionBegin;
8420   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8421   PetscValidType(mat,1);
8422   PetscCall(MatStashSetInitialSize_Private(&mat->stash,size));
8423   PetscCall(MatStashSetInitialSize_Private(&mat->bstash,bsize));
8424   PetscFunctionReturn(0);
8425 }
8426 
8427 /*@
8428    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8429      the matrix
8430 
8431    Neighbor-wise Collective on Mat
8432 
8433    Input Parameters:
8434 +  mat   - the matrix
8435 .  x,y - the vectors
8436 -  w - where the result is stored
8437 
8438    Level: intermediate
8439 
8440    Notes:
8441     w may be the same vector as y.
8442 
8443     This allows one to use either the restriction or interpolation (its transpose)
8444     matrix to do the interpolation
8445 
8446 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8447 
8448 @*/
8449 PetscErrorCode MatInterpolateAdd(Mat A,Vec x,Vec y,Vec w)
8450 {
8451   PetscInt       M,N,Ny;
8452 
8453   PetscFunctionBegin;
8454   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8455   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8456   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8457   PetscValidHeaderSpecific(w,VEC_CLASSID,4);
8458   PetscCall(MatGetSize(A,&M,&N));
8459   PetscCall(VecGetSize(y,&Ny));
8460   if (M == Ny) {
8461     PetscCall(MatMultAdd(A,x,y,w));
8462   } else {
8463     PetscCall(MatMultTransposeAdd(A,x,y,w));
8464   }
8465   PetscFunctionReturn(0);
8466 }
8467 
8468 /*@
8469    MatInterpolate - y = A*x or A'*x depending on the shape of
8470      the matrix
8471 
8472    Neighbor-wise Collective on Mat
8473 
8474    Input Parameters:
8475 +  mat   - the matrix
8476 -  x,y - the vectors
8477 
8478    Level: intermediate
8479 
8480    Notes:
8481     This allows one to use either the restriction or interpolation (its transpose)
8482     matrix to do the interpolation
8483 
8484 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8485 
8486 @*/
8487 PetscErrorCode MatInterpolate(Mat A,Vec x,Vec y)
8488 {
8489   PetscInt       M,N,Ny;
8490 
8491   PetscFunctionBegin;
8492   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8493   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8494   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8495   PetscCall(MatGetSize(A,&M,&N));
8496   PetscCall(VecGetSize(y,&Ny));
8497   if (M == Ny) {
8498     PetscCall(MatMult(A,x,y));
8499   } else {
8500     PetscCall(MatMultTranspose(A,x,y));
8501   }
8502   PetscFunctionReturn(0);
8503 }
8504 
8505 /*@
8506    MatRestrict - y = A*x or A'*x
8507 
8508    Neighbor-wise Collective on Mat
8509 
8510    Input Parameters:
8511 +  mat   - the matrix
8512 -  x,y - the vectors
8513 
8514    Level: intermediate
8515 
8516    Notes:
8517     This allows one to use either the restriction or interpolation (its transpose)
8518     matrix to do the restriction
8519 
8520 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`
8521 
8522 @*/
8523 PetscErrorCode MatRestrict(Mat A,Vec x,Vec y)
8524 {
8525   PetscInt       M,N,Ny;
8526 
8527   PetscFunctionBegin;
8528   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8529   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8530   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8531   PetscCall(MatGetSize(A,&M,&N));
8532   PetscCall(VecGetSize(y,&Ny));
8533   if (M == Ny) {
8534     PetscCall(MatMult(A,x,y));
8535   } else {
8536     PetscCall(MatMultTranspose(A,x,y));
8537   }
8538   PetscFunctionReturn(0);
8539 }
8540 
8541 /*@
8542    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8543 
8544    Neighbor-wise Collective on Mat
8545 
8546    Input Parameters:
8547 +  mat   - the matrix
8548 -  w, x - the input dense matrices
8549 
8550    Output Parameters:
8551 .  y - the output dense matrix
8552 
8553    Level: intermediate
8554 
8555    Notes:
8556     This allows one to use either the restriction or interpolation (its transpose)
8557     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8558     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8559 
8560 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`
8561 
8562 @*/
8563 PetscErrorCode MatMatInterpolateAdd(Mat A,Mat x,Mat w,Mat *y)
8564 {
8565   PetscInt       M,N,Mx,Nx,Mo,My = 0,Ny = 0;
8566   PetscBool      trans = PETSC_TRUE;
8567   MatReuse       reuse = MAT_INITIAL_MATRIX;
8568 
8569   PetscFunctionBegin;
8570   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8571   PetscValidHeaderSpecific(x,MAT_CLASSID,2);
8572   PetscValidType(x,2);
8573   if (w) PetscValidHeaderSpecific(w,MAT_CLASSID,3);
8574   if (*y) PetscValidHeaderSpecific(*y,MAT_CLASSID,4);
8575   PetscCall(MatGetSize(A,&M,&N));
8576   PetscCall(MatGetSize(x,&Mx,&Nx));
8577   if (N == Mx) trans = PETSC_FALSE;
8578   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);
8579   Mo = trans ? N : M;
8580   if (*y) {
8581     PetscCall(MatGetSize(*y,&My,&Ny));
8582     if (Mo == My && Nx == Ny) { reuse = MAT_REUSE_MATRIX; }
8583     else {
8584       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);
8585       PetscCall(MatDestroy(y));
8586     }
8587   }
8588 
8589   if (w && *y == w) { /* this is to minimize changes in PCMG */
8590     PetscBool flg;
8591 
8592     PetscCall(PetscObjectQuery((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject*)&w));
8593     if (w) {
8594       PetscInt My,Ny,Mw,Nw;
8595 
8596       PetscCall(PetscObjectTypeCompare((PetscObject)*y,((PetscObject)w)->type_name,&flg));
8597       PetscCall(MatGetSize(*y,&My,&Ny));
8598       PetscCall(MatGetSize(w,&Mw,&Nw));
8599       if (!flg || My != Mw || Ny != Nw) w = NULL;
8600     }
8601     if (!w) {
8602       PetscCall(MatDuplicate(*y,MAT_COPY_VALUES,&w));
8603       PetscCall(PetscObjectCompose((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject)w));
8604       PetscCall(PetscLogObjectParent((PetscObject)*y,(PetscObject)w));
8605       PetscCall(PetscObjectDereference((PetscObject)w));
8606     } else {
8607       PetscCall(MatCopy(*y,w,UNKNOWN_NONZERO_PATTERN));
8608     }
8609   }
8610   if (!trans) {
8611     PetscCall(MatMatMult(A,x,reuse,PETSC_DEFAULT,y));
8612   } else {
8613     PetscCall(MatTransposeMatMult(A,x,reuse,PETSC_DEFAULT,y));
8614   }
8615   if (w) PetscCall(MatAXPY(*y,1.0,w,UNKNOWN_NONZERO_PATTERN));
8616   PetscFunctionReturn(0);
8617 }
8618 
8619 /*@
8620    MatMatInterpolate - Y = A*X or A'*X
8621 
8622    Neighbor-wise Collective on Mat
8623 
8624    Input Parameters:
8625 +  mat   - the matrix
8626 -  x - the input dense matrix
8627 
8628    Output Parameters:
8629 .  y - the output dense matrix
8630 
8631    Level: intermediate
8632 
8633    Notes:
8634     This allows one to use either the restriction or interpolation (its transpose)
8635     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8636     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8637 
8638 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`
8639 
8640 @*/
8641 PetscErrorCode MatMatInterpolate(Mat A,Mat x,Mat *y)
8642 {
8643   PetscFunctionBegin;
8644   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8645   PetscFunctionReturn(0);
8646 }
8647 
8648 /*@
8649    MatMatRestrict - Y = A*X or A'*X
8650 
8651    Neighbor-wise Collective on Mat
8652 
8653    Input Parameters:
8654 +  mat   - the matrix
8655 -  x - the input dense matrix
8656 
8657    Output Parameters:
8658 .  y - the output dense matrix
8659 
8660    Level: intermediate
8661 
8662    Notes:
8663     This allows one to use either the restriction or interpolation (its transpose)
8664     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8665     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8666 
8667 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`
8668 @*/
8669 PetscErrorCode MatMatRestrict(Mat A,Mat x,Mat *y)
8670 {
8671   PetscFunctionBegin;
8672   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8673   PetscFunctionReturn(0);
8674 }
8675 
8676 /*@
8677    MatGetNullSpace - retrieves the null space of a matrix.
8678 
8679    Logically Collective on Mat
8680 
8681    Input Parameters:
8682 +  mat - the matrix
8683 -  nullsp - the null space object
8684 
8685    Level: developer
8686 
8687 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`
8688 @*/
8689 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8690 {
8691   PetscFunctionBegin;
8692   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8693   PetscValidPointer(nullsp,2);
8694   *nullsp = (mat->symmetric_set && mat->symmetric && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8695   PetscFunctionReturn(0);
8696 }
8697 
8698 /*@
8699    MatSetNullSpace - attaches a null space to a matrix.
8700 
8701    Logically Collective on Mat
8702 
8703    Input Parameters:
8704 +  mat - the matrix
8705 -  nullsp - the null space object
8706 
8707    Level: advanced
8708 
8709    Notes:
8710       This null space is used by the KSP linear solvers to solve singular systems.
8711 
8712       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
8713 
8714       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
8715       to zero but the linear system will still be solved in a least squares sense.
8716 
8717       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8718    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).
8719    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
8720    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
8721    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).
8722    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8723 
8724     If the matrix is known to be symmetric because it is an SBAIJ matrix or one as called MatSetOption(mat,MAT_SYMMETRIC or MAT_SYMMETRIC_ETERNAL,PETSC_TRUE); this
8725     routine also automatically calls MatSetTransposeNullSpace().
8726 
8727     The user should call `MatNullSpaceDestroy()`.
8728 
8729 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8730           `KSPSetPCSide()`
8731 @*/
8732 PetscErrorCode MatSetNullSpace(Mat mat,MatNullSpace nullsp)
8733 {
8734   PetscFunctionBegin;
8735   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8736   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8737   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8738   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8739   mat->nullsp = nullsp;
8740   if (mat->symmetric_set && mat->symmetric) {
8741     PetscCall(MatSetTransposeNullSpace(mat,nullsp));
8742   }
8743   PetscFunctionReturn(0);
8744 }
8745 
8746 /*@
8747    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8748 
8749    Logically Collective on Mat
8750 
8751    Input Parameters:
8752 +  mat - the matrix
8753 -  nullsp - the null space object
8754 
8755    Level: developer
8756 
8757 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8758 @*/
8759 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8760 {
8761   PetscFunctionBegin;
8762   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8763   PetscValidType(mat,1);
8764   PetscValidPointer(nullsp,2);
8765   *nullsp = (mat->symmetric_set && mat->symmetric && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8766   PetscFunctionReturn(0);
8767 }
8768 
8769 /*@
8770    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8771 
8772    Logically Collective on Mat
8773 
8774    Input Parameters:
8775 +  mat - the matrix
8776 -  nullsp - the null space object
8777 
8778    Level: advanced
8779 
8780    Notes:
8781       This allows solving singular linear systems defined by the transpose of the matrix using KSP solvers with left preconditioning.
8782 
8783       See MatSetNullSpace()
8784 
8785 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8786 @*/
8787 PetscErrorCode MatSetTransposeNullSpace(Mat mat,MatNullSpace nullsp)
8788 {
8789   PetscFunctionBegin;
8790   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8791   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8792   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8793   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8794   mat->transnullsp = nullsp;
8795   PetscFunctionReturn(0);
8796 }
8797 
8798 /*@
8799    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8800         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8801 
8802    Logically Collective on Mat
8803 
8804    Input Parameters:
8805 +  mat - the matrix
8806 -  nullsp - the null space object
8807 
8808    Level: advanced
8809 
8810    Notes:
8811       Overwrites any previous near null space that may have been attached
8812 
8813       You can remove the null space by calling this routine with an nullsp of NULL
8814 
8815 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8816 @*/
8817 PetscErrorCode MatSetNearNullSpace(Mat mat,MatNullSpace nullsp)
8818 {
8819   PetscFunctionBegin;
8820   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8821   PetscValidType(mat,1);
8822   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8823   MatCheckPreallocated(mat,1);
8824   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8825   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8826   mat->nearnullsp = nullsp;
8827   PetscFunctionReturn(0);
8828 }
8829 
8830 /*@
8831    MatGetNearNullSpace - Get null space attached with MatSetNearNullSpace()
8832 
8833    Not Collective
8834 
8835    Input Parameter:
8836 .  mat - the matrix
8837 
8838    Output Parameter:
8839 .  nullsp - the null space object, NULL if not set
8840 
8841    Level: developer
8842 
8843 .seealso: `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8844 @*/
8845 PetscErrorCode MatGetNearNullSpace(Mat mat,MatNullSpace *nullsp)
8846 {
8847   PetscFunctionBegin;
8848   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8849   PetscValidType(mat,1);
8850   PetscValidPointer(nullsp,2);
8851   MatCheckPreallocated(mat,1);
8852   *nullsp = mat->nearnullsp;
8853   PetscFunctionReturn(0);
8854 }
8855 
8856 /*@C
8857    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8858 
8859    Collective on Mat
8860 
8861    Input Parameters:
8862 +  mat - the matrix
8863 .  row - row/column permutation
8864 .  fill - expected fill factor >= 1.0
8865 -  level - level of fill, for ICC(k)
8866 
8867    Notes:
8868    Probably really in-place only when level of fill is zero, otherwise allocates
8869    new space to store factored matrix and deletes previous memory.
8870 
8871    Most users should employ the simplified KSP interface for linear solvers
8872    instead of working directly with matrix algebra routines such as this.
8873    See, e.g., KSPCreate().
8874 
8875    Level: developer
8876 
8877 .seealso: `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8878 
8879     Developer Note: fortran interface is not autogenerated as the f90
8880     interface definition cannot be generated correctly [due to MatFactorInfo]
8881 
8882 @*/
8883 PetscErrorCode MatICCFactor(Mat mat,IS row,const MatFactorInfo *info)
8884 {
8885   PetscFunctionBegin;
8886   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8887   PetscValidType(mat,1);
8888   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
8889   PetscValidPointer(info,3);
8890   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
8891   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
8892   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8893   PetscCheck(mat->ops->iccfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8894   MatCheckPreallocated(mat,1);
8895   PetscCall((*mat->ops->iccfactor)(mat,row,info));
8896   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8897   PetscFunctionReturn(0);
8898 }
8899 
8900 /*@
8901    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8902          ghosted ones.
8903 
8904    Not Collective
8905 
8906    Input Parameters:
8907 +  mat - the matrix
8908 -  diag - the diagonal values, including ghost ones
8909 
8910    Level: developer
8911 
8912    Notes:
8913     Works only for MPIAIJ and MPIBAIJ matrices
8914 
8915 .seealso: `MatDiagonalScale()`
8916 @*/
8917 PetscErrorCode MatDiagonalScaleLocal(Mat mat,Vec diag)
8918 {
8919   PetscMPIInt    size;
8920 
8921   PetscFunctionBegin;
8922   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8923   PetscValidHeaderSpecific(diag,VEC_CLASSID,2);
8924   PetscValidType(mat,1);
8925 
8926   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be already assembled");
8927   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
8928   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8929   if (size == 1) {
8930     PetscInt n,m;
8931     PetscCall(VecGetSize(diag,&n));
8932     PetscCall(MatGetSize(mat,NULL,&m));
8933     if (m == n) {
8934       PetscCall(MatDiagonalScale(mat,NULL,diag));
8935     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only supported for sequential matrices when no ghost points/periodic conditions");
8936   } else {
8937     PetscUseMethod(mat,"MatDiagonalScaleLocal_C",(Mat,Vec),(mat,diag));
8938   }
8939   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
8940   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8941   PetscFunctionReturn(0);
8942 }
8943 
8944 /*@
8945    MatGetInertia - Gets the inertia from a factored matrix
8946 
8947    Collective on Mat
8948 
8949    Input Parameter:
8950 .  mat - the matrix
8951 
8952    Output Parameters:
8953 +   nneg - number of negative eigenvalues
8954 .   nzero - number of zero eigenvalues
8955 -   npos - number of positive eigenvalues
8956 
8957    Level: advanced
8958 
8959    Notes:
8960     Matrix must have been factored by MatCholeskyFactor()
8961 
8962 @*/
8963 PetscErrorCode MatGetInertia(Mat mat,PetscInt *nneg,PetscInt *nzero,PetscInt *npos)
8964 {
8965   PetscFunctionBegin;
8966   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8967   PetscValidType(mat,1);
8968   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
8969   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Numeric factor mat is not assembled");
8970   PetscCheck(mat->ops->getinertia,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8971   PetscCall((*mat->ops->getinertia)(mat,nneg,nzero,npos));
8972   PetscFunctionReturn(0);
8973 }
8974 
8975 /* ----------------------------------------------------------------*/
8976 /*@C
8977    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8978 
8979    Neighbor-wise Collective on Mats
8980 
8981    Input Parameters:
8982 +  mat - the factored matrix
8983 -  b - the right-hand-side vectors
8984 
8985    Output Parameter:
8986 .  x - the result vectors
8987 
8988    Notes:
8989    The vectors b and x cannot be the same.  I.e., one cannot
8990    call MatSolves(A,x,x).
8991 
8992    Notes:
8993    Most users should employ the simplified KSP interface for linear solvers
8994    instead of working directly with matrix algebra routines such as this.
8995    See, e.g., KSPCreate().
8996 
8997    Level: developer
8998 
8999 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9000 @*/
9001 PetscErrorCode MatSolves(Mat mat,Vecs b,Vecs x)
9002 {
9003   PetscFunctionBegin;
9004   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9005   PetscValidType(mat,1);
9006   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
9007   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
9008   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
9009 
9010   PetscCheck(mat->ops->solves,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
9011   MatCheckPreallocated(mat,1);
9012   PetscCall(PetscLogEventBegin(MAT_Solves,mat,0,0,0));
9013   PetscCall((*mat->ops->solves)(mat,b,x));
9014   PetscCall(PetscLogEventEnd(MAT_Solves,mat,0,0,0));
9015   PetscFunctionReturn(0);
9016 }
9017 
9018 /*@
9019    MatIsSymmetric - Test whether a matrix is symmetric
9020 
9021    Collective on Mat
9022 
9023    Input Parameters:
9024 +  A - the matrix to test
9025 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9026 
9027    Output Parameters:
9028 .  flg - the result
9029 
9030    Notes:
9031     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
9032 
9033    Level: intermediate
9034 
9035 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`
9036 @*/
9037 PetscErrorCode MatIsSymmetric(Mat A,PetscReal tol,PetscBool *flg)
9038 {
9039   PetscFunctionBegin;
9040   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9041   PetscValidBoolPointer(flg,3);
9042 
9043   if (!A->symmetric_set) {
9044     if (!A->ops->issymmetric) {
9045       MatType mattype;
9046       PetscCall(MatGetType(A,&mattype));
9047       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for symmetric",mattype);
9048     }
9049     PetscCall((*A->ops->issymmetric)(A,tol,flg));
9050     if (!tol) {
9051       PetscCall(MatSetOption(A,MAT_SYMMETRIC,*flg));
9052     }
9053   } else if (A->symmetric) {
9054     *flg = PETSC_TRUE;
9055   } else if (!tol) {
9056     *flg = PETSC_FALSE;
9057   } else {
9058     if (!A->ops->issymmetric) {
9059       MatType mattype;
9060       PetscCall(MatGetType(A,&mattype));
9061       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for symmetric",mattype);
9062     }
9063     PetscCall((*A->ops->issymmetric)(A,tol,flg));
9064   }
9065   PetscFunctionReturn(0);
9066 }
9067 
9068 /*@
9069    MatIsHermitian - Test whether a matrix is Hermitian
9070 
9071    Collective on Mat
9072 
9073    Input Parameters:
9074 +  A - the matrix to test
9075 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9076 
9077    Output Parameters:
9078 .  flg - the result
9079 
9080    Level: intermediate
9081 
9082 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9083           `MatIsSymmetricKnown()`, `MatIsSymmetric()`
9084 @*/
9085 PetscErrorCode MatIsHermitian(Mat A,PetscReal tol,PetscBool *flg)
9086 {
9087   PetscFunctionBegin;
9088   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9089   PetscValidBoolPointer(flg,3);
9090 
9091   if (!A->hermitian_set) {
9092     if (!A->ops->ishermitian) {
9093       MatType mattype;
9094       PetscCall(MatGetType(A,&mattype));
9095       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for hermitian",mattype);
9096     }
9097     PetscCall((*A->ops->ishermitian)(A,tol,flg));
9098     if (!tol) {
9099       PetscCall(MatSetOption(A,MAT_HERMITIAN,*flg));
9100     }
9101   } else if (A->hermitian) {
9102     *flg = PETSC_TRUE;
9103   } else if (!tol) {
9104     *flg = PETSC_FALSE;
9105   } else {
9106     if (!A->ops->ishermitian) {
9107       MatType mattype;
9108       PetscCall(MatGetType(A,&mattype));
9109       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for hermitian",mattype);
9110     }
9111     PetscCall((*A->ops->ishermitian)(A,tol,flg));
9112   }
9113   PetscFunctionReturn(0);
9114 }
9115 
9116 /*@
9117    MatIsSymmetricKnown - Checks the flag on the matrix to see if it is symmetric.
9118 
9119    Not Collective
9120 
9121    Input Parameter:
9122 .  A - the matrix to check
9123 
9124    Output Parameters:
9125 +  set - if the symmetric flag is set (this tells you if the next flag is valid)
9126 -  flg - the result
9127 
9128    Level: advanced
9129 
9130    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsSymmetric()
9131          if you want it explicitly checked
9132 
9133 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9134 @*/
9135 PetscErrorCode MatIsSymmetricKnown(Mat A,PetscBool *set,PetscBool *flg)
9136 {
9137   PetscFunctionBegin;
9138   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9139   PetscValidBoolPointer(set,2);
9140   PetscValidBoolPointer(flg,3);
9141   if (A->symmetric_set) {
9142     *set = PETSC_TRUE;
9143     *flg = A->symmetric;
9144   } else {
9145     *set = PETSC_FALSE;
9146   }
9147   PetscFunctionReturn(0);
9148 }
9149 
9150 /*@
9151    MatIsHermitianKnown - Checks the flag on the matrix to see if it is hermitian.
9152 
9153    Not Collective
9154 
9155    Input Parameter:
9156 .  A - the matrix to check
9157 
9158    Output Parameters:
9159 +  set - if the hermitian flag is set (this tells you if the next flag is valid)
9160 -  flg - the result
9161 
9162    Level: advanced
9163 
9164    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsHermitian()
9165          if you want it explicitly checked
9166 
9167 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9168 @*/
9169 PetscErrorCode MatIsHermitianKnown(Mat A,PetscBool *set,PetscBool *flg)
9170 {
9171   PetscFunctionBegin;
9172   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9173   PetscValidBoolPointer(set,2);
9174   PetscValidBoolPointer(flg,3);
9175   if (A->hermitian_set) {
9176     *set = PETSC_TRUE;
9177     *flg = A->hermitian;
9178   } else {
9179     *set = PETSC_FALSE;
9180   }
9181   PetscFunctionReturn(0);
9182 }
9183 
9184 /*@
9185    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9186 
9187    Collective on Mat
9188 
9189    Input Parameter:
9190 .  A - the matrix to test
9191 
9192    Output Parameters:
9193 .  flg - the result
9194 
9195    Level: intermediate
9196 
9197 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`
9198 @*/
9199 PetscErrorCode MatIsStructurallySymmetric(Mat A,PetscBool *flg)
9200 {
9201   PetscFunctionBegin;
9202   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9203   PetscValidBoolPointer(flg,2);
9204   if (!A->structurally_symmetric_set) {
9205     PetscCheck(A->ops->isstructurallysymmetric,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Matrix of type %s does not support checking for structural symmetric",((PetscObject)A)->type_name);
9206     PetscCall((*A->ops->isstructurallysymmetric)(A,flg));
9207     PetscCall(MatSetOption(A,MAT_STRUCTURALLY_SYMMETRIC,*flg));
9208   } else *flg = A->structurally_symmetric;
9209   PetscFunctionReturn(0);
9210 }
9211 
9212 /*@
9213    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9214        to be communicated to other processors during the MatAssemblyBegin/End() process
9215 
9216     Not collective
9217 
9218    Input Parameter:
9219 .   vec - the vector
9220 
9221    Output Parameters:
9222 +   nstash   - the size of the stash
9223 .   reallocs - the number of additional mallocs incurred.
9224 .   bnstash   - the size of the block stash
9225 -   breallocs - the number of additional mallocs incurred.in the block stash
9226 
9227    Level: advanced
9228 
9229 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9230 
9231 @*/
9232 PetscErrorCode MatStashGetInfo(Mat mat,PetscInt *nstash,PetscInt *reallocs,PetscInt *bnstash,PetscInt *breallocs)
9233 {
9234   PetscFunctionBegin;
9235   PetscCall(MatStashGetInfo_Private(&mat->stash,nstash,reallocs));
9236   PetscCall(MatStashGetInfo_Private(&mat->bstash,bnstash,breallocs));
9237   PetscFunctionReturn(0);
9238 }
9239 
9240 /*@C
9241    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9242      parallel layout
9243 
9244    Collective on Mat
9245 
9246    Input Parameter:
9247 .  mat - the matrix
9248 
9249    Output Parameters:
9250 +   right - (optional) vector that the matrix can be multiplied against
9251 -   left - (optional) vector that the matrix vector product can be stored in
9252 
9253    Notes:
9254     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().
9255 
9256   Notes:
9257     These are new vectors which are not owned by the Mat, they should be destroyed in VecDestroy() when no longer needed
9258 
9259   Level: advanced
9260 
9261 .seealso: `MatCreate()`, `VecDestroy()`
9262 @*/
9263 PetscErrorCode MatCreateVecs(Mat mat,Vec *right,Vec *left)
9264 {
9265   PetscFunctionBegin;
9266   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9267   PetscValidType(mat,1);
9268   if (mat->ops->getvecs) {
9269     PetscCall((*mat->ops->getvecs)(mat,right,left));
9270   } else {
9271     PetscInt rbs,cbs;
9272     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
9273     if (right) {
9274       PetscCheck(mat->cmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for columns not yet setup");
9275       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),right));
9276       PetscCall(VecSetSizes(*right,mat->cmap->n,PETSC_DETERMINE));
9277       PetscCall(VecSetBlockSize(*right,cbs));
9278       PetscCall(VecSetType(*right,mat->defaultvectype));
9279 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9280       if (mat->boundtocpu && mat->bindingpropagates) {
9281         PetscCall(VecSetBindingPropagates(*right,PETSC_TRUE));
9282         PetscCall(VecBindToCPU(*right,PETSC_TRUE));
9283       }
9284 #endif
9285       PetscCall(PetscLayoutReference(mat->cmap,&(*right)->map));
9286     }
9287     if (left) {
9288       PetscCheck(mat->rmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for rows not yet setup");
9289       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),left));
9290       PetscCall(VecSetSizes(*left,mat->rmap->n,PETSC_DETERMINE));
9291       PetscCall(VecSetBlockSize(*left,rbs));
9292       PetscCall(VecSetType(*left,mat->defaultvectype));
9293 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9294       if (mat->boundtocpu && mat->bindingpropagates) {
9295         PetscCall(VecSetBindingPropagates(*left,PETSC_TRUE));
9296         PetscCall(VecBindToCPU(*left,PETSC_TRUE));
9297       }
9298 #endif
9299       PetscCall(PetscLayoutReference(mat->rmap,&(*left)->map));
9300     }
9301   }
9302   PetscFunctionReturn(0);
9303 }
9304 
9305 /*@C
9306    MatFactorInfoInitialize - Initializes a MatFactorInfo data structure
9307      with default values.
9308 
9309    Not Collective
9310 
9311    Input Parameters:
9312 .    info - the MatFactorInfo data structure
9313 
9314    Notes:
9315     The solvers are generally used through the KSP and PC objects, for example
9316           PCLU, PCILU, PCCHOLESKY, PCICC
9317 
9318    Level: developer
9319 
9320 .seealso: `MatFactorInfo`
9321 
9322     Developer Note: fortran interface is not autogenerated as the f90
9323     interface definition cannot be generated correctly [due to MatFactorInfo]
9324 
9325 @*/
9326 
9327 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9328 {
9329   PetscFunctionBegin;
9330   PetscCall(PetscMemzero(info,sizeof(MatFactorInfo)));
9331   PetscFunctionReturn(0);
9332 }
9333 
9334 /*@
9335    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9336 
9337    Collective on Mat
9338 
9339    Input Parameters:
9340 +  mat - the factored matrix
9341 -  is - the index set defining the Schur indices (0-based)
9342 
9343    Notes:
9344     Call MatFactorSolveSchurComplement() or MatFactorSolveSchurComplementTranspose() after this call to solve a Schur complement system.
9345 
9346    You can call MatFactorGetSchurComplement() or MatFactorCreateSchurComplement() after this call.
9347 
9348    Level: developer
9349 
9350 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9351           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`
9352 
9353 @*/
9354 PetscErrorCode MatFactorSetSchurIS(Mat mat,IS is)
9355 {
9356   PetscErrorCode (*f)(Mat,IS);
9357 
9358   PetscFunctionBegin;
9359   PetscValidType(mat,1);
9360   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9361   PetscValidType(is,2);
9362   PetscValidHeaderSpecific(is,IS_CLASSID,2);
9363   PetscCheckSameComm(mat,1,is,2);
9364   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
9365   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorSetSchurIS_C",&f));
9366   PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9367   PetscCall(MatDestroy(&mat->schur));
9368   PetscCall((*f)(mat,is));
9369   PetscCheck(mat->schur,PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Schur complement has not been created");
9370   PetscFunctionReturn(0);
9371 }
9372 
9373 /*@
9374   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9375 
9376    Logically Collective on Mat
9377 
9378    Input Parameters:
9379 +  F - the factored matrix obtained by calling MatGetFactor() from PETSc-MUMPS interface
9380 .  S - location where to return the Schur complement, can be NULL
9381 -  status - the status of the Schur complement matrix, can be NULL
9382 
9383    Notes:
9384    You must call MatFactorSetSchurIS() before calling this routine.
9385 
9386    The routine provides a copy of the Schur matrix stored within the solver data structures.
9387    The caller must destroy the object when it is no longer needed.
9388    If MatFactorInvertSchurComplement() has been called, the routine gets back the inverse.
9389 
9390    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)
9391 
9392    Developer Notes:
9393     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9394    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9395 
9396    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9397 
9398    Level: advanced
9399 
9400    References:
9401 
9402 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`
9403 @*/
9404 PetscErrorCode MatFactorCreateSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9405 {
9406   PetscFunctionBegin;
9407   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9408   if (S) PetscValidPointer(S,2);
9409   if (status) PetscValidPointer(status,3);
9410   if (S) {
9411     PetscErrorCode (*f)(Mat,Mat*);
9412 
9413     PetscCall(PetscObjectQueryFunction((PetscObject)F,"MatFactorCreateSchurComplement_C",&f));
9414     if (f) {
9415       PetscCall((*f)(F,S));
9416     } else {
9417       PetscCall(MatDuplicate(F->schur,MAT_COPY_VALUES,S));
9418     }
9419   }
9420   if (status) *status = F->schur_status;
9421   PetscFunctionReturn(0);
9422 }
9423 
9424 /*@
9425   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9426 
9427    Logically Collective on Mat
9428 
9429    Input Parameters:
9430 +  F - the factored matrix obtained by calling MatGetFactor()
9431 .  *S - location where to return the Schur complement, can be NULL
9432 -  status - the status of the Schur complement matrix, can be NULL
9433 
9434    Notes:
9435    You must call MatFactorSetSchurIS() before calling this routine.
9436 
9437    Schur complement mode is currently implemented for sequential matrices.
9438    The routine returns a the Schur Complement stored within the data strutures of the solver.
9439    If MatFactorInvertSchurComplement() has previously been called, the returned matrix is actually the inverse of the Schur complement.
9440    The returned matrix should not be destroyed; the caller should call MatFactorRestoreSchurComplement() when the object is no longer needed.
9441 
9442    Use MatFactorCreateSchurComplement() to create a copy of the Schur complement matrix that is within a factored matrix
9443 
9444    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9445 
9446    Level: advanced
9447 
9448    References:
9449 
9450 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9451 @*/
9452 PetscErrorCode MatFactorGetSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9453 {
9454   PetscFunctionBegin;
9455   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9456   if (S) PetscValidPointer(S,2);
9457   if (status) PetscValidPointer(status,3);
9458   if (S) *S = F->schur;
9459   if (status) *status = F->schur_status;
9460   PetscFunctionReturn(0);
9461 }
9462 
9463 /*@
9464   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to MatFactorGetSchurComplement
9465 
9466    Logically Collective on Mat
9467 
9468    Input Parameters:
9469 +  F - the factored matrix obtained by calling MatGetFactor()
9470 .  *S - location where the Schur complement is stored
9471 -  status - the status of the Schur complement matrix (see MatFactorSchurStatus)
9472 
9473    Notes:
9474 
9475    Level: advanced
9476 
9477    References:
9478 
9479 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9480 @*/
9481 PetscErrorCode MatFactorRestoreSchurComplement(Mat F,Mat* S,MatFactorSchurStatus status)
9482 {
9483   PetscFunctionBegin;
9484   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9485   if (S) {
9486     PetscValidHeaderSpecific(*S,MAT_CLASSID,2);
9487     *S = NULL;
9488   }
9489   F->schur_status = status;
9490   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9491   PetscFunctionReturn(0);
9492 }
9493 
9494 /*@
9495   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9496 
9497    Logically Collective on Mat
9498 
9499    Input Parameters:
9500 +  F - the factored matrix obtained by calling MatGetFactor()
9501 .  rhs - location where the right hand side of the Schur complement system is stored
9502 -  sol - location where the solution of the Schur complement system has to be returned
9503 
9504    Notes:
9505    The sizes of the vectors should match the size of the Schur complement
9506 
9507    Must be called after MatFactorSetSchurIS()
9508 
9509    Level: advanced
9510 
9511    References:
9512 
9513 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9514 @*/
9515 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9516 {
9517   PetscFunctionBegin;
9518   PetscValidType(F,1);
9519   PetscValidType(rhs,2);
9520   PetscValidType(sol,3);
9521   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9522   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9523   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9524   PetscCheckSameComm(F,1,rhs,2);
9525   PetscCheckSameComm(F,1,sol,3);
9526   PetscCall(MatFactorFactorizeSchurComplement(F));
9527   switch (F->schur_status) {
9528   case MAT_FACTOR_SCHUR_FACTORED:
9529     PetscCall(MatSolveTranspose(F->schur,rhs,sol));
9530     break;
9531   case MAT_FACTOR_SCHUR_INVERTED:
9532     PetscCall(MatMultTranspose(F->schur,rhs,sol));
9533     break;
9534   default:
9535     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9536   }
9537   PetscFunctionReturn(0);
9538 }
9539 
9540 /*@
9541   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9542 
9543    Logically Collective on Mat
9544 
9545    Input Parameters:
9546 +  F - the factored matrix obtained by calling MatGetFactor()
9547 .  rhs - location where the right hand side of the Schur complement system is stored
9548 -  sol - location where the solution of the Schur complement system has to be returned
9549 
9550    Notes:
9551    The sizes of the vectors should match the size of the Schur complement
9552 
9553    Must be called after MatFactorSetSchurIS()
9554 
9555    Level: advanced
9556 
9557    References:
9558 
9559 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9560 @*/
9561 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9562 {
9563   PetscFunctionBegin;
9564   PetscValidType(F,1);
9565   PetscValidType(rhs,2);
9566   PetscValidType(sol,3);
9567   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9568   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9569   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9570   PetscCheckSameComm(F,1,rhs,2);
9571   PetscCheckSameComm(F,1,sol,3);
9572   PetscCall(MatFactorFactorizeSchurComplement(F));
9573   switch (F->schur_status) {
9574   case MAT_FACTOR_SCHUR_FACTORED:
9575     PetscCall(MatSolve(F->schur,rhs,sol));
9576     break;
9577   case MAT_FACTOR_SCHUR_INVERTED:
9578     PetscCall(MatMult(F->schur,rhs,sol));
9579     break;
9580   default:
9581     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9582   }
9583   PetscFunctionReturn(0);
9584 }
9585 
9586 /*@
9587   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9588 
9589    Logically Collective on Mat
9590 
9591    Input Parameters:
9592 .  F - the factored matrix obtained by calling MatGetFactor()
9593 
9594    Notes:
9595     Must be called after MatFactorSetSchurIS().
9596 
9597    Call MatFactorGetSchurComplement() or  MatFactorCreateSchurComplement() AFTER this call to actually compute the inverse and get access to it.
9598 
9599    Level: advanced
9600 
9601    References:
9602 
9603 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9604 @*/
9605 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9606 {
9607   PetscFunctionBegin;
9608   PetscValidType(F,1);
9609   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9610   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9611   PetscCall(MatFactorFactorizeSchurComplement(F));
9612   PetscCall(MatFactorInvertSchurComplement_Private(F));
9613   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9614   PetscFunctionReturn(0);
9615 }
9616 
9617 /*@
9618   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9619 
9620    Logically Collective on Mat
9621 
9622    Input Parameters:
9623 .  F - the factored matrix obtained by calling MatGetFactor()
9624 
9625    Notes:
9626     Must be called after MatFactorSetSchurIS().
9627 
9628    Level: advanced
9629 
9630    References:
9631 
9632 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9633 @*/
9634 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9635 {
9636   PetscFunctionBegin;
9637   PetscValidType(F,1);
9638   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9639   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9640   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9641   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9642   PetscFunctionReturn(0);
9643 }
9644 
9645 /*@
9646    MatPtAP - Creates the matrix product C = P^T * A * P
9647 
9648    Neighbor-wise Collective on Mat
9649 
9650    Input Parameters:
9651 +  A - the matrix
9652 .  P - the projection matrix
9653 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9654 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use PETSC_DEFAULT if you do not have a good estimate
9655           if the result is a dense matrix this is irrelevant
9656 
9657    Output Parameters:
9658 .  C - the product matrix
9659 
9660    Notes:
9661    C will be created and must be destroyed by the user with MatDestroy().
9662 
9663    For matrix types without special implementation the function fallbacks to MatMatMult() followed by MatTransposeMatMult().
9664 
9665    Level: intermediate
9666 
9667 .seealso: `MatMatMult()`, `MatRARt()`
9668 @*/
9669 PetscErrorCode MatPtAP(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
9670 {
9671   PetscFunctionBegin;
9672   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9673   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9674 
9675   if (scall == MAT_INITIAL_MATRIX) {
9676     PetscCall(MatProductCreate(A,P,NULL,C));
9677     PetscCall(MatProductSetType(*C,MATPRODUCT_PtAP));
9678     PetscCall(MatProductSetAlgorithm(*C,"default"));
9679     PetscCall(MatProductSetFill(*C,fill));
9680 
9681     (*C)->product->api_user = PETSC_TRUE;
9682     PetscCall(MatProductSetFromOptions(*C));
9683     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);
9684     PetscCall(MatProductSymbolic(*C));
9685   } else { /* scall == MAT_REUSE_MATRIX */
9686     PetscCall(MatProductReplaceMats(A,P,NULL,*C));
9687   }
9688 
9689   PetscCall(MatProductNumeric(*C));
9690   if (A->symmetric) {
9691     if (A->spd) {
9692       PetscCall(MatSetOption(*C,MAT_SPD,PETSC_TRUE));
9693     } else {
9694       PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9695     }
9696   }
9697   PetscFunctionReturn(0);
9698 }
9699 
9700 /*@
9701    MatRARt - Creates the matrix product C = R * A * R^T
9702 
9703    Neighbor-wise Collective on Mat
9704 
9705    Input Parameters:
9706 +  A - the matrix
9707 .  R - the projection matrix
9708 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9709 -  fill - expected fill as ratio of nnz(C)/nnz(A), use PETSC_DEFAULT if you do not have a good estimate
9710           if the result is a dense matrix this is irrelevant
9711 
9712    Output Parameters:
9713 .  C - the product matrix
9714 
9715    Notes:
9716    C will be created and must be destroyed by the user with MatDestroy().
9717 
9718    This routine is currently only implemented for pairs of AIJ matrices and classes
9719    which inherit from AIJ. Due to PETSc sparse matrix block row distribution among processes,
9720    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9721    We recommend using MatPtAP().
9722 
9723    Level: intermediate
9724 
9725 .seealso: `MatMatMult()`, `MatPtAP()`
9726 @*/
9727 PetscErrorCode MatRARt(Mat A,Mat R,MatReuse scall,PetscReal fill,Mat *C)
9728 {
9729   PetscFunctionBegin;
9730   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9731   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9732 
9733   if (scall == MAT_INITIAL_MATRIX) {
9734     PetscCall(MatProductCreate(A,R,NULL,C));
9735     PetscCall(MatProductSetType(*C,MATPRODUCT_RARt));
9736     PetscCall(MatProductSetAlgorithm(*C,"default"));
9737     PetscCall(MatProductSetFill(*C,fill));
9738 
9739     (*C)->product->api_user = PETSC_TRUE;
9740     PetscCall(MatProductSetFromOptions(*C));
9741     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);
9742     PetscCall(MatProductSymbolic(*C));
9743   } else { /* scall == MAT_REUSE_MATRIX */
9744     PetscCall(MatProductReplaceMats(A,R,NULL,*C));
9745   }
9746 
9747   PetscCall(MatProductNumeric(*C));
9748   if (A->symmetric_set && A->symmetric) {
9749     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9750   }
9751   PetscFunctionReturn(0);
9752 }
9753 
9754 static PetscErrorCode MatProduct_Private(Mat A,Mat B,MatReuse scall,PetscReal fill,MatProductType ptype, Mat *C)
9755 {
9756   PetscFunctionBegin;
9757   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9758 
9759   if (scall == MAT_INITIAL_MATRIX) {
9760     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n",MatProductTypes[ptype]));
9761     PetscCall(MatProductCreate(A,B,NULL,C));
9762     PetscCall(MatProductSetType(*C,ptype));
9763     PetscCall(MatProductSetAlgorithm(*C,MATPRODUCTALGORITHMDEFAULT));
9764     PetscCall(MatProductSetFill(*C,fill));
9765 
9766     (*C)->product->api_user = PETSC_TRUE;
9767     PetscCall(MatProductSetFromOptions(*C));
9768     PetscCall(MatProductSymbolic(*C));
9769   } else { /* scall == MAT_REUSE_MATRIX */
9770     Mat_Product *product = (*C)->product;
9771     PetscBool isdense;
9772 
9773     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C),&isdense,MATSEQDENSE,MATMPIDENSE,""));
9774     if (isdense && product && product->type != ptype) {
9775       PetscCall(MatProductClear(*C));
9776       product = NULL;
9777     }
9778     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n",product ? "with" : "without",MatProductTypes[ptype]));
9779     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9780       if (isdense) {
9781         PetscCall(MatProductCreate_Private(A,B,NULL,*C));
9782         product = (*C)->product;
9783         product->fill     = fill;
9784         product->api_user = PETSC_TRUE;
9785         product->clear    = PETSC_TRUE;
9786 
9787         PetscCall(MatProductSetType(*C,ptype));
9788         PetscCall(MatProductSetFromOptions(*C));
9789         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);
9790         PetscCall(MatProductSymbolic(*C));
9791       } else SETERRQ(PetscObjectComm((PetscObject)(*C)),PETSC_ERR_SUP,"Call MatProductCreate() first");
9792     } else { /* user may change input matrices A or B when REUSE */
9793       PetscCall(MatProductReplaceMats(A,B,NULL,*C));
9794     }
9795   }
9796   PetscCall(MatProductNumeric(*C));
9797   PetscFunctionReturn(0);
9798 }
9799 
9800 /*@
9801    MatMatMult - Performs Matrix-Matrix Multiplication C=A*B.
9802 
9803    Neighbor-wise Collective on Mat
9804 
9805    Input Parameters:
9806 +  A - the left matrix
9807 .  B - the right matrix
9808 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9809 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if you do not have a good estimate
9810           if the result is a dense matrix this is irrelevant
9811 
9812    Output Parameters:
9813 .  C - the product matrix
9814 
9815    Notes:
9816    Unless scall is MAT_REUSE_MATRIX C will be created.
9817 
9818    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
9819    call to this function with MAT_INITIAL_MATRIX.
9820 
9821    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9822 
9823    If you have many matrices with the same non-zero structure to multiply, you should use MatProductCreate()/MatProductSymbolic()/MatProductReplaceMats(), and call MatProductNumeric() repeatedly.
9824 
9825    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.
9826 
9827    Example of Usage:
9828 .vb
9829      MatProductCreate(A,B,NULL,&C);
9830      MatProductSetType(C,MATPRODUCT_AB);
9831      MatProductSymbolic(C);
9832      MatProductNumeric(C); // compute C=A * B
9833      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9834      MatProductNumeric(C);
9835      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9836      MatProductNumeric(C);
9837 .ve
9838 
9839    Level: intermediate
9840 
9841 .seealso: `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9842 @*/
9843 PetscErrorCode MatMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9844 {
9845   PetscFunctionBegin;
9846   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AB,C));
9847   PetscFunctionReturn(0);
9848 }
9849 
9850 /*@
9851    MatMatTransposeMult - Performs Matrix-Matrix Multiplication C=A*B^T.
9852 
9853    Neighbor-wise Collective on Mat
9854 
9855    Input Parameters:
9856 +  A - the left matrix
9857 .  B - the right matrix
9858 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9859 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9860 
9861    Output Parameters:
9862 .  C - the product matrix
9863 
9864    Notes:
9865    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9866 
9867    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9868 
9869   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9870    actually needed.
9871 
9872    This routine is currently only implemented for pairs of SeqAIJ matrices, for the SeqDense class,
9873    and for pairs of MPIDense matrices.
9874 
9875    Options Database Keys:
9876 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for MPIDense matrices: the
9877               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9878               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9879 
9880    Level: intermediate
9881 
9882 .seealso: `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`
9883 @*/
9884 PetscErrorCode MatMatTransposeMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9885 {
9886   PetscFunctionBegin;
9887   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_ABt,C));
9888   if (A == B) {
9889     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9890   }
9891   PetscFunctionReturn(0);
9892 }
9893 
9894 /*@
9895    MatTransposeMatMult - Performs Matrix-Matrix Multiplication C=A^T*B.
9896 
9897    Neighbor-wise Collective on Mat
9898 
9899    Input Parameters:
9900 +  A - the left matrix
9901 .  B - the right matrix
9902 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9903 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9904 
9905    Output Parameters:
9906 .  C - the product matrix
9907 
9908    Notes:
9909    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9910 
9911    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9912 
9913   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9914    actually needed.
9915 
9916    This routine is currently implemented for pairs of AIJ matrices and pairs of SeqDense matrices and classes
9917    which inherit from SeqAIJ.  C will be of the same type as the input matrices.
9918 
9919    Level: intermediate
9920 
9921 .seealso: `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9922 @*/
9923 PetscErrorCode MatTransposeMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9924 {
9925   PetscFunctionBegin;
9926   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AtB,C));
9927   PetscFunctionReturn(0);
9928 }
9929 
9930 /*@
9931    MatMatMatMult - Performs Matrix-Matrix-Matrix Multiplication D=A*B*C.
9932 
9933    Neighbor-wise Collective on Mat
9934 
9935    Input Parameters:
9936 +  A - the left matrix
9937 .  B - the middle matrix
9938 .  C - the right matrix
9939 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9940 -  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
9941           if the result is a dense matrix this is irrelevant
9942 
9943    Output Parameters:
9944 .  D - the product matrix
9945 
9946    Notes:
9947    Unless scall is MAT_REUSE_MATRIX D will be created.
9948 
9949    MAT_REUSE_MATRIX can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9950 
9951    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9952    actually needed.
9953 
9954    If you have many matrices with the same non-zero structure to multiply, you
9955    should use MAT_REUSE_MATRIX in all calls but the first
9956 
9957    Level: intermediate
9958 
9959 .seealso: `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9960 @*/
9961 PetscErrorCode MatMatMatMult(Mat A,Mat B,Mat C,MatReuse scall,PetscReal fill,Mat *D)
9962 {
9963   PetscFunctionBegin;
9964   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D,6);
9965   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9966 
9967   if (scall == MAT_INITIAL_MATRIX) {
9968     PetscCall(MatProductCreate(A,B,C,D));
9969     PetscCall(MatProductSetType(*D,MATPRODUCT_ABC));
9970     PetscCall(MatProductSetAlgorithm(*D,"default"));
9971     PetscCall(MatProductSetFill(*D,fill));
9972 
9973     (*D)->product->api_user = PETSC_TRUE;
9974     PetscCall(MatProductSetFromOptions(*D));
9975     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);
9976     PetscCall(MatProductSymbolic(*D));
9977   } else { /* user may change input matrices when REUSE */
9978     PetscCall(MatProductReplaceMats(A,B,C,*D));
9979   }
9980   PetscCall(MatProductNumeric(*D));
9981   PetscFunctionReturn(0);
9982 }
9983 
9984 /*@
9985    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9986 
9987    Collective on Mat
9988 
9989    Input Parameters:
9990 +  mat - the matrix
9991 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9992 .  subcomm - MPI communicator split from the communicator where mat resides in (or MPI_COMM_NULL if nsubcomm is used)
9993 -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9994 
9995    Output Parameter:
9996 .  matredundant - redundant matrix
9997 
9998    Notes:
9999    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
10000    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10001 
10002    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10003    calling it.
10004 
10005    Level: advanced
10006 
10007 .seealso: `MatDestroy()`
10008 @*/
10009 PetscErrorCode MatCreateRedundantMatrix(Mat mat,PetscInt nsubcomm,MPI_Comm subcomm,MatReuse reuse,Mat *matredundant)
10010 {
10011   MPI_Comm       comm;
10012   PetscMPIInt    size;
10013   PetscInt       mloc_sub,nloc_sub,rstart,rend,M=mat->rmap->N,N=mat->cmap->N,bs=mat->rmap->bs;
10014   Mat_Redundant  *redund=NULL;
10015   PetscSubcomm   psubcomm=NULL;
10016   MPI_Comm       subcomm_in=subcomm;
10017   Mat            *matseq;
10018   IS             isrow,iscol;
10019   PetscBool      newsubcomm=PETSC_FALSE;
10020 
10021   PetscFunctionBegin;
10022   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10023   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10024     PetscValidPointer(*matredundant,5);
10025     PetscValidHeaderSpecific(*matredundant,MAT_CLASSID,5);
10026   }
10027 
10028   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10029   if (size == 1 || nsubcomm == 1) {
10030     if (reuse == MAT_INITIAL_MATRIX) {
10031       PetscCall(MatDuplicate(mat,MAT_COPY_VALUES,matredundant));
10032     } else {
10033       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");
10034       PetscCall(MatCopy(mat,*matredundant,SAME_NONZERO_PATTERN));
10035     }
10036     PetscFunctionReturn(0);
10037   }
10038 
10039   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10040   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10041   MatCheckPreallocated(mat,1);
10042 
10043   PetscCall(PetscLogEventBegin(MAT_RedundantMat,mat,0,0,0));
10044   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10045     /* create psubcomm, then get subcomm */
10046     PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10047     PetscCallMPI(MPI_Comm_size(comm,&size));
10048     PetscCheck(nsubcomm >= 1 && nsubcomm <= size,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"nsubcomm must between 1 and %d",size);
10049 
10050     PetscCall(PetscSubcommCreate(comm,&psubcomm));
10051     PetscCall(PetscSubcommSetNumber(psubcomm,nsubcomm));
10052     PetscCall(PetscSubcommSetType(psubcomm,PETSC_SUBCOMM_CONTIGUOUS));
10053     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10054     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm),&subcomm,NULL));
10055     newsubcomm = PETSC_TRUE;
10056     PetscCall(PetscSubcommDestroy(&psubcomm));
10057   }
10058 
10059   /* get isrow, iscol and a local sequential matrix matseq[0] */
10060   if (reuse == MAT_INITIAL_MATRIX) {
10061     mloc_sub = PETSC_DECIDE;
10062     nloc_sub = PETSC_DECIDE;
10063     if (bs < 1) {
10064       PetscCall(PetscSplitOwnership(subcomm,&mloc_sub,&M));
10065       PetscCall(PetscSplitOwnership(subcomm,&nloc_sub,&N));
10066     } else {
10067       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&mloc_sub,&M));
10068       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&nloc_sub,&N));
10069     }
10070     PetscCallMPI(MPI_Scan(&mloc_sub,&rend,1,MPIU_INT,MPI_SUM,subcomm));
10071     rstart = rend - mloc_sub;
10072     PetscCall(ISCreateStride(PETSC_COMM_SELF,mloc_sub,rstart,1,&isrow));
10073     PetscCall(ISCreateStride(PETSC_COMM_SELF,N,0,1,&iscol));
10074   } else { /* reuse == MAT_REUSE_MATRIX */
10075     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");
10076     /* retrieve subcomm */
10077     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant),&subcomm));
10078     redund = (*matredundant)->redundant;
10079     isrow  = redund->isrow;
10080     iscol  = redund->iscol;
10081     matseq = redund->matseq;
10082   }
10083   PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscol,reuse,&matseq));
10084 
10085   /* get matredundant over subcomm */
10086   if (reuse == MAT_INITIAL_MATRIX) {
10087     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],nloc_sub,reuse,matredundant));
10088 
10089     /* create a supporting struct and attach it to C for reuse */
10090     PetscCall(PetscNewLog(*matredundant,&redund));
10091     (*matredundant)->redundant = redund;
10092     redund->isrow              = isrow;
10093     redund->iscol              = iscol;
10094     redund->matseq             = matseq;
10095     if (newsubcomm) {
10096       redund->subcomm          = subcomm;
10097     } else {
10098       redund->subcomm          = MPI_COMM_NULL;
10099     }
10100   } else {
10101     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],PETSC_DECIDE,reuse,matredundant));
10102   }
10103 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
10104   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10105     PetscCall(MatBindToCPU(*matredundant,PETSC_TRUE));
10106     PetscCall(MatSetBindingPropagates(*matredundant,PETSC_TRUE));
10107   }
10108 #endif
10109   PetscCall(PetscLogEventEnd(MAT_RedundantMat,mat,0,0,0));
10110   PetscFunctionReturn(0);
10111 }
10112 
10113 /*@C
10114    MatGetMultiProcBlock - Create multiple [bjacobi] 'parallel submatrices' from
10115    a given 'mat' object. Each submatrix can span multiple procs.
10116 
10117    Collective on Mat
10118 
10119    Input Parameters:
10120 +  mat - the matrix
10121 .  subcomm - the subcommunicator obtained by com_split(comm)
10122 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10123 
10124    Output Parameter:
10125 .  subMat - 'parallel submatrices each spans a given subcomm
10126 
10127   Notes:
10128   The submatrix partition across processors is dictated by 'subComm' a
10129   communicator obtained by MPI_comm_split(). The subComm
10130   is not restriced to be grouped with consecutive original ranks.
10131 
10132   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10133   map directly to the layout of the original matrix [wrt the local
10134   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10135   into the 'DiagonalMat' of the subMat, hence it is used directly from
10136   the subMat. However the offDiagMat looses some columns - and this is
10137   reconstructed with MatSetValues()
10138 
10139   Level: advanced
10140 
10141 .seealso: `MatCreateSubMatrices()`
10142 @*/
10143 PetscErrorCode   MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall,Mat *subMat)
10144 {
10145   PetscMPIInt    commsize,subCommSize;
10146 
10147   PetscFunctionBegin;
10148   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&commsize));
10149   PetscCallMPI(MPI_Comm_size(subComm,&subCommSize));
10150   PetscCheck(subCommSize <= commsize,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"CommSize %d < SubCommZize %d",commsize,subCommSize);
10151 
10152   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");
10153   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock,mat,0,0,0));
10154   PetscCall((*mat->ops->getmultiprocblock)(mat,subComm,scall,subMat));
10155   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock,mat,0,0,0));
10156   PetscFunctionReturn(0);
10157 }
10158 
10159 /*@
10160    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10161 
10162    Not Collective
10163 
10164    Input Parameters:
10165 +  mat - matrix to extract local submatrix from
10166 .  isrow - local row indices for submatrix
10167 -  iscol - local column indices for submatrix
10168 
10169    Output Parameter:
10170 .  submat - the submatrix
10171 
10172    Level: intermediate
10173 
10174    Notes:
10175    The submat should be returned with MatRestoreLocalSubMatrix().
10176 
10177    Depending on the format of mat, the returned submat may not implement MatMult().  Its communicator may be
10178    the same as mat, it may be PETSC_COMM_SELF, or some other subcomm of mat's.
10179 
10180    The submat always implements MatSetValuesLocal().  If isrow and iscol have the same block size, then
10181    MatSetValuesBlockedLocal() will also be implemented.
10182 
10183    The mat must have had a ISLocalToGlobalMapping provided to it with MatSetLocalToGlobalMapping(). Note that
10184    matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10185 
10186 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10187 @*/
10188 PetscErrorCode MatGetLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10189 {
10190   PetscFunctionBegin;
10191   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10192   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10193   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10194   PetscCheckSameComm(isrow,2,iscol,3);
10195   PetscValidPointer(submat,4);
10196   PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must have local to global mapping provided before this call");
10197 
10198   if (mat->ops->getlocalsubmatrix) {
10199     PetscCall((*mat->ops->getlocalsubmatrix)(mat,isrow,iscol,submat));
10200   } else {
10201     PetscCall(MatCreateLocalRef(mat,isrow,iscol,submat));
10202   }
10203   PetscFunctionReturn(0);
10204 }
10205 
10206 /*@
10207    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering
10208 
10209    Not Collective
10210 
10211    Input Parameters:
10212 +  mat - matrix to extract local submatrix from
10213 .  isrow - local row indices for submatrix
10214 .  iscol - local column indices for submatrix
10215 -  submat - the submatrix
10216 
10217    Level: intermediate
10218 
10219 .seealso: `MatGetLocalSubMatrix()`
10220 @*/
10221 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10222 {
10223   PetscFunctionBegin;
10224   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10225   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10226   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10227   PetscCheckSameComm(isrow,2,iscol,3);
10228   PetscValidPointer(submat,4);
10229   if (*submat) {
10230     PetscValidHeaderSpecific(*submat,MAT_CLASSID,4);
10231   }
10232 
10233   if (mat->ops->restorelocalsubmatrix) {
10234     PetscCall((*mat->ops->restorelocalsubmatrix)(mat,isrow,iscol,submat));
10235   } else {
10236     PetscCall(MatDestroy(submat));
10237   }
10238   *submat = NULL;
10239   PetscFunctionReturn(0);
10240 }
10241 
10242 /* --------------------------------------------------------*/
10243 /*@
10244    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10245 
10246    Collective on Mat
10247 
10248    Input Parameter:
10249 .  mat - the matrix
10250 
10251    Output Parameter:
10252 .  is - if any rows have zero diagonals this contains the list of them
10253 
10254    Level: developer
10255 
10256 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10257 @*/
10258 PetscErrorCode MatFindZeroDiagonals(Mat mat,IS *is)
10259 {
10260   PetscFunctionBegin;
10261   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10262   PetscValidType(mat,1);
10263   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10264   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10265 
10266   if (!mat->ops->findzerodiagonals) {
10267     Vec                diag;
10268     const PetscScalar *a;
10269     PetscInt          *rows;
10270     PetscInt           rStart, rEnd, r, nrow = 0;
10271 
10272     PetscCall(MatCreateVecs(mat, &diag, NULL));
10273     PetscCall(MatGetDiagonal(mat, diag));
10274     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10275     PetscCall(VecGetArrayRead(diag, &a));
10276     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) ++nrow;
10277     PetscCall(PetscMalloc1(nrow, &rows));
10278     nrow = 0;
10279     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) rows[nrow++] = r+rStart;
10280     PetscCall(VecRestoreArrayRead(diag, &a));
10281     PetscCall(VecDestroy(&diag));
10282     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) mat), nrow, rows, PETSC_OWN_POINTER, is));
10283   } else {
10284     PetscCall((*mat->ops->findzerodiagonals)(mat, is));
10285   }
10286   PetscFunctionReturn(0);
10287 }
10288 
10289 /*@
10290    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10291 
10292    Collective on Mat
10293 
10294    Input Parameter:
10295 .  mat - the matrix
10296 
10297    Output Parameter:
10298 .  is - contains the list of rows with off block diagonal entries
10299 
10300    Level: developer
10301 
10302 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10303 @*/
10304 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat,IS *is)
10305 {
10306   PetscFunctionBegin;
10307   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10308   PetscValidType(mat,1);
10309   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10310   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10311 
10312   PetscCheck(mat->ops->findoffblockdiagonalentries,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a find off block diagonal entries defined",((PetscObject)mat)->type_name);
10313   PetscCall((*mat->ops->findoffblockdiagonalentries)(mat,is));
10314   PetscFunctionReturn(0);
10315 }
10316 
10317 /*@C
10318   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10319 
10320   Collective on Mat
10321 
10322   Input Parameters:
10323 . mat - the matrix
10324 
10325   Output Parameters:
10326 . values - the block inverses in column major order (FORTRAN-like)
10327 
10328    Note:
10329      The size of the blocks is determined by the block size of the matrix.
10330 
10331    Fortran Note:
10332      This routine is not available from Fortran.
10333 
10334   Level: advanced
10335 
10336 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10337 @*/
10338 PetscErrorCode MatInvertBlockDiagonal(Mat mat,const PetscScalar **values)
10339 {
10340   PetscFunctionBegin;
10341   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10342   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10343   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10344   PetscCheck(mat->ops->invertblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10345   PetscCall((*mat->ops->invertblockdiagonal)(mat,values));
10346   PetscFunctionReturn(0);
10347 }
10348 
10349 /*@C
10350   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10351 
10352   Collective on Mat
10353 
10354   Input Parameters:
10355 + mat - the matrix
10356 . nblocks - the number of blocks on the process, set with MatSetVariableBlockSizes()
10357 - bsizes - the size of each block on the process, set with MatSetVariableBlockSizes()
10358 
10359   Output Parameters:
10360 . values - the block inverses in column major order (FORTRAN-like)
10361 
10362    Note:
10363    This routine is not available from Fortran.
10364 
10365   Level: advanced
10366 
10367 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10368 @*/
10369 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *values)
10370 {
10371   PetscFunctionBegin;
10372   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10373   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10374   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10375   PetscCheck(mat->ops->invertvariableblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10376   PetscCall((*mat->ops->invertvariableblockdiagonal)(mat,nblocks,bsizes,values));
10377   PetscFunctionReturn(0);
10378 }
10379 
10380 /*@
10381   MatInvertBlockDiagonalMat - set matrix C to be the inverted block diagonal of matrix A
10382 
10383   Collective on Mat
10384 
10385   Input Parameters:
10386 . A - the matrix
10387 
10388   Output Parameters:
10389 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10390 
10391   Notes: the blocksize of the matrix is used to determine the blocks on the diagonal of C
10392 
10393   Level: advanced
10394 
10395 .seealso: `MatInvertBlockDiagonal()`
10396 @*/
10397 PetscErrorCode MatInvertBlockDiagonalMat(Mat A,Mat C)
10398 {
10399   const PetscScalar *vals;
10400   PetscInt          *dnnz;
10401   PetscInt           m,rstart,rend,bs,i,j;
10402 
10403   PetscFunctionBegin;
10404   PetscCall(MatInvertBlockDiagonal(A,&vals));
10405   PetscCall(MatGetBlockSize(A,&bs));
10406   PetscCall(MatGetLocalSize(A,&m,NULL));
10407   PetscCall(MatSetLayouts(C,A->rmap,A->cmap));
10408   PetscCall(PetscMalloc1(m/bs,&dnnz));
10409   for (j = 0; j < m/bs; j++) dnnz[j] = 1;
10410   PetscCall(MatXAIJSetPreallocation(C,bs,dnnz,NULL,NULL,NULL));
10411   PetscCall(PetscFree(dnnz));
10412   PetscCall(MatGetOwnershipRange(C,&rstart,&rend));
10413   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_FALSE));
10414   for (i = rstart/bs; i < rend/bs; i++) {
10415     PetscCall(MatSetValuesBlocked(C,1,&i,1,&i,&vals[(i-rstart/bs)*bs*bs],INSERT_VALUES));
10416   }
10417   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
10418   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
10419   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_TRUE));
10420   PetscFunctionReturn(0);
10421 }
10422 
10423 /*@C
10424     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10425     via MatTransposeColoringCreate().
10426 
10427     Collective on MatTransposeColoring
10428 
10429     Input Parameter:
10430 .   c - coloring context
10431 
10432     Level: intermediate
10433 
10434 .seealso: `MatTransposeColoringCreate()`
10435 @*/
10436 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10437 {
10438   MatTransposeColoring matcolor=*c;
10439 
10440   PetscFunctionBegin;
10441   if (!matcolor) PetscFunctionReturn(0);
10442   if (--((PetscObject)matcolor)->refct > 0) {matcolor = NULL; PetscFunctionReturn(0);}
10443 
10444   PetscCall(PetscFree3(matcolor->ncolumns,matcolor->nrows,matcolor->colorforrow));
10445   PetscCall(PetscFree(matcolor->rows));
10446   PetscCall(PetscFree(matcolor->den2sp));
10447   PetscCall(PetscFree(matcolor->colorforcol));
10448   PetscCall(PetscFree(matcolor->columns));
10449   if (matcolor->brows>0) PetscCall(PetscFree(matcolor->lstart));
10450   PetscCall(PetscHeaderDestroy(c));
10451   PetscFunctionReturn(0);
10452 }
10453 
10454 /*@C
10455     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10456     a MatTransposeColoring context has been created, computes a dense B^T by Apply
10457     MatTransposeColoring to sparse B.
10458 
10459     Collective on MatTransposeColoring
10460 
10461     Input Parameters:
10462 +   B - sparse matrix B
10463 .   Btdense - symbolic dense matrix B^T
10464 -   coloring - coloring context created with MatTransposeColoringCreate()
10465 
10466     Output Parameter:
10467 .   Btdense - dense matrix B^T
10468 
10469     Level: advanced
10470 
10471      Notes:
10472     These are used internally for some implementations of MatRARt()
10473 
10474 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10475 
10476 @*/
10477 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring,Mat B,Mat Btdense)
10478 {
10479   PetscFunctionBegin;
10480   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10481   PetscValidHeaderSpecific(Btdense,MAT_CLASSID,3);
10482   PetscValidHeaderSpecific(coloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10483 
10484   PetscCheck(B->ops->transcoloringapplysptoden,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)B)->type_name);
10485   PetscCall((B->ops->transcoloringapplysptoden)(coloring,B,Btdense));
10486   PetscFunctionReturn(0);
10487 }
10488 
10489 /*@C
10490     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10491     a MatTransposeColoring context has been created and a dense matrix Cden=A*Btdense
10492     in which Btdens is obtained from MatTransColoringApplySpToDen(), recover sparse matrix
10493     Csp from Cden.
10494 
10495     Collective on MatTransposeColoring
10496 
10497     Input Parameters:
10498 +   coloring - coloring context created with MatTransposeColoringCreate()
10499 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10500 
10501     Output Parameter:
10502 .   Csp - sparse matrix
10503 
10504     Level: advanced
10505 
10506      Notes:
10507     These are used internally for some implementations of MatRARt()
10508 
10509 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10510 
10511 @*/
10512 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring,Mat Cden,Mat Csp)
10513 {
10514   PetscFunctionBegin;
10515   PetscValidHeaderSpecific(matcoloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10516   PetscValidHeaderSpecific(Cden,MAT_CLASSID,2);
10517   PetscValidHeaderSpecific(Csp,MAT_CLASSID,3);
10518 
10519   PetscCheck(Csp->ops->transcoloringapplydentosp,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)Csp)->type_name);
10520   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring,Cden,Csp));
10521   PetscCall(MatAssemblyBegin(Csp,MAT_FINAL_ASSEMBLY));
10522   PetscCall(MatAssemblyEnd(Csp,MAT_FINAL_ASSEMBLY));
10523   PetscFunctionReturn(0);
10524 }
10525 
10526 /*@C
10527    MatTransposeColoringCreate - Creates a matrix coloring context for matrix product C=A*B^T.
10528 
10529    Collective on Mat
10530 
10531    Input Parameters:
10532 +  mat - the matrix product C
10533 -  iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring()
10534 
10535     Output Parameter:
10536 .   color - the new coloring context
10537 
10538     Level: intermediate
10539 
10540 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10541           `MatTransColoringApplyDenToSp()`
10542 @*/
10543 PetscErrorCode MatTransposeColoringCreate(Mat mat,ISColoring iscoloring,MatTransposeColoring *color)
10544 {
10545   MatTransposeColoring c;
10546   MPI_Comm             comm;
10547 
10548   PetscFunctionBegin;
10549   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate,mat,0,0,0));
10550   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10551   PetscCall(PetscHeaderCreate(c,MAT_TRANSPOSECOLORING_CLASSID,"MatTransposeColoring","Matrix product C=A*B^T via coloring","Mat",comm,MatTransposeColoringDestroy,NULL));
10552 
10553   c->ctype = iscoloring->ctype;
10554   if (mat->ops->transposecoloringcreate) {
10555     PetscCall((*mat->ops->transposecoloringcreate)(mat,iscoloring,c));
10556   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);
10557 
10558   *color = c;
10559   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate,mat,0,0,0));
10560   PetscFunctionReturn(0);
10561 }
10562 
10563 /*@
10564       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10565         matrix has had no new nonzero locations added to the matrix since the previous call then the value will be the
10566         same, otherwise it will be larger
10567 
10568      Not Collective
10569 
10570   Input Parameter:
10571 .    A  - the matrix
10572 
10573   Output Parameter:
10574 .    state - the current state
10575 
10576   Notes:
10577     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10578          different matrices
10579 
10580   Level: intermediate
10581 
10582 .seealso: `PetscObjectStateGet()`
10583 @*/
10584 PetscErrorCode MatGetNonzeroState(Mat mat,PetscObjectState *state)
10585 {
10586   PetscFunctionBegin;
10587   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10588   *state = mat->nonzerostate;
10589   PetscFunctionReturn(0);
10590 }
10591 
10592 /*@
10593       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10594                  matrices from each processor
10595 
10596     Collective
10597 
10598    Input Parameters:
10599 +    comm - the communicators the parallel matrix will live on
10600 .    seqmat - the input sequential matrices
10601 .    n - number of local columns (or PETSC_DECIDE)
10602 -    reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10603 
10604    Output Parameter:
10605 .    mpimat - the parallel matrix generated
10606 
10607     Level: advanced
10608 
10609    Notes:
10610     The number of columns of the matrix in EACH processor MUST be the same.
10611 
10612 @*/
10613 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm,Mat seqmat,PetscInt n,MatReuse reuse,Mat *mpimat)
10614 {
10615   PetscFunctionBegin;
10616   PetscCheck(seqmat->ops->creatempimatconcatenateseqmat,PetscObjectComm((PetscObject)seqmat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)seqmat)->type_name);
10617   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");
10618 
10619   PetscCall(PetscLogEventBegin(MAT_Merge,seqmat,0,0,0));
10620   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm,seqmat,n,reuse,mpimat));
10621   PetscCall(PetscLogEventEnd(MAT_Merge,seqmat,0,0,0));
10622   PetscFunctionReturn(0);
10623 }
10624 
10625 /*@
10626      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent
10627                  ranks' ownership ranges.
10628 
10629     Collective on A
10630 
10631    Input Parameters:
10632 +    A   - the matrix to create subdomains from
10633 -    N   - requested number of subdomains
10634 
10635    Output Parameters:
10636 +    n   - number of subdomains resulting on this rank
10637 -    iss - IS list with indices of subdomains on this rank
10638 
10639     Level: advanced
10640 
10641     Notes:
10642     number of subdomains must be smaller than the communicator size
10643 @*/
10644 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A,PetscInt N,PetscInt *n,IS *iss[])
10645 {
10646   MPI_Comm        comm,subcomm;
10647   PetscMPIInt     size,rank,color;
10648   PetscInt        rstart,rend,k;
10649 
10650   PetscFunctionBegin;
10651   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
10652   PetscCallMPI(MPI_Comm_size(comm,&size));
10653   PetscCallMPI(MPI_Comm_rank(comm,&rank));
10654   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);
10655   *n = 1;
10656   k = ((PetscInt)size)/N + ((PetscInt)size%N>0); /* There are up to k ranks to a color */
10657   color = rank/k;
10658   PetscCallMPI(MPI_Comm_split(comm,color,rank,&subcomm));
10659   PetscCall(PetscMalloc1(1,iss));
10660   PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
10661   PetscCall(ISCreateStride(subcomm,rend-rstart,rstart,1,iss[0]));
10662   PetscCallMPI(MPI_Comm_free(&subcomm));
10663   PetscFunctionReturn(0);
10664 }
10665 
10666 /*@
10667    MatGalerkin - Constructs the coarse grid problem via Galerkin projection.
10668 
10669    If the interpolation and restriction operators are the same, uses MatPtAP.
10670    If they are not the same, use MatMatMatMult.
10671 
10672    Once the coarse grid problem is constructed, correct for interpolation operators
10673    that are not of full rank, which can legitimately happen in the case of non-nested
10674    geometric multigrid.
10675 
10676    Input Parameters:
10677 +  restrct - restriction operator
10678 .  dA - fine grid matrix
10679 .  interpolate - interpolation operator
10680 .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10681 -  fill - expected fill, use PETSC_DEFAULT if you do not have a good estimate
10682 
10683    Output Parameters:
10684 .  A - the Galerkin coarse matrix
10685 
10686    Options Database Key:
10687 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10688 
10689    Level: developer
10690 
10691 .seealso: `MatPtAP()`, `MatMatMatMult()`
10692 @*/
10693 PetscErrorCode  MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10694 {
10695   IS             zerorows;
10696   Vec            diag;
10697 
10698   PetscFunctionBegin;
10699   PetscCheck(reuse != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
10700   /* Construct the coarse grid matrix */
10701   if (interpolate == restrct) {
10702     PetscCall(MatPtAP(dA,interpolate,reuse,fill,A));
10703   } else {
10704     PetscCall(MatMatMatMult(restrct,dA,interpolate,reuse,fill,A));
10705   }
10706 
10707   /* If the interpolation matrix is not of full rank, A will have zero rows.
10708      This can legitimately happen in the case of non-nested geometric multigrid.
10709      In that event, we set the rows of the matrix to the rows of the identity,
10710      ignoring the equations (as the RHS will also be zero). */
10711 
10712   PetscCall(MatFindZeroRows(*A, &zerorows));
10713 
10714   if (zerorows != NULL) { /* if there are any zero rows */
10715     PetscCall(MatCreateVecs(*A, &diag, NULL));
10716     PetscCall(MatGetDiagonal(*A, diag));
10717     PetscCall(VecISSet(diag, zerorows, 1.0));
10718     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10719     PetscCall(VecDestroy(&diag));
10720     PetscCall(ISDestroy(&zerorows));
10721   }
10722   PetscFunctionReturn(0);
10723 }
10724 
10725 /*@C
10726     MatSetOperation - Allows user to set a matrix operation for any matrix type
10727 
10728    Logically Collective on Mat
10729 
10730     Input Parameters:
10731 +   mat - the matrix
10732 .   op - the name of the operation
10733 -   f - the function that provides the operation
10734 
10735    Level: developer
10736 
10737     Usage:
10738 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10739 $      PetscCall(MatCreateXXX(comm,...&A);
10740 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10741 
10742     Notes:
10743     See the file include/petscmat.h for a complete list of matrix
10744     operations, which all have the form MATOP_<OPERATION>, where
10745     <OPERATION> is the name (in all capital letters) of the
10746     user interface routine (e.g., MatMult() -> MATOP_MULT).
10747 
10748     All user-provided functions (except for MATOP_DESTROY) should have the same calling
10749     sequence as the usual matrix interface routines, since they
10750     are intended to be accessed via the usual matrix interface
10751     routines, e.g.,
10752 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10753 
10754     In particular each function MUST return an error code of 0 on success and
10755     nonzero on failure.
10756 
10757     This routine is distinct from MatShellSetOperation() in that it can be called on any matrix type.
10758 
10759 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10760 @*/
10761 PetscErrorCode MatSetOperation(Mat mat,MatOperation op,void (*f)(void))
10762 {
10763   PetscFunctionBegin;
10764   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10765   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) {
10766     mat->ops->viewnative = mat->ops->view;
10767   }
10768   (((void(**)(void))mat->ops)[op]) = f;
10769   PetscFunctionReturn(0);
10770 }
10771 
10772 /*@C
10773     MatGetOperation - Gets a matrix operation for any matrix type.
10774 
10775     Not Collective
10776 
10777     Input Parameters:
10778 +   mat - the matrix
10779 -   op - the name of the operation
10780 
10781     Output Parameter:
10782 .   f - the function that provides the operation
10783 
10784     Level: developer
10785 
10786     Usage:
10787 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10788 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10789 
10790     Notes:
10791     See the file include/petscmat.h for a complete list of matrix
10792     operations, which all have the form MATOP_<OPERATION>, where
10793     <OPERATION> is the name (in all capital letters) of the
10794     user interface routine (e.g., MatMult() -> MATOP_MULT).
10795 
10796     This routine is distinct from MatShellGetOperation() in that it can be called on any matrix type.
10797 
10798 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10799 @*/
10800 PetscErrorCode MatGetOperation(Mat mat,MatOperation op,void(**f)(void))
10801 {
10802   PetscFunctionBegin;
10803   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10804   *f = (((void (**)(void))mat->ops)[op]);
10805   PetscFunctionReturn(0);
10806 }
10807 
10808 /*@
10809     MatHasOperation - Determines whether the given matrix supports the particular
10810     operation.
10811 
10812    Not Collective
10813 
10814    Input Parameters:
10815 +  mat - the matrix
10816 -  op - the operation, for example, MATOP_GET_DIAGONAL
10817 
10818    Output Parameter:
10819 .  has - either PETSC_TRUE or PETSC_FALSE
10820 
10821    Level: advanced
10822 
10823    Notes:
10824    See the file include/petscmat.h for a complete list of matrix
10825    operations, which all have the form MATOP_<OPERATION>, where
10826    <OPERATION> is the name (in all capital letters) of the
10827    user-level routine.  E.g., MatNorm() -> MATOP_NORM.
10828 
10829 .seealso: `MatCreateShell()`
10830 @*/
10831 PetscErrorCode MatHasOperation(Mat mat,MatOperation op,PetscBool *has)
10832 {
10833   PetscFunctionBegin;
10834   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10835   PetscValidBoolPointer(has,3);
10836   if (mat->ops->hasoperation) {
10837     PetscCall((*mat->ops->hasoperation)(mat,op,has));
10838   } else {
10839     if (((void**)mat->ops)[op]) *has = PETSC_TRUE;
10840     else {
10841       *has = PETSC_FALSE;
10842       if (op == MATOP_CREATE_SUBMATRIX) {
10843         PetscMPIInt size;
10844 
10845         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10846         if (size == 1) {
10847           PetscCall(MatHasOperation(mat,MATOP_CREATE_SUBMATRICES,has));
10848         }
10849       }
10850     }
10851   }
10852   PetscFunctionReturn(0);
10853 }
10854 
10855 /*@
10856     MatHasCongruentLayouts - Determines whether the rows and columns layouts
10857     of the matrix are congruent
10858 
10859    Collective on mat
10860 
10861    Input Parameters:
10862 .  mat - the matrix
10863 
10864    Output Parameter:
10865 .  cong - either PETSC_TRUE or PETSC_FALSE
10866 
10867    Level: beginner
10868 
10869    Notes:
10870 
10871 .seealso: `MatCreate()`, `MatSetSizes()`
10872 @*/
10873 PetscErrorCode MatHasCongruentLayouts(Mat mat,PetscBool *cong)
10874 {
10875   PetscFunctionBegin;
10876   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10877   PetscValidType(mat,1);
10878   PetscValidBoolPointer(cong,2);
10879   if (!mat->rmap || !mat->cmap) {
10880     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10881     PetscFunctionReturn(0);
10882   }
10883   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10884     PetscCall(PetscLayoutSetUp(mat->rmap));
10885     PetscCall(PetscLayoutSetUp(mat->cmap));
10886     PetscCall(PetscLayoutCompare(mat->rmap,mat->cmap,cong));
10887     if (*cong) mat->congruentlayouts = 1;
10888     else       mat->congruentlayouts = 0;
10889   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10890   PetscFunctionReturn(0);
10891 }
10892 
10893 PetscErrorCode MatSetInf(Mat A)
10894 {
10895   PetscFunctionBegin;
10896   PetscCheck(A->ops->setinf,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10897   PetscCall((*A->ops->setinf)(A));
10898   PetscFunctionReturn(0);
10899 }
10900 
10901 /*C
10902    MatCreateGraph - create a scalar matrix, for use in graph algorithms
10903 
10904    Collective on mat
10905 
10906    Input Parameters:
10907 +  A - the matrix
10908 -  sym - PETSC_TRUE indicates that the graph will be symmetrized
10909 .  scale - PETSC_TRUE indicates that the graph will be scaled with the diagonal
10910 
10911    Output Parameter:
10912 .  graph - the resulting graph
10913 
10914    Level: advanced
10915 
10916    Notes:
10917 
10918 .seealso: `MatCreate()`, `MatFilter()`
10919 */
10920 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, Mat *graph)
10921 {
10922   PetscFunctionBegin;
10923   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
10924   PetscValidType(A,1);
10925   PetscValidPointer(graph,3);
10926   PetscCheck(A->ops->creategraph,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10927   PetscCall((*A->ops->creategraph)(A,sym,scale,graph));
10928   PetscFunctionReturn(0);
10929 }
10930 
10931 /*C
10932    MatFilter - filters a Mat values with an absolut value equal to or below a give threshold
10933 
10934    Collective on mat
10935 
10936    Input Parameter:
10937 .  value - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries <= value
10938 
10939    Input/Output Parameter:
10940 .  A - the Mat to filter in place
10941 
10942    Level: advanced
10943 
10944    Notes:
10945 
10946 .seealso: `MatCreate()`, `MatCreateGraph()`
10947 */
10948 PETSC_EXTERN PetscErrorCode MatFilter(Mat G,PetscReal value,Mat *F)
10949 {
10950   PetscFunctionBegin;
10951   PetscValidHeaderSpecific(G,MAT_CLASSID,1);
10952   PetscValidType(G,1);
10953   PetscValidPointer(F,3);
10954   if (value >= 0.0) {
10955     PetscCheck(G->ops->filter,PetscObjectComm((PetscObject)G),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10956     PetscCall((G->ops->filter)(G,value,F));
10957   }
10958   PetscFunctionReturn(0);
10959 }
10960