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