xref: /petsc/src/mat/interface/matrix.c (revision 5a9175c23ff35bbab7fd940dc9074f2479049b62)
1 /*
2    This is where the abstract matrix operations are defined
3 */
4 
5 #include <petsc/private/matimpl.h>        /*I "petscmat.h" I*/
6 #include <petsc/private/isimpl.h>
7 #include <petsc/private/vecimpl.h>
8 
9 /* Logging support */
10 PetscClassId MAT_CLASSID;
11 PetscClassId MAT_COLORING_CLASSID;
12 PetscClassId MAT_FDCOLORING_CLASSID;
13 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
14 
15 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
16 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve,MAT_MatTrSolve;
17 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
18 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
19 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
20 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
21 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
22 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
23 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply,MAT_Transpose,MAT_FDColoringFunction, MAT_CreateSubMat;
24 PetscLogEvent MAT_TransposeColoringCreate;
25 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
26 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric,MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
27 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
28 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
29 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
30 PetscLogEvent MAT_MultHermitianTranspose,MAT_MultHermitianTransposeAdd;
31 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
32 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
33 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
34 PetscLogEvent MAT_GetMultiProcBlock;
35 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
36 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
37 PetscLogEvent MAT_SetValuesBatch;
38 PetscLogEvent MAT_ViennaCLCopyToGPU;
39 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
40 PetscLogEvent MAT_Merge,MAT_Residual,MAT_SetRandom;
41 PetscLogEvent MAT_FactorFactS,MAT_FactorInvS;
42 PetscLogEvent MATCOLORING_Apply,MATCOLORING_Comm,MATCOLORING_Local,MATCOLORING_ISCreate,MATCOLORING_SetUp,MATCOLORING_Weights;
43 PetscLogEvent MAT_H2Opus_Build,MAT_H2Opus_Compress,MAT_H2Opus_Orthog,MAT_H2Opus_LR;
44 
45 const char *const MatFactorTypes[] = {"NONE","LU","CHOLESKY","ILU","ICC","ILUDT","QR","MatFactorType","MAT_FACTOR_",NULL};
46 
47 /*@
48    MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
49                   for sparse matrices that already have locations it fills the locations with random numbers
50 
51    Logically Collective on Mat
52 
53    Input Parameters:
54 +  x  - the matrix
55 -  rctx - the random number context, formed by PetscRandomCreate(), or NULL and
56           it will create one internally.
57 
58    Output Parameter:
59 .  x  - the matrix
60 
61    Example of Usage:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68    Level: intermediate
69 
70 .seealso: `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
71 @*/
72 PetscErrorCode MatSetRandom(Mat x,PetscRandom rctx)
73 {
74   PetscRandom    randObj = NULL;
75 
76   PetscFunctionBegin;
77   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
78   if (rctx) PetscValidHeaderSpecific(rctx,PETSC_RANDOM_CLASSID,2);
79   PetscValidType(x,1);
80   MatCheckPreallocated(x,1);
81 
82   PetscCheck(x->ops->setrandom,PetscObjectComm((PetscObject)x),PETSC_ERR_SUP,"Mat type %s",((PetscObject)x)->type_name);
83 
84   if (!rctx) {
85     MPI_Comm comm;
86     PetscCall(PetscObjectGetComm((PetscObject)x,&comm));
87     PetscCall(PetscRandomCreate(comm,&randObj));
88     PetscCall(PetscRandomSetFromOptions(randObj));
89     rctx = randObj;
90   }
91   PetscCall(PetscLogEventBegin(MAT_SetRandom,x,rctx,0,0));
92   PetscCall((*x->ops->setrandom)(x,rctx));
93   PetscCall(PetscLogEventEnd(MAT_SetRandom,x,rctx,0,0));
94 
95   PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY));
96   PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY));
97   PetscCall(PetscRandomDestroy(&randObj));
98   PetscFunctionReturn(0);
99 }
100 
101 /*@
102    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
103 
104    Logically Collective on Mat
105 
106    Input Parameter:
107 .  mat - the factored matrix
108 
109    Output Parameters:
110 +  pivot - the pivot value computed
111 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
112          the share the matrix
113 
114    Level: advanced
115 
116    Notes:
117     This routine does not work for factorizations done with external packages.
118 
119     This routine should only be called if MatGetFactorError() returns a value of MAT_FACTOR_NUMERIC_ZEROPIVOT
120 
121     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
122 
123 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`
124 @*/
125 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat,PetscReal *pivot,PetscInt *row)
126 {
127   PetscFunctionBegin;
128   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
129   PetscValidRealPointer(pivot,2);
130   PetscValidIntPointer(row,3);
131   *pivot = mat->factorerror_zeropivot_value;
132   *row   = mat->factorerror_zeropivot_row;
133   PetscFunctionReturn(0);
134 }
135 
136 /*@
137    MatFactorGetError - gets the error code from a factorization
138 
139    Logically Collective on Mat
140 
141    Input Parameters:
142 .  mat - the factored matrix
143 
144    Output Parameter:
145 .  err  - the error code
146 
147    Level: advanced
148 
149    Notes:
150     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
151 
152 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`
153 @*/
154 PetscErrorCode MatFactorGetError(Mat mat,MatFactorError *err)
155 {
156   PetscFunctionBegin;
157   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
158   PetscValidPointer(err,2);
159   *err = mat->factorerrortype;
160   PetscFunctionReturn(0);
161 }
162 
163 /*@
164    MatFactorClearError - clears the error code in a factorization
165 
166    Logically Collective on Mat
167 
168    Input Parameter:
169 .  mat - the factored matrix
170 
171    Level: developer
172 
173    Notes:
174     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
175 
176 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`
177 @*/
178 PetscErrorCode MatFactorClearError(Mat mat)
179 {
180   PetscFunctionBegin;
181   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
182   mat->factorerrortype             = MAT_FACTOR_NOERROR;
183   mat->factorerror_zeropivot_value = 0.0;
184   mat->factorerror_zeropivot_row   = 0;
185   PetscFunctionReturn(0);
186 }
187 
188 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat,PetscBool cols,PetscReal tol,IS *nonzero)
189 {
190   Vec               r,l;
191   const PetscScalar *al;
192   PetscInt          i,nz,gnz,N,n;
193 
194   PetscFunctionBegin;
195   PetscCall(MatCreateVecs(mat,&r,&l));
196   if (!cols) { /* nonzero rows */
197     PetscCall(MatGetSize(mat,&N,NULL));
198     PetscCall(MatGetLocalSize(mat,&n,NULL));
199     PetscCall(VecSet(l,0.0));
200     PetscCall(VecSetRandom(r,NULL));
201     PetscCall(MatMult(mat,r,l));
202     PetscCall(VecGetArrayRead(l,&al));
203   } else { /* nonzero columns */
204     PetscCall(MatGetSize(mat,NULL,&N));
205     PetscCall(MatGetLocalSize(mat,NULL,&n));
206     PetscCall(VecSet(r,0.0));
207     PetscCall(VecSetRandom(l,NULL));
208     PetscCall(MatMultTranspose(mat,l,r));
209     PetscCall(VecGetArrayRead(r,&al));
210   }
211   if (tol <= 0.0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nz++; }
212   else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nz++; }
213   PetscCall(MPIU_Allreduce(&nz,&gnz,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
214   if (gnz != N) {
215     PetscInt *nzr;
216     PetscCall(PetscMalloc1(nz,&nzr));
217     if (nz) {
218       if (tol < 0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nzr[nz++] = i; }
219       else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; }
220     }
221     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat),nz,nzr,PETSC_OWN_POINTER,nonzero));
222   } else *nonzero = NULL;
223   if (!cols) { /* nonzero rows */
224     PetscCall(VecRestoreArrayRead(l,&al));
225   } else {
226     PetscCall(VecRestoreArrayRead(r,&al));
227   }
228   PetscCall(VecDestroy(&l));
229   PetscCall(VecDestroy(&r));
230   PetscFunctionReturn(0);
231 }
232 
233 /*@
234       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
235 
236   Input Parameter:
237 .    A  - the matrix
238 
239   Output Parameter:
240 .    keptrows - the rows that are not completely zero
241 
242   Notes:
243     keptrows is set to NULL if all rows are nonzero.
244 
245   Level: intermediate
246 
247  @*/
248 PetscErrorCode MatFindNonzeroRows(Mat mat,IS *keptrows)
249 {
250   PetscFunctionBegin;
251   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
252   PetscValidType(mat,1);
253   PetscValidPointer(keptrows,2);
254   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
255   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
256   if (mat->ops->findnonzerorows) {
257     PetscCall((*mat->ops->findnonzerorows)(mat,keptrows));
258   } else {
259     PetscCall(MatFindNonzeroRowsOrCols_Basic(mat,PETSC_FALSE,0.0,keptrows));
260   }
261   PetscFunctionReturn(0);
262 }
263 
264 /*@
265       MatFindZeroRows - Locate all rows that are completely zero in the matrix
266 
267   Input Parameter:
268 .    A  - the matrix
269 
270   Output Parameter:
271 .    zerorows - the rows that are completely zero
272 
273   Notes:
274     zerorows is set to NULL if no rows are zero.
275 
276   Level: intermediate
277 
278  @*/
279 PetscErrorCode MatFindZeroRows(Mat mat,IS *zerorows)
280 {
281   IS       keptrows;
282   PetscInt m, n;
283 
284   PetscFunctionBegin;
285   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
286   PetscValidType(mat,1);
287   PetscValidPointer(zerorows,2);
288   PetscCall(MatFindNonzeroRows(mat, &keptrows));
289   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
290      In keeping with this convention, we set zerorows to NULL if there are no zero
291      rows. */
292   if (keptrows == NULL) {
293     *zerorows = NULL;
294   } else {
295     PetscCall(MatGetOwnershipRange(mat,&m,&n));
296     PetscCall(ISComplement(keptrows,m,n,zerorows));
297     PetscCall(ISDestroy(&keptrows));
298   }
299   PetscFunctionReturn(0);
300 }
301 
302 /*@
303    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
304 
305    Not Collective
306 
307    Input Parameters:
308 .   A - the matrix
309 
310    Output Parameters:
311 .   a - the diagonal part (which is a SEQUENTIAL matrix)
312 
313    Notes:
314     see the manual page for MatCreateAIJ() for more information on the "diagonal part" of the matrix.
315           Use caution, as the reference count on the returned matrix is not incremented and it is used as
316           part of the containing MPI Mat's normal operation.
317 
318    Level: advanced
319 
320 @*/
321 PetscErrorCode MatGetDiagonalBlock(Mat A,Mat *a)
322 {
323   PetscFunctionBegin;
324   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
325   PetscValidType(A,1);
326   PetscValidPointer(a,2);
327   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
328   if (A->ops->getdiagonalblock) {
329     PetscCall((*A->ops->getdiagonalblock)(A,a));
330   } else {
331     PetscMPIInt size;
332 
333     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
334     PetscCheck(size == 1,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not for parallel matrix type %s",((PetscObject)A)->type_name);
335     *a = A;
336   }
337   PetscFunctionReturn(0);
338 }
339 
340 /*@
341    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
342 
343    Collective on Mat
344 
345    Input Parameters:
346 .  mat - the matrix
347 
348    Output Parameter:
349 .   trace - the sum of the diagonal entries
350 
351    Level: advanced
352 
353 @*/
354 PetscErrorCode MatGetTrace(Mat mat,PetscScalar *trace)
355 {
356   Vec diag;
357 
358   PetscFunctionBegin;
359   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
360   PetscValidScalarPointer(trace,2);
361   PetscCall(MatCreateVecs(mat,&diag,NULL));
362   PetscCall(MatGetDiagonal(mat,diag));
363   PetscCall(VecSum(diag,trace));
364   PetscCall(VecDestroy(&diag));
365   PetscFunctionReturn(0);
366 }
367 
368 /*@
369    MatRealPart - Zeros out the imaginary part of the matrix
370 
371    Logically Collective on Mat
372 
373    Input Parameters:
374 .  mat - the matrix
375 
376    Level: advanced
377 
378 .seealso: `MatImaginaryPart()`
379 @*/
380 PetscErrorCode MatRealPart(Mat mat)
381 {
382   PetscFunctionBegin;
383   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
384   PetscValidType(mat,1);
385   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
386   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
387   PetscCheck(mat->ops->realpart,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
388   MatCheckPreallocated(mat,1);
389   PetscCall((*mat->ops->realpart)(mat));
390   PetscFunctionReturn(0);
391 }
392 
393 /*@C
394    MatGetGhosts - Get the global index of all ghost nodes defined by the sparse matrix
395 
396    Collective on Mat
397 
398    Input Parameter:
399 .  mat - the matrix
400 
401    Output Parameters:
402 +   nghosts - number of ghosts (note for BAIJ matrices there is one ghost for each block)
403 -   ghosts - the global indices of the ghost points
404 
405    Notes:
406     the nghosts and ghosts are suitable to pass into VecCreateGhost()
407 
408    Level: advanced
409 
410 @*/
411 PetscErrorCode MatGetGhosts(Mat mat,PetscInt *nghosts,const PetscInt *ghosts[])
412 {
413   PetscFunctionBegin;
414   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
415   PetscValidType(mat,1);
416   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
417   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
418   if (mat->ops->getghosts) {
419     PetscCall((*mat->ops->getghosts)(mat,nghosts,ghosts));
420   } else {
421     if (nghosts) *nghosts = 0;
422     if (ghosts)  *ghosts  = NULL;
423   }
424   PetscFunctionReturn(0);
425 }
426 
427 /*@
428    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
429 
430    Logically Collective on Mat
431 
432    Input Parameters:
433 .  mat - the matrix
434 
435    Level: advanced
436 
437 .seealso: `MatRealPart()`
438 @*/
439 PetscErrorCode MatImaginaryPart(Mat mat)
440 {
441   PetscFunctionBegin;
442   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
443   PetscValidType(mat,1);
444   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
445   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
446   PetscCheck(mat->ops->imaginarypart,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
447   MatCheckPreallocated(mat,1);
448   PetscCall((*mat->ops->imaginarypart)(mat));
449   PetscFunctionReturn(0);
450 }
451 
452 /*@
453    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for BAIJ matrices)
454 
455    Not Collective
456 
457    Input Parameter:
458 .  mat - the matrix
459 
460    Output Parameters:
461 +  missing - is any diagonal missing
462 -  dd - first diagonal entry that is missing (optional) on this process
463 
464    Level: advanced
465 
466 .seealso: `MatRealPart()`
467 @*/
468 PetscErrorCode MatMissingDiagonal(Mat mat,PetscBool *missing,PetscInt *dd)
469 {
470   PetscFunctionBegin;
471   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
472   PetscValidType(mat,1);
473   PetscValidBoolPointer(missing,2);
474   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix %s",((PetscObject)mat)->type_name);
475   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
476   PetscCheck(mat->ops->missingdiagonal,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
477   PetscCall((*mat->ops->missingdiagonal)(mat,missing,dd));
478   PetscFunctionReturn(0);
479 }
480 
481 /*@C
482    MatGetRow - Gets a row of a matrix.  You MUST call MatRestoreRow()
483    for each row that you get to ensure that your application does
484    not bleed memory.
485 
486    Not Collective
487 
488    Input Parameters:
489 +  mat - the matrix
490 -  row - the row to get
491 
492    Output Parameters:
493 +  ncols -  if not NULL, the number of nonzeros in the row
494 .  cols - if not NULL, the column numbers
495 -  vals - if not NULL, the values
496 
497    Notes:
498    This routine is provided for people who need to have direct access
499    to the structure of a matrix.  We hope that we provide enough
500    high-level matrix routines that few users will need it.
501 
502    MatGetRow() always returns 0-based column indices, regardless of
503    whether the internal representation is 0-based (default) or 1-based.
504 
505    For better efficiency, set cols and/or vals to NULL if you do
506    not wish to extract these quantities.
507 
508    The user can only examine the values extracted with MatGetRow();
509    the values cannot be altered.  To change the matrix entries, one
510    must use MatSetValues().
511 
512    You can only have one call to MatGetRow() outstanding for a particular
513    matrix at a time, per processor. MatGetRow() can only obtain rows
514    associated with the given processor, it cannot get rows from the
515    other processors; for that we suggest using MatCreateSubMatrices(), then
516    MatGetRow() on the submatrix. The row index passed to MatGetRow()
517    is in the global number of rows.
518 
519    Fortran Notes:
520    The calling sequence from Fortran is
521 .vb
522    MatGetRow(matrix,row,ncols,cols,values,ierr)
523          Mat     matrix (input)
524          integer row    (input)
525          integer ncols  (output)
526          integer cols(maxcols) (output)
527          double precision (or double complex) values(maxcols) output
528 .ve
529    where maxcols >= maximum nonzeros in any row of the matrix.
530 
531    Caution:
532    Do not try to change the contents of the output arrays (cols and vals).
533    In some cases, this may corrupt the matrix.
534 
535    Level: advanced
536 
537 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`
538 @*/
539 PetscErrorCode MatGetRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
540 {
541   PetscInt incols;
542 
543   PetscFunctionBegin;
544   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
545   PetscValidType(mat,1);
546   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
547   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
548   PetscCheck(mat->ops->getrow,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
549   MatCheckPreallocated(mat,1);
550   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")",row,mat->rmap->rstart,mat->rmap->rend);
551   PetscCall(PetscLogEventBegin(MAT_GetRow,mat,0,0,0));
552   PetscCall((*mat->ops->getrow)(mat,row,&incols,(PetscInt**)cols,(PetscScalar**)vals));
553   if (ncols) *ncols = incols;
554   PetscCall(PetscLogEventEnd(MAT_GetRow,mat,0,0,0));
555   PetscFunctionReturn(0);
556 }
557 
558 /*@
559    MatConjugate - replaces the matrix values with their complex conjugates
560 
561    Logically Collective on Mat
562 
563    Input Parameters:
564 .  mat - the matrix
565 
566    Level: advanced
567 
568 .seealso: `VecConjugate()`
569 @*/
570 PetscErrorCode MatConjugate(Mat mat)
571 {
572   PetscFunctionBegin;
573   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
574   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
575   if (PetscDefined(USE_COMPLEX)) {
576     PetscCheck(mat->ops->conjugate,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not provided for matrix type %s, send email to petsc-maint@mcs.anl.gov",((PetscObject)mat)->type_name);
577     PetscCall((*mat->ops->conjugate)(mat));
578   }
579   PetscFunctionReturn(0);
580 }
581 
582 /*@C
583    MatRestoreRow - Frees any temporary space allocated by MatGetRow().
584 
585    Not Collective
586 
587    Input Parameters:
588 +  mat - the matrix
589 .  row - the row to get
590 .  ncols, cols - the number of nonzeros and their columns
591 -  vals - if nonzero the column values
592 
593    Notes:
594    This routine should be called after you have finished examining the entries.
595 
596    This routine zeros out ncols, cols, and vals. This is to prevent accidental
597    us of the array after it has been restored. If you pass NULL, it will
598    not zero the pointers.  Use of cols or vals after MatRestoreRow is invalid.
599 
600    Fortran Notes:
601    The calling sequence from Fortran is
602 .vb
603    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
604       Mat     matrix (input)
605       integer row    (input)
606       integer ncols  (output)
607       integer cols(maxcols) (output)
608       double precision (or double complex) values(maxcols) output
609 .ve
610    Where maxcols >= maximum nonzeros in any row of the matrix.
611 
612    In Fortran MatRestoreRow() MUST be called after MatGetRow()
613    before another call to MatGetRow() can be made.
614 
615    Level: advanced
616 
617 .seealso: `MatGetRow()`
618 @*/
619 PetscErrorCode MatRestoreRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
620 {
621   PetscFunctionBegin;
622   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
623   if (ncols) PetscValidIntPointer(ncols,3);
624   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
625   if (!mat->ops->restorerow) PetscFunctionReturn(0);
626   PetscCall((*mat->ops->restorerow)(mat,row,ncols,(PetscInt **)cols,(PetscScalar **)vals));
627   if (ncols) *ncols = 0;
628   if (cols)  *cols = NULL;
629   if (vals)  *vals = NULL;
630   PetscFunctionReturn(0);
631 }
632 
633 /*@
634    MatGetRowUpperTriangular - Sets a flag to enable calls to MatGetRow() for matrix in MATSBAIJ format.
635    You should call MatRestoreRowUpperTriangular() after calling MatGetRow/MatRestoreRow() to disable the flag.
636 
637    Not Collective
638 
639    Input Parameters:
640 .  mat - the matrix
641 
642    Notes:
643    The flag is to ensure that users are aware of MatGetRow() only provides the upper triangular part of the row for the matrices in MATSBAIJ format.
644 
645    Level: advanced
646 
647 .seealso: `MatRestoreRowUpperTriangular()`
648 @*/
649 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
650 {
651   PetscFunctionBegin;
652   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
653   PetscValidType(mat,1);
654   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
655   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
656   MatCheckPreallocated(mat,1);
657   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
658   PetscCall((*mat->ops->getrowuppertriangular)(mat));
659   PetscFunctionReturn(0);
660 }
661 
662 /*@
663    MatRestoreRowUpperTriangular - Disable calls to MatGetRow() for matrix in MATSBAIJ format.
664 
665    Not Collective
666 
667    Input Parameters:
668 .  mat - the matrix
669 
670    Notes:
671    This routine should be called after you have finished MatGetRow/MatRestoreRow().
672 
673    Level: advanced
674 
675 .seealso: `MatGetRowUpperTriangular()`
676 @*/
677 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
678 {
679   PetscFunctionBegin;
680   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
681   PetscValidType(mat,1);
682   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
683   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
684   MatCheckPreallocated(mat,1);
685   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
686   PetscCall((*mat->ops->restorerowuppertriangular)(mat));
687   PetscFunctionReturn(0);
688 }
689 
690 /*@C
691    MatSetOptionsPrefix - Sets the prefix used for searching for all
692    Mat options in the database.
693 
694    Logically Collective on Mat
695 
696    Input Parameters:
697 +  A - the Mat context
698 -  prefix - the prefix to prepend to all option names
699 
700    Notes:
701    A hyphen (-) must NOT be given at the beginning of the prefix name.
702    The first character of all runtime options is AUTOMATICALLY the hyphen.
703 
704    This is NOT used for options for the factorization of the matrix. Normally the
705    prefix is automatically passed in from the PC calling the factorization. To set
706    it directly use  `MatSetOptionsPrefixFactor()`
707 
708    Level: advanced
709 
710 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
711 @*/
712 PetscErrorCode MatSetOptionsPrefix(Mat A,const char prefix[])
713 {
714   PetscFunctionBegin;
715   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
716   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A,prefix));
717   PetscFunctionReturn(0);
718 }
719 
720 /*@C
721    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all Mat factor options in the database for
722    for matrices created with `MatGetFactor()`
723 
724    Logically Collective on Mat
725 
726    Input Parameters:
727 +  A - the Mat context
728 -  prefix - the prefix to prepend to all option names for the factored matrix
729 
730    Notes:
731    A hyphen (-) must NOT be given at the beginning of the prefix name.
732    The first character of all runtime options is AUTOMATICALLY the hyphen.
733 
734    Normally the prefix is automatically passed in from the PC calling the factorization. To set
735    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
736 
737    Level: developer
738 
739 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
740 @*/
741 PetscErrorCode MatSetOptionsPrefixFactor(Mat A,const char prefix[])
742 {
743   PetscFunctionBegin;
744   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
745   if (prefix) {
746     PetscValidCharPointer(prefix,2);
747     PetscCheck(prefix[0] != '-',PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
748     if (prefix != A->factorprefix) {
749       PetscCall(PetscFree(A->factorprefix));
750       PetscCall(PetscStrallocpy(prefix,&A->factorprefix));
751     }
752   } else PetscCall(PetscFree(A->factorprefix));
753   PetscFunctionReturn(0);
754 }
755 
756 /*@C
757    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all Mat factor options in the database for
758    for matrices created with `MatGetFactor()`
759 
760    Logically Collective on Mat
761 
762    Input Parameters:
763 +  A - the Mat context
764 -  prefix - the prefix to prepend to all option names for the factored matrix
765 
766    Notes:
767    A hyphen (-) must NOT be given at the beginning of the prefix name.
768    The first character of all runtime options is AUTOMATICALLY the hyphen.
769 
770    Normally the prefix is automatically passed in from the PC calling the factorization. To set
771    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
772 
773    Level: developer
774    .seealso: `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
775              `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
776              `MatSetOptionsPrefix()`
777 @*/
778 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A,const char prefix[])
779 {
780   char           *buf = A->factorprefix;
781   size_t         len1,len2;
782 
783   PetscFunctionBegin;
784   PetscValidHeader(A,1);
785   if (!prefix) PetscFunctionReturn(0);
786   if (!buf) {
787     PetscCall(MatSetOptionsPrefixFactor(A,prefix));
788     PetscFunctionReturn(0);
789   }
790   PetscCheck(prefix[0] != '-',PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
791 
792   PetscCall(PetscStrlen(prefix,&len1));
793   PetscCall(PetscStrlen(buf,&len2));
794   PetscCall(PetscMalloc1(1+len1+len2,&A->factorprefix));
795   PetscCall(PetscStrcpy(A->factorprefix,buf));
796   PetscCall(PetscStrcat(A->factorprefix,prefix));
797   PetscCall(PetscFree(buf));
798   PetscFunctionReturn(0);
799 }
800 
801 /*@C
802    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
803    Mat options in the database.
804 
805    Logically Collective on Mat
806 
807    Input Parameters:
808 +  A - the Mat context
809 -  prefix - the prefix to prepend to all option names
810 
811    Notes:
812    A hyphen (-) must NOT be given at the beginning of the prefix name.
813    The first character of all runtime options is AUTOMATICALLY the hyphen.
814 
815    Level: advanced
816 
817 .seealso: `MatGetOptionsPrefix()`
818 @*/
819 PetscErrorCode MatAppendOptionsPrefix(Mat A,const char prefix[])
820 {
821   PetscFunctionBegin;
822   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
823   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A,prefix));
824   PetscFunctionReturn(0);
825 }
826 
827 /*@C
828    MatGetOptionsPrefix - Gets the prefix used for searching for all
829    Mat options in the database.
830 
831    Not Collective
832 
833    Input Parameter:
834 .  A - the Mat context
835 
836    Output Parameter:
837 .  prefix - pointer to the prefix string used
838 
839    Notes:
840     On the fortran side, the user should pass in a string 'prefix' of
841    sufficient length to hold the prefix.
842 
843    Level: advanced
844 
845 .seealso: `MatAppendOptionsPrefix()`
846 @*/
847 PetscErrorCode MatGetOptionsPrefix(Mat A,const char *prefix[])
848 {
849   PetscFunctionBegin;
850   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
851   PetscValidPointer(prefix,2);
852   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A,prefix));
853   PetscFunctionReturn(0);
854 }
855 
856 /*@
857    MatResetPreallocation - Reset mat to use the original nonzero pattern provided by users.
858 
859    Collective on Mat
860 
861    Input Parameters:
862 .  A - the Mat context
863 
864    Notes:
865    The allocated memory will be shrunk after calling MatAssembly with MAT_FINAL_ASSEMBLY. Users can reset the preallocation to access the original memory.
866    Currently support MPIAIJ and SEQAIJ.
867 
868    Level: beginner
869 
870 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
871 @*/
872 PetscErrorCode MatResetPreallocation(Mat A)
873 {
874   PetscFunctionBegin;
875   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
876   PetscValidType(A,1);
877   PetscUseMethod(A,"MatResetPreallocation_C",(Mat),(A));
878   PetscFunctionReturn(0);
879 }
880 
881 /*@
882    MatSetUp - Sets up the internal matrix data structures for later use.
883 
884    Collective on Mat
885 
886    Input Parameters:
887 .  A - the Mat context
888 
889    Notes:
890    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
891 
892    If a suitable preallocation routine is used, this function does not need to be called.
893 
894    See the Performance chapter of the PETSc users manual for how to preallocate matrices
895 
896    Level: beginner
897 
898 .seealso: `MatCreate()`, `MatDestroy()`
899 @*/
900 PetscErrorCode MatSetUp(Mat A)
901 {
902   PetscFunctionBegin;
903   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
904   if (!((PetscObject)A)->type_name) {
905     PetscMPIInt size;
906 
907     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
908     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
909   }
910   if (!A->preallocated && A->ops->setup) {
911     PetscCall(PetscInfo(A,"Warning not preallocating matrix storage\n"));
912     PetscCall((*A->ops->setup)(A));
913   }
914   PetscCall(PetscLayoutSetUp(A->rmap));
915   PetscCall(PetscLayoutSetUp(A->cmap));
916   A->preallocated = PETSC_TRUE;
917   PetscFunctionReturn(0);
918 }
919 
920 #if defined(PETSC_HAVE_SAWS)
921 #include <petscviewersaws.h>
922 #endif
923 
924 /*@C
925    MatViewFromOptions - View from Options
926 
927    Collective on Mat
928 
929    Input Parameters:
930 +  A - the Mat context
931 .  obj - Optional object
932 -  name - command line option
933 
934    Level: intermediate
935 .seealso: `Mat`, `MatView`, `PetscObjectViewFromOptions()`, `MatCreate()`
936 @*/
937 PetscErrorCode  MatViewFromOptions(Mat A,PetscObject obj,const char name[])
938 {
939   PetscFunctionBegin;
940   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
941   PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name));
942   PetscFunctionReturn(0);
943 }
944 
945 /*@C
946    MatView - Visualizes a matrix object.
947 
948    Collective on Mat
949 
950    Input Parameters:
951 +  mat - the matrix
952 -  viewer - visualization context
953 
954   Notes:
955   The available visualization contexts include
956 +    PETSC_VIEWER_STDOUT_SELF - for sequential matrices
957 .    PETSC_VIEWER_STDOUT_WORLD - for parallel matrices created on PETSC_COMM_WORLD
958 .    PETSC_VIEWER_STDOUT_(comm) - for matrices created on MPI communicator comm
959 -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
960 
961    The user can open alternative visualization contexts with
962 +    PetscViewerASCIIOpen() - Outputs matrix to a specified file
963 .    PetscViewerBinaryOpen() - Outputs matrix in binary to a
964          specified file; corresponding input uses MatLoad()
965 .    PetscViewerDrawOpen() - Outputs nonzero matrix structure to
966          an X window display
967 -    PetscViewerSocketOpen() - Outputs matrix to Socket viewer.
968          Currently only the sequential dense and AIJ
969          matrix types support the Socket viewer.
970 
971    The user can call PetscViewerPushFormat() to specify the output
972    format of ASCII printed objects (when using PETSC_VIEWER_STDOUT_SELF,
973    PETSC_VIEWER_STDOUT_WORLD and PetscViewerASCIIOpen).  Available formats include
974 +    PETSC_VIEWER_DEFAULT - default, prints matrix contents
975 .    PETSC_VIEWER_ASCII_MATLAB - prints matrix contents in Matlab format
976 .    PETSC_VIEWER_ASCII_DENSE - prints entire matrix including zeros
977 .    PETSC_VIEWER_ASCII_COMMON - prints matrix contents, using a sparse
978          format common among all matrix types
979 .    PETSC_VIEWER_ASCII_IMPL - prints matrix contents, using an implementation-specific
980          format (which is in many cases the same as the default)
981 .    PETSC_VIEWER_ASCII_INFO - prints basic information about the matrix
982          size and structure (not the matrix entries)
983 -    PETSC_VIEWER_ASCII_INFO_DETAIL - prints more detailed information about
984          the matrix structure
985 
986    Options Database Keys:
987 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatAssemblyEnd()
988 .  -mat_view ::ascii_info_detail - Prints more detailed info
989 .  -mat_view - Prints matrix in ASCII format
990 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
991 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
992 .  -display <name> - Sets display name (default is host)
993 .  -draw_pause <sec> - Sets number of seconds to pause after display
994 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
995 .  -viewer_socket_machine <machine> -
996 .  -viewer_socket_port <port> -
997 .  -mat_view binary - save matrix to file in binary format
998 -  -viewer_binary_filename <name> -
999 
1000    Level: beginner
1001 
1002    Notes:
1003     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1004     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1005 
1006     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1007 
1008     See the manual page for MatLoad() for the exact format of the binary file when the binary
1009       viewer is used.
1010 
1011       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1012       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1013 
1014       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1015       and then use the following mouse functions.
1016 .vb
1017   left mouse: zoom in
1018   middle mouse: zoom out
1019   right mouse: continue with the simulation
1020 .ve
1021 
1022 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`,
1023           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`
1024 @*/
1025 PetscErrorCode MatView(Mat mat,PetscViewer viewer)
1026 {
1027   PetscInt          rows,cols,rbs,cbs;
1028   PetscBool         isascii,isstring,issaws;
1029   PetscViewerFormat format;
1030   PetscMPIInt       size;
1031 
1032   PetscFunctionBegin;
1033   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1034   PetscValidType(mat,1);
1035   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat),&viewer));
1036   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1037   PetscCheckSameComm(mat,1,viewer,2);
1038   MatCheckPreallocated(mat,1);
1039 
1040   PetscCall(PetscViewerGetFormat(viewer,&format));
1041   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
1042   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1043 
1044   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring));
1045   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
1046   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws));
1047   if ((!isascii || (format != PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) && mat->factortype) {
1048     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"No viewers for factored matrix except ASCII info or info_detail");
1049   }
1050 
1051   PetscCall(PetscLogEventBegin(MAT_View,mat,viewer,0,0));
1052   if (isascii) {
1053     PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Must call MatAssemblyBegin/End() before viewing matrix");
1054     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat,viewer));
1055     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1056       MatNullSpace nullsp,transnullsp;
1057 
1058       PetscCall(PetscViewerASCIIPushTab(viewer));
1059       PetscCall(MatGetSize(mat,&rows,&cols));
1060       PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
1061       if (rbs != 1 || cbs != 1) {
1062         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n",rows,cols,rbs,cbs));
1063         else            PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n",rows,cols,rbs));
1064       } else PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n",rows,cols));
1065       if (mat->factortype) {
1066         MatSolverType solver;
1067         PetscCall(MatFactorGetSolverType(mat,&solver));
1068         PetscCall(PetscViewerASCIIPrintf(viewer,"package used to perform factorization: %s\n",solver));
1069       }
1070       if (mat->ops->getinfo) {
1071         MatInfo info;
1072         PetscCall(MatGetInfo(mat,MAT_GLOBAL_SUM,&info));
1073         PetscCall(PetscViewerASCIIPrintf(viewer,"total: nonzeros=%.f, allocated nonzeros=%.f\n",info.nz_used,info.nz_allocated));
1074         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer,"total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n",(PetscInt)info.mallocs));
1075       }
1076       PetscCall(MatGetNullSpace(mat,&nullsp));
1077       PetscCall(MatGetTransposeNullSpace(mat,&transnullsp));
1078       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached null space\n"));
1079       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached transposed null space\n"));
1080       PetscCall(MatGetNearNullSpace(mat,&nullsp));
1081       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached near null space\n"));
1082       PetscCall(PetscViewerASCIIPushTab(viewer));
1083       PetscCall(MatProductView(mat,viewer));
1084       PetscCall(PetscViewerASCIIPopTab(viewer));
1085     }
1086   } else if (issaws) {
1087 #if defined(PETSC_HAVE_SAWS)
1088     PetscMPIInt rank;
1089 
1090     PetscCall(PetscObjectName((PetscObject)mat));
1091     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
1092     if (!((PetscObject)mat)->amsmem && rank == 0) {
1093       PetscCall(PetscObjectViewSAWs((PetscObject)mat,viewer));
1094     }
1095 #endif
1096   } else if (isstring) {
1097     const char *type;
1098     PetscCall(MatGetType(mat,&type));
1099     PetscCall(PetscViewerStringSPrintf(viewer," MatType: %-7.7s",type));
1100     if (mat->ops->view) PetscCall((*mat->ops->view)(mat,viewer));
1101   }
1102   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1103     PetscCall(PetscViewerASCIIPushTab(viewer));
1104     PetscCall((*mat->ops->viewnative)(mat,viewer));
1105     PetscCall(PetscViewerASCIIPopTab(viewer));
1106   } else if (mat->ops->view) {
1107     PetscCall(PetscViewerASCIIPushTab(viewer));
1108     PetscCall((*mat->ops->view)(mat,viewer));
1109     PetscCall(PetscViewerASCIIPopTab(viewer));
1110   }
1111   if (isascii) {
1112     PetscCall(PetscViewerGetFormat(viewer,&format));
1113     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1114       PetscCall(PetscViewerASCIIPopTab(viewer));
1115     }
1116   }
1117   PetscCall(PetscLogEventEnd(MAT_View,mat,viewer,0,0));
1118   PetscFunctionReturn(0);
1119 }
1120 
1121 #if defined(PETSC_USE_DEBUG)
1122 #include <../src/sys/totalview/tv_data_display.h>
1123 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1124 {
1125   TV_add_row("Local rows", "int", &mat->rmap->n);
1126   TV_add_row("Local columns", "int", &mat->cmap->n);
1127   TV_add_row("Global rows", "int", &mat->rmap->N);
1128   TV_add_row("Global columns", "int", &mat->cmap->N);
1129   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1130   return TV_format_OK;
1131 }
1132 #endif
1133 
1134 /*@C
1135    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1136    with MatView().  The matrix format is determined from the options database.
1137    Generates a parallel MPI matrix if the communicator has more than one
1138    processor.  The default matrix type is AIJ.
1139 
1140    Collective on PetscViewer
1141 
1142    Input Parameters:
1143 +  mat - the newly loaded matrix, this needs to have been created with MatCreate()
1144             or some related function before a call to MatLoad()
1145 -  viewer - binary/HDF5 file viewer
1146 
1147    Options Database Keys:
1148    Used with block matrix formats (MATSEQBAIJ,  ...) to specify
1149    block size
1150 .    -matload_block_size <bs> - set block size
1151 
1152    Level: beginner
1153 
1154    Notes:
1155    If the Mat type has not yet been given then MATAIJ is used, call MatSetFromOptions() on the
1156    Mat before calling this routine if you wish to set it from the options database.
1157 
1158    MatLoad() automatically loads into the options database any options
1159    given in the file filename.info where filename is the name of the file
1160    that was passed to the PetscViewerBinaryOpen(). The options in the info
1161    file will be ignored if you use the -viewer_binary_skip_info option.
1162 
1163    If the type or size of mat is not set before a call to MatLoad, PETSc
1164    sets the default matrix type AIJ and sets the local and global sizes.
1165    If type and/or size is already set, then the same are used.
1166 
1167    In parallel, each processor can load a subset of rows (or the
1168    entire matrix).  This routine is especially useful when a large
1169    matrix is stored on disk and only part of it is desired on each
1170    processor.  For example, a parallel solver may access only some of
1171    the rows from each processor.  The algorithm used here reads
1172    relatively small blocks of data rather than reading the entire
1173    matrix and then subsetting it.
1174 
1175    Viewer's PetscViewerType must be either PETSCVIEWERBINARY or PETSCVIEWERHDF5.
1176    Such viewer can be created using PetscViewerBinaryOpen()/PetscViewerHDF5Open(),
1177    or the sequence like
1178 $    PetscViewer v;
1179 $    PetscViewerCreate(PETSC_COMM_WORLD,&v);
1180 $    PetscViewerSetType(v,PETSCVIEWERBINARY);
1181 $    PetscViewerSetFromOptions(v);
1182 $    PetscViewerFileSetMode(v,FILE_MODE_READ);
1183 $    PetscViewerFileSetName(v,"datafile");
1184    The optional PetscViewerSetFromOptions() call allows to override PetscViewerSetType() using option
1185 $ -viewer_type {binary,hdf5}
1186 
1187    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1188    and src/mat/tutorials/ex10.c with the second approach.
1189 
1190    Notes about the PETSc binary format:
1191    In case of PETSCVIEWERBINARY, a native PETSc binary format is used. Each of the blocks
1192    is read onto rank 0 and then shipped to its destination rank, one after another.
1193    Multiple objects, both matrices and vectors, can be stored within the same file.
1194    Their PetscObject name is ignored; they are loaded in the order of their storage.
1195 
1196    Most users should not need to know the details of the binary storage
1197    format, since MatLoad() and MatView() completely hide these details.
1198    But for anyone who's interested, the standard binary matrix storage
1199    format is
1200 
1201 $    PetscInt    MAT_FILE_CLASSID
1202 $    PetscInt    number of rows
1203 $    PetscInt    number of columns
1204 $    PetscInt    total number of nonzeros
1205 $    PetscInt    *number nonzeros in each row
1206 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1207 $    PetscScalar *values of all nonzeros
1208 
1209    PETSc automatically does the byte swapping for
1210 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1211 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1212 read/write routines you have to swap the bytes; see PetscBinaryRead()
1213 and PetscBinaryWrite() to see how this may be done.
1214 
1215    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1216    In case of PETSCVIEWERHDF5, a parallel HDF5 reader is used.
1217    Each processor's chunk is loaded independently by its owning rank.
1218    Multiple objects, both matrices and vectors, can be stored within the same file.
1219    They are looked up by their PetscObject name.
1220 
1221    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1222    by default the same structure and naming of the AIJ arrays and column count
1223    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1224 $    save example.mat A b -v7.3
1225    can be directly read by this routine (see Reference 1 for details).
1226    Note that depending on your MATLAB version, this format might be a default,
1227    otherwise you can set it as default in Preferences.
1228 
1229    Unless -nocompression flag is used to save the file in MATLAB,
1230    PETSc must be configured with ZLIB package.
1231 
1232    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1233 
1234    Current HDF5 (MAT-File) limitations:
1235    This reader currently supports only real MATSEQAIJ, MATMPIAIJ, MATSEQDENSE and MATMPIDENSE matrices.
1236 
1237    Corresponding MatView() is not yet implemented.
1238 
1239    The loaded matrix is actually a transpose of the original one in MATLAB,
1240    unless you push PETSC_VIEWER_HDF5_MAT format (see examples above).
1241    With this format, matrix is automatically transposed by PETSc,
1242    unless the matrix is marked as SPD or symmetric
1243    (see MatSetOption(), MAT_SPD, MAT_SYMMETRIC).
1244 
1245    References:
1246 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1247 
1248 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1249 
1250  @*/
1251 PetscErrorCode MatLoad(Mat mat,PetscViewer viewer)
1252 {
1253   PetscBool flg;
1254 
1255   PetscFunctionBegin;
1256   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1257   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1258 
1259   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat,MATAIJ));
1260 
1261   flg  = PETSC_FALSE;
1262   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matload_symmetric",&flg,NULL));
1263   if (flg) {
1264     PetscCall(MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE));
1265     PetscCall(MatSetOption(mat,MAT_SYMMETRY_ETERNAL,PETSC_TRUE));
1266   }
1267   flg  = PETSC_FALSE;
1268   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matload_spd",&flg,NULL));
1269   if (flg) PetscCall(MatSetOption(mat,MAT_SPD,PETSC_TRUE));
1270 
1271   PetscCheck(mat->ops->load,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatLoad is not supported for type %s",((PetscObject)mat)->type_name);
1272   PetscCall(PetscLogEventBegin(MAT_Load,mat,viewer,0,0));
1273   PetscCall((*mat->ops->load)(mat,viewer));
1274   PetscCall(PetscLogEventEnd(MAT_Load,mat,viewer,0,0));
1275   PetscFunctionReturn(0);
1276 }
1277 
1278 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1279 {
1280   Mat_Redundant *redund = *redundant;
1281 
1282   PetscFunctionBegin;
1283   if (redund) {
1284     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1285       PetscCall(ISDestroy(&redund->isrow));
1286       PetscCall(ISDestroy(&redund->iscol));
1287       PetscCall(MatDestroySubMatrices(1,&redund->matseq));
1288     } else {
1289       PetscCall(PetscFree2(redund->send_rank,redund->recv_rank));
1290       PetscCall(PetscFree(redund->sbuf_j));
1291       PetscCall(PetscFree(redund->sbuf_a));
1292       for (PetscInt i=0; i<redund->nrecvs; i++) {
1293         PetscCall(PetscFree(redund->rbuf_j[i]));
1294         PetscCall(PetscFree(redund->rbuf_a[i]));
1295       }
1296       PetscCall(PetscFree4(redund->sbuf_nz,redund->rbuf_nz,redund->rbuf_j,redund->rbuf_a));
1297     }
1298 
1299     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1300     PetscCall(PetscFree(redund));
1301   }
1302   PetscFunctionReturn(0);
1303 }
1304 
1305 /*@C
1306    MatDestroy - Frees space taken by a matrix.
1307 
1308    Collective on Mat
1309 
1310    Input Parameter:
1311 .  A - the matrix
1312 
1313    Level: beginner
1314 
1315    Developer Notes:
1316    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1317    MatDestroySubMatrices(). Thus one must be sure that any changes here must also be made in those routines.
1318    MatHeaderMerge() and MatHeaderReplace() also manipulate the data in the Mat object and likely need changes
1319    if changes are needed here.
1320 @*/
1321 PetscErrorCode MatDestroy(Mat *A)
1322 {
1323   PetscFunctionBegin;
1324   if (!*A) PetscFunctionReturn(0);
1325   PetscValidHeaderSpecific(*A,MAT_CLASSID,1);
1326   if (--((PetscObject)(*A))->refct > 0) {*A = NULL; PetscFunctionReturn(0);}
1327 
1328   /* if memory was published with SAWs then destroy it */
1329   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1330   if ((*A)->ops->destroy) PetscCall((*(*A)->ops->destroy)(*A));
1331 
1332   PetscCall(PetscFree((*A)->factorprefix));
1333   PetscCall(PetscFree((*A)->defaultvectype));
1334   PetscCall(PetscFree((*A)->bsizes));
1335   PetscCall(PetscFree((*A)->solvertype));
1336   for (PetscInt i=0; i<MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1337   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1338   PetscCall(MatProductClear(*A));
1339   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1340   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1341   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1342   PetscCall(MatDestroy(&(*A)->schur));
1343   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1344   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1345   PetscCall(PetscHeaderDestroy(A));
1346   PetscFunctionReturn(0);
1347 }
1348 
1349 /*@C
1350    MatSetValues - Inserts or adds a block of values into a matrix.
1351    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
1352    MUST be called after all calls to MatSetValues() have been completed.
1353 
1354    Not Collective
1355 
1356    Input Parameters:
1357 +  mat - the matrix
1358 .  v - a logically two-dimensional array of values
1359 .  m, idxm - the number of rows and their global indices
1360 .  n, idxn - the number of columns and their global indices
1361 -  addv - either ADD_VALUES or INSERT_VALUES, where
1362    ADD_VALUES adds values to any existing entries, and
1363    INSERT_VALUES replaces existing entries with new values
1364 
1365    Notes:
1366    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
1367       MatSetUp() before using this routine
1368 
1369    By default the values, v, are row-oriented. See MatSetOption() for other options.
1370 
1371    Calls to MatSetValues() with the INSERT_VALUES and ADD_VALUES
1372    options cannot be mixed without intervening calls to the assembly
1373    routines.
1374 
1375    MatSetValues() uses 0-based row and column numbers in Fortran
1376    as well as in C.
1377 
1378    Negative indices may be passed in idxm and idxn, these rows and columns are
1379    simply ignored. This allows easily inserting element stiffness matrices
1380    with homogeneous Dirchlet boundary conditions that you don't want represented
1381    in the matrix.
1382 
1383    Efficiency Alert:
1384    The routine MatSetValuesBlocked() may offer much better efficiency
1385    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1386 
1387    Level: beginner
1388 
1389    Developer Notes:
1390     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1391                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1392 
1393 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1394           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1395 @*/
1396 PetscErrorCode MatSetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1397 {
1398   PetscFunctionBeginHot;
1399   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1400   PetscValidType(mat,1);
1401   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1402   PetscValidIntPointer(idxm,3);
1403   PetscValidIntPointer(idxn,5);
1404   MatCheckPreallocated(mat,1);
1405 
1406   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1407   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1408 
1409   if (PetscDefined(USE_DEBUG)) {
1410     PetscInt       i,j;
1411 
1412     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1413     PetscCheck(mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1414 
1415     for (i=0; i<m; i++) {
1416       for (j=0; j<n; j++) {
1417         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i*n+j]))
1418 #if defined(PETSC_USE_COMPLEX)
1419           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")",(double)PetscRealPart(v[i*n+j]),(double)PetscImaginaryPart(v[i*n+j]),idxm[i],idxn[j]);
1420 #else
1421           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")",(double)v[i*n+j],idxm[i],idxn[j]);
1422 #endif
1423       }
1424     }
1425     for (i=0; i<m; i++) PetscCheck(idxm[i] < mat->rmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT,idxm[i],mat->rmap->N-1);
1426     for (i=0; i<n; i++) PetscCheck(idxn[i] < mat->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT,idxn[i],mat->cmap->N-1);
1427   }
1428 
1429   if (mat->assembled) {
1430     mat->was_assembled = PETSC_TRUE;
1431     mat->assembled     = PETSC_FALSE;
1432   }
1433   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1434   PetscCall((*mat->ops->setvalues)(mat,m,idxm,n,idxn,v,addv));
1435   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1436   PetscFunctionReturn(0);
1437 }
1438 
1439 /*@C
1440    MatSetValuesIS - Inserts or adds a block of values into a matrix using IS to indicate the rows and columns
1441    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
1442    MUST be called after all calls to MatSetValues() have been completed.
1443 
1444    Not Collective
1445 
1446    Input Parameters:
1447 +  mat - the matrix
1448 .  v - a logically two-dimensional array of values
1449 .  ism - the rows to provide
1450 .  isn - the columns to provide
1451 -  addv - either ADD_VALUES or INSERT_VALUES, where
1452    ADD_VALUES adds values to any existing entries, and
1453    INSERT_VALUES replaces existing entries with new values
1454 
1455    Notes:
1456    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
1457       MatSetUp() before using this routine
1458 
1459    By default the values, v, are row-oriented. See MatSetOption() for other options.
1460 
1461    Calls to MatSetValues() with the INSERT_VALUES and ADD_VALUES
1462    options cannot be mixed without intervening calls to the assembly
1463    routines.
1464 
1465    MatSetValues() uses 0-based row and column numbers in Fortran
1466    as well as in C.
1467 
1468    Negative indices may be passed in ism and isn, these rows and columns are
1469    simply ignored. This allows easily inserting element stiffness matrices
1470    with homogeneous Dirchlet boundary conditions that you don't want represented
1471    in the matrix.
1472 
1473    Efficiency Alert:
1474    The routine MatSetValuesBlocked() may offer much better efficiency
1475    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1476 
1477    Level: beginner
1478 
1479    Developer Notes:
1480     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1481                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1482 
1483     This is currently not optimized for any particular IS type
1484 
1485 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal(),
1486           InsertMode, INSERT_VALUES, ADD_VALUES, MatSetValues()
1487 @*/
1488 PetscErrorCode MatSetValuesIS(Mat mat,IS ism,IS isn,const PetscScalar v[],InsertMode addv)
1489 {
1490   PetscInt       m,n;
1491   const PetscInt *rows,*cols;
1492 
1493   PetscFunctionBeginHot;
1494   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1495   PetscCall(ISGetIndices(ism,&rows));
1496   PetscCall(ISGetIndices(isn,&cols));
1497   PetscCall(ISGetLocalSize(ism,&m));
1498   PetscCall(ISGetLocalSize(isn,&n));
1499   PetscCall(MatSetValues(mat,m,rows,n,cols,v,addv));
1500   PetscCall(ISRestoreIndices(ism,&rows));
1501   PetscCall(ISRestoreIndices(isn,&cols));
1502   PetscFunctionReturn(0);
1503 }
1504 
1505 /*@
1506    MatSetValuesRowLocal - Inserts a row (block row for BAIJ matrices) of nonzero
1507         values into a matrix
1508 
1509    Not Collective
1510 
1511    Input Parameters:
1512 +  mat - the matrix
1513 .  row - the (block) row to set
1514 -  v - a logically two-dimensional array of values
1515 
1516    Notes:
1517    By the values, v, are column-oriented (for the block version) and sorted
1518 
1519    All the nonzeros in the row must be provided
1520 
1521    The matrix must have previously had its column indices set
1522 
1523    The row must belong to this process
1524 
1525    Level: intermediate
1526 
1527 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1528           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1529 @*/
1530 PetscErrorCode MatSetValuesRowLocal(Mat mat,PetscInt row,const PetscScalar v[])
1531 {
1532   PetscInt globalrow;
1533 
1534   PetscFunctionBegin;
1535   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1536   PetscValidType(mat,1);
1537   PetscValidScalarPointer(v,3);
1538   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,1,&row,&globalrow));
1539   PetscCall(MatSetValuesRow(mat,globalrow,v));
1540   PetscFunctionReturn(0);
1541 }
1542 
1543 /*@
1544    MatSetValuesRow - Inserts a row (block row for BAIJ matrices) of nonzero
1545         values into a matrix
1546 
1547    Not Collective
1548 
1549    Input Parameters:
1550 +  mat - the matrix
1551 .  row - the (block) row to set
1552 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1553 
1554    Notes:
1555    The values, v, are column-oriented for the block version.
1556 
1557    All the nonzeros in the row must be provided
1558 
1559    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually MatSetValues() is used.
1560 
1561    The row must belong to this process
1562 
1563    Level: advanced
1564 
1565 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1566           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1567 @*/
1568 PetscErrorCode MatSetValuesRow(Mat mat,PetscInt row,const PetscScalar v[])
1569 {
1570   PetscFunctionBeginHot;
1571   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1572   PetscValidType(mat,1);
1573   MatCheckPreallocated(mat,1);
1574   PetscValidScalarPointer(v,3);
1575   PetscCheck(mat->insertmode != ADD_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add and insert values");
1576   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1577   mat->insertmode = INSERT_VALUES;
1578 
1579   if (mat->assembled) {
1580     mat->was_assembled = PETSC_TRUE;
1581     mat->assembled     = PETSC_FALSE;
1582   }
1583   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1584   PetscCheck(mat->ops->setvaluesrow,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1585   PetscCall((*mat->ops->setvaluesrow)(mat,row,v));
1586   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1587   PetscFunctionReturn(0);
1588 }
1589 
1590 /*@
1591    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1592      Using structured grid indexing
1593 
1594    Not Collective
1595 
1596    Input Parameters:
1597 +  mat - the matrix
1598 .  m - number of rows being entered
1599 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1600 .  n - number of columns being entered
1601 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1602 .  v - a logically two-dimensional array of values
1603 -  addv - either ADD_VALUES or INSERT_VALUES, where
1604    ADD_VALUES adds values to any existing entries, and
1605    INSERT_VALUES replaces existing entries with new values
1606 
1607    Notes:
1608    By default the values, v, are row-oriented.  See MatSetOption() for other options.
1609 
1610    Calls to MatSetValuesStencil() with the INSERT_VALUES and ADD_VALUES
1611    options cannot be mixed without intervening calls to the assembly
1612    routines.
1613 
1614    The grid coordinates are across the entire grid, not just the local portion
1615 
1616    MatSetValuesStencil() uses 0-based row and column numbers in Fortran
1617    as well as in C.
1618 
1619    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1620 
1621    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1622    or call MatSetLocalToGlobalMapping() and MatSetStencil() first.
1623 
1624    The columns and rows in the stencil passed in MUST be contained within the
1625    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1626    if you create a DMDA with an overlap of one grid level and on a particular process its first
1627    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1628    first i index you can use in your column and row indices in MatSetStencil() is 5.
1629 
1630    In Fortran idxm and idxn should be declared as
1631 $     MatStencil idxm(4,m),idxn(4,n)
1632    and the values inserted using
1633 $    idxm(MatStencil_i,1) = i
1634 $    idxm(MatStencil_j,1) = j
1635 $    idxm(MatStencil_k,1) = k
1636 $    idxm(MatStencil_c,1) = c
1637    etc
1638 
1639    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1640    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1641    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1642    DM_BOUNDARY_PERIODIC boundary type.
1643 
1644    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1645    a single value per point) you can skip filling those indices.
1646 
1647    Inspired by the structured grid interface to the HYPRE package
1648    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1649 
1650    Efficiency Alert:
1651    The routine MatSetValuesBlockedStencil() may offer much better efficiency
1652    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1653 
1654    Level: beginner
1655 
1656 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1657           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1658 @*/
1659 PetscErrorCode MatSetValuesStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1660 {
1661   PetscInt       buf[8192],*bufm=NULL,*bufn=NULL,*jdxm,*jdxn;
1662   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1663   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1664 
1665   PetscFunctionBegin;
1666   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1667   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1668   PetscValidType(mat,1);
1669   PetscValidPointer(idxm,3);
1670   PetscValidPointer(idxn,5);
1671 
1672   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1673     jdxm = buf; jdxn = buf+m;
1674   } else {
1675     PetscCall(PetscMalloc2(m,&bufm,n,&bufn));
1676     jdxm = bufm; jdxn = bufn;
1677   }
1678   for (i=0; i<m; i++) {
1679     for (j=0; j<3-sdim; j++) dxm++;
1680     tmp = *dxm++ - starts[0];
1681     for (j=0; j<dim-1; j++) {
1682       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1683       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1684     }
1685     if (mat->stencil.noc) dxm++;
1686     jdxm[i] = tmp;
1687   }
1688   for (i=0; i<n; i++) {
1689     for (j=0; j<3-sdim; j++) dxn++;
1690     tmp = *dxn++ - starts[0];
1691     for (j=0; j<dim-1; j++) {
1692       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1693       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1694     }
1695     if (mat->stencil.noc) dxn++;
1696     jdxn[i] = tmp;
1697   }
1698   PetscCall(MatSetValuesLocal(mat,m,jdxm,n,jdxn,v,addv));
1699   PetscCall(PetscFree2(bufm,bufn));
1700   PetscFunctionReturn(0);
1701 }
1702 
1703 /*@
1704    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1705      Using structured grid indexing
1706 
1707    Not Collective
1708 
1709    Input Parameters:
1710 +  mat - the matrix
1711 .  m - number of rows being entered
1712 .  idxm - grid coordinates for matrix rows being entered
1713 .  n - number of columns being entered
1714 .  idxn - grid coordinates for matrix columns being entered
1715 .  v - a logically two-dimensional array of values
1716 -  addv - either ADD_VALUES or INSERT_VALUES, where
1717    ADD_VALUES adds values to any existing entries, and
1718    INSERT_VALUES replaces existing entries with new values
1719 
1720    Notes:
1721    By default the values, v, are row-oriented and unsorted.
1722    See MatSetOption() for other options.
1723 
1724    Calls to MatSetValuesBlockedStencil() with the INSERT_VALUES and ADD_VALUES
1725    options cannot be mixed without intervening calls to the assembly
1726    routines.
1727 
1728    The grid coordinates are across the entire grid, not just the local portion
1729 
1730    MatSetValuesBlockedStencil() uses 0-based row and column numbers in Fortran
1731    as well as in C.
1732 
1733    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1734 
1735    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1736    or call MatSetBlockSize(), MatSetLocalToGlobalMapping() and MatSetStencil() first.
1737 
1738    The columns and rows in the stencil passed in MUST be contained within the
1739    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1740    if you create a DMDA with an overlap of one grid level and on a particular process its first
1741    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1742    first i index you can use in your column and row indices in MatSetStencil() is 5.
1743 
1744    In Fortran idxm and idxn should be declared as
1745 $     MatStencil idxm(4,m),idxn(4,n)
1746    and the values inserted using
1747 $    idxm(MatStencil_i,1) = i
1748 $    idxm(MatStencil_j,1) = j
1749 $    idxm(MatStencil_k,1) = k
1750    etc
1751 
1752    Negative indices may be passed in idxm and idxn, these rows and columns are
1753    simply ignored. This allows easily inserting element stiffness matrices
1754    with homogeneous Dirchlet boundary conditions that you don't want represented
1755    in the matrix.
1756 
1757    Inspired by the structured grid interface to the HYPRE package
1758    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1759 
1760    Level: beginner
1761 
1762 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1763           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1764           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1765 @*/
1766 PetscErrorCode MatSetValuesBlockedStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1767 {
1768   PetscInt       buf[8192],*bufm=NULL,*bufn=NULL,*jdxm,*jdxn;
1769   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1770   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1771 
1772   PetscFunctionBegin;
1773   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1774   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1775   PetscValidType(mat,1);
1776   PetscValidPointer(idxm,3);
1777   PetscValidPointer(idxn,5);
1778   PetscValidScalarPointer(v,6);
1779 
1780   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1781     jdxm = buf; jdxn = buf+m;
1782   } else {
1783     PetscCall(PetscMalloc2(m,&bufm,n,&bufn));
1784     jdxm = bufm; jdxn = bufn;
1785   }
1786   for (i=0; i<m; i++) {
1787     for (j=0; j<3-sdim; j++) dxm++;
1788     tmp = *dxm++ - starts[0];
1789     for (j=0; j<sdim-1; j++) {
1790       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1791       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1792     }
1793     dxm++;
1794     jdxm[i] = tmp;
1795   }
1796   for (i=0; i<n; i++) {
1797     for (j=0; j<3-sdim; j++) dxn++;
1798     tmp = *dxn++ - starts[0];
1799     for (j=0; j<sdim-1; j++) {
1800       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1801       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1802     }
1803     dxn++;
1804     jdxn[i] = tmp;
1805   }
1806   PetscCall(MatSetValuesBlockedLocal(mat,m,jdxm,n,jdxn,v,addv));
1807   PetscCall(PetscFree2(bufm,bufn));
1808   PetscFunctionReturn(0);
1809 }
1810 
1811 /*@
1812    MatSetStencil - Sets the grid information for setting values into a matrix via
1813         MatSetValuesStencil()
1814 
1815    Not Collective
1816 
1817    Input Parameters:
1818 +  mat - the matrix
1819 .  dim - dimension of the grid 1, 2, or 3
1820 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1821 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1822 -  dof - number of degrees of freedom per node
1823 
1824    Inspired by the structured grid interface to the HYPRE package
1825    (www.llnl.gov/CASC/hyper)
1826 
1827    For matrices generated with DMCreateMatrix() this routine is automatically called and so not needed by the
1828    user.
1829 
1830    Level: beginner
1831 
1832 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1833           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1834 @*/
1835 PetscErrorCode MatSetStencil(Mat mat,PetscInt dim,const PetscInt dims[],const PetscInt starts[],PetscInt dof)
1836 {
1837   PetscFunctionBegin;
1838   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1839   PetscValidIntPointer(dims,3);
1840   PetscValidIntPointer(starts,4);
1841 
1842   mat->stencil.dim = dim + (dof > 1);
1843   for (PetscInt i=0; i<dim; i++) {
1844     mat->stencil.dims[i]   = dims[dim-i-1];      /* copy the values in backwards */
1845     mat->stencil.starts[i] = starts[dim-i-1];
1846   }
1847   mat->stencil.dims[dim]   = dof;
1848   mat->stencil.starts[dim] = 0;
1849   mat->stencil.noc         = (PetscBool)(dof == 1);
1850   PetscFunctionReturn(0);
1851 }
1852 
1853 /*@C
1854    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1855 
1856    Not Collective
1857 
1858    Input Parameters:
1859 +  mat - the matrix
1860 .  v - a logically two-dimensional array of values
1861 .  m, idxm - the number of block rows and their global block indices
1862 .  n, idxn - the number of block columns and their global block indices
1863 -  addv - either ADD_VALUES or INSERT_VALUES, where
1864    ADD_VALUES adds values to any existing entries, and
1865    INSERT_VALUES replaces existing entries with new values
1866 
1867    Notes:
1868    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call
1869    MatXXXXSetPreallocation() or MatSetUp() before using this routine.
1870 
1871    The m and n count the NUMBER of blocks in the row direction and column direction,
1872    NOT the total number of rows/columns; for example, if the block size is 2 and
1873    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1874    The values in idxm would be 1 2; that is the first index for each block divided by
1875    the block size.
1876 
1877    Note that you must call MatSetBlockSize() when constructing this matrix (before
1878    preallocating it).
1879 
1880    By default the values, v, are row-oriented, so the layout of
1881    v is the same as for MatSetValues(). See MatSetOption() for other options.
1882 
1883    Calls to MatSetValuesBlocked() with the INSERT_VALUES and ADD_VALUES
1884    options cannot be mixed without intervening calls to the assembly
1885    routines.
1886 
1887    MatSetValuesBlocked() uses 0-based row and column numbers in Fortran
1888    as well as in C.
1889 
1890    Negative indices may be passed in idxm and idxn, these rows and columns are
1891    simply ignored. This allows easily inserting element stiffness matrices
1892    with homogeneous Dirchlet boundary conditions that you don't want represented
1893    in the matrix.
1894 
1895    Each time an entry is set within a sparse matrix via MatSetValues(),
1896    internal searching must be done to determine where to place the
1897    data in the matrix storage space.  By instead inserting blocks of
1898    entries via MatSetValuesBlocked(), the overhead of matrix assembly is
1899    reduced.
1900 
1901    Example:
1902 $   Suppose m=n=2 and block size(bs) = 2 The array is
1903 $
1904 $   1  2  | 3  4
1905 $   5  6  | 7  8
1906 $   - - - | - - -
1907 $   9  10 | 11 12
1908 $   13 14 | 15 16
1909 $
1910 $   v[] should be passed in like
1911 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1912 $
1913 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1914 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1915 
1916    Level: intermediate
1917 
1918 .seealso: `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1919 @*/
1920 PetscErrorCode MatSetValuesBlocked(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1921 {
1922   PetscFunctionBeginHot;
1923   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1924   PetscValidType(mat,1);
1925   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1926   PetscValidIntPointer(idxm,3);
1927   PetscValidIntPointer(idxn,5);
1928   MatCheckPreallocated(mat,1);
1929   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1930   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1931   if (PetscDefined(USE_DEBUG)) {
1932     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1933     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1934   }
1935   if (PetscDefined(USE_DEBUG)) {
1936     PetscInt rbs,cbs,M,N,i;
1937     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
1938     PetscCall(MatGetSize(mat,&M,&N));
1939     for (i=0; i<m; i++) PetscCheck(idxm[i]*rbs < M,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT,i,idxm[i],M);
1940     for (i=0; i<n; i++) PetscCheck(idxn[i]*cbs < N,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT,i,idxn[i],N);
1941   }
1942   if (mat->assembled) {
1943     mat->was_assembled = PETSC_TRUE;
1944     mat->assembled     = PETSC_FALSE;
1945   }
1946   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1947   if (mat->ops->setvaluesblocked) {
1948     PetscCall((*mat->ops->setvaluesblocked)(mat,m,idxm,n,idxn,v,addv));
1949   } else {
1950     PetscInt buf[8192],*bufr=NULL,*bufc=NULL,*iidxm,*iidxn;
1951     PetscInt i,j,bs,cbs;
1952 
1953     PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
1954     if (m*bs+n*cbs <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1955       iidxm = buf;
1956       iidxn = buf + m*bs;
1957     } else {
1958       PetscCall(PetscMalloc2(m*bs,&bufr,n*cbs,&bufc));
1959       iidxm = bufr;
1960       iidxn = bufc;
1961     }
1962     for (i=0; i<m; i++) {
1963       for (j=0; j<bs; j++) {
1964         iidxm[i*bs+j] = bs*idxm[i] + j;
1965       }
1966     }
1967     if (m != n || bs != cbs || idxm != idxn) {
1968       for (i=0; i<n; i++) {
1969         for (j=0; j<cbs; j++) {
1970           iidxn[i*cbs+j] = cbs*idxn[i] + j;
1971         }
1972       }
1973     } else iidxn = iidxm;
1974     PetscCall(MatSetValues(mat,m*bs,iidxm,n*cbs,iidxn,v,addv));
1975     PetscCall(PetscFree2(bufr,bufc));
1976   }
1977   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1978   PetscFunctionReturn(0);
1979 }
1980 
1981 /*@C
1982    MatGetValues - Gets a block of values from a matrix.
1983 
1984    Not Collective; can only return values that are owned by the give process
1985 
1986    Input Parameters:
1987 +  mat - the matrix
1988 .  v - a logically two-dimensional array for storing the values
1989 .  m, idxm - the number of rows and their global indices
1990 -  n, idxn - the number of columns and their global indices
1991 
1992    Notes:
1993      The user must allocate space (m*n PetscScalars) for the values, v.
1994      The values, v, are then returned in a row-oriented format,
1995      analogous to that used by default in MatSetValues().
1996 
1997      MatGetValues() uses 0-based row and column numbers in
1998      Fortran as well as in C.
1999 
2000      MatGetValues() requires that the matrix has been assembled
2001      with MatAssemblyBegin()/MatAssemblyEnd().  Thus, calls to
2002      MatSetValues() and MatGetValues() CANNOT be made in succession
2003      without intermediate matrix assembly.
2004 
2005      Negative row or column indices will be ignored and those locations in v[] will be
2006      left unchanged.
2007 
2008      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2009      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2010      from MatGetOwnershipRange(mat,&rstart,&rend).
2011 
2012    Level: advanced
2013 
2014 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2015 @*/
2016 PetscErrorCode MatGetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
2017 {
2018   PetscFunctionBegin;
2019   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2020   PetscValidType(mat,1);
2021   if (!m || !n) PetscFunctionReturn(0);
2022   PetscValidIntPointer(idxm,3);
2023   PetscValidIntPointer(idxn,5);
2024   PetscValidScalarPointer(v,6);
2025   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2026   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2027   PetscCheck(mat->ops->getvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2028   MatCheckPreallocated(mat,1);
2029 
2030   PetscCall(PetscLogEventBegin(MAT_GetValues,mat,0,0,0));
2031   PetscCall((*mat->ops->getvalues)(mat,m,idxm,n,idxn,v));
2032   PetscCall(PetscLogEventEnd(MAT_GetValues,mat,0,0,0));
2033   PetscFunctionReturn(0);
2034 }
2035 
2036 /*@C
2037    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2038      defined previously by MatSetLocalToGlobalMapping()
2039 
2040    Not Collective
2041 
2042    Input Parameters:
2043 +  mat - the matrix
2044 .  nrow, irow - number of rows and their local indices
2045 -  ncol, icol - number of columns and their local indices
2046 
2047    Output Parameter:
2048 .  y -  a logically two-dimensional array of values
2049 
2050    Notes:
2051      If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine.
2052 
2053      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2054      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from MatGetOwnershipRange(mat,&rstart,&rend). One can
2055      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the ISLocalToGlobalMapping set
2056      with MatSetLocalToGlobalMapping().
2057 
2058    Developer Notes:
2059       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2060       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2061 
2062    Level: advanced
2063 
2064 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2065           `MatSetValuesLocal()`, `MatGetValues()`
2066 @*/
2067 PetscErrorCode MatGetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],PetscScalar y[])
2068 {
2069   PetscFunctionBeginHot;
2070   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2071   PetscValidType(mat,1);
2072   MatCheckPreallocated(mat,1);
2073   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2074   PetscValidIntPointer(irow,3);
2075   PetscValidIntPointer(icol,5);
2076   if (PetscDefined(USE_DEBUG)) {
2077     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2078     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2079   }
2080   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2081   PetscCall(PetscLogEventBegin(MAT_GetValues,mat,0,0,0));
2082   if (mat->ops->getvalueslocal) {
2083     PetscCall((*mat->ops->getvalueslocal)(mat,nrow,irow,ncol,icol,y));
2084   } else {
2085     PetscInt buf[8192],*bufr=NULL,*bufc=NULL,*irowm,*icolm;
2086     if ((nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2087       irowm = buf; icolm = buf+nrow;
2088     } else {
2089       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2090       irowm = bufr; icolm = bufc;
2091     }
2092     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2093     PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2094     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,irowm));
2095     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,icolm));
2096     PetscCall(MatGetValues(mat,nrow,irowm,ncol,icolm,y));
2097     PetscCall(PetscFree2(bufr,bufc));
2098   }
2099   PetscCall(PetscLogEventEnd(MAT_GetValues,mat,0,0,0));
2100   PetscFunctionReturn(0);
2101 }
2102 
2103 /*@
2104   MatSetValuesBatch - Adds (ADD_VALUES) many blocks of values into a matrix at once. The blocks must all be square and
2105   the same size. Currently, this can only be called once and creates the given matrix.
2106 
2107   Not Collective
2108 
2109   Input Parameters:
2110 + mat - the matrix
2111 . nb - the number of blocks
2112 . bs - the number of rows (and columns) in each block
2113 . rows - a concatenation of the rows for each block
2114 - v - a concatenation of logically two-dimensional arrays of values
2115 
2116   Notes:
2117   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2118 
2119   Level: advanced
2120 
2121 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2122           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
2123 @*/
2124 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2125 {
2126   PetscFunctionBegin;
2127   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2128   PetscValidType(mat,1);
2129   PetscValidIntPointer(rows,4);
2130   PetscValidScalarPointer(v,5);
2131   PetscAssert(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2132 
2133   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch,mat,0,0,0));
2134   if (mat->ops->setvaluesbatch) {
2135     PetscCall((*mat->ops->setvaluesbatch)(mat,nb,bs,rows,v));
2136   } else {
2137     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b*bs], bs, &rows[b*bs], &v[b*bs*bs], ADD_VALUES));
2138   }
2139   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch,mat,0,0,0));
2140   PetscFunctionReturn(0);
2141 }
2142 
2143 /*@
2144    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2145    the routine MatSetValuesLocal() to allow users to insert matrix entries
2146    using a local (per-processor) numbering.
2147 
2148    Not Collective
2149 
2150    Input Parameters:
2151 +  x - the matrix
2152 .  rmapping - row mapping created with ISLocalToGlobalMappingCreate() or ISLocalToGlobalMappingCreateIS()
2153 -  cmapping - column mapping
2154 
2155    Level: intermediate
2156 
2157 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2158 @*/
2159 PetscErrorCode MatSetLocalToGlobalMapping(Mat x,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
2160 {
2161   PetscFunctionBegin;
2162   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
2163   PetscValidType(x,1);
2164   if (rmapping) PetscValidHeaderSpecific(rmapping,IS_LTOGM_CLASSID,2);
2165   if (cmapping) PetscValidHeaderSpecific(cmapping,IS_LTOGM_CLASSID,3);
2166   if (x->ops->setlocaltoglobalmapping) {
2167     PetscCall((*x->ops->setlocaltoglobalmapping)(x,rmapping,cmapping));
2168   } else {
2169     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap,rmapping));
2170     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap,cmapping));
2171   }
2172   PetscFunctionReturn(0);
2173 }
2174 
2175 /*@
2176    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by MatSetLocalToGlobalMapping()
2177 
2178    Not Collective
2179 
2180    Input Parameter:
2181 .  A - the matrix
2182 
2183    Output Parameters:
2184 + rmapping - row mapping
2185 - cmapping - column mapping
2186 
2187    Level: advanced
2188 
2189 .seealso: `MatSetValuesLocal()`
2190 @*/
2191 PetscErrorCode MatGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping)
2192 {
2193   PetscFunctionBegin;
2194   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2195   PetscValidType(A,1);
2196   if (rmapping) {
2197     PetscValidPointer(rmapping,2);
2198     *rmapping = A->rmap->mapping;
2199   }
2200   if (cmapping) {
2201     PetscValidPointer(cmapping,3);
2202     *cmapping = A->cmap->mapping;
2203   }
2204   PetscFunctionReturn(0);
2205 }
2206 
2207 /*@
2208    MatSetLayouts - Sets the PetscLayout objects for rows and columns of a matrix
2209 
2210    Logically Collective on A
2211 
2212    Input Parameters:
2213 +  A - the matrix
2214 . rmap - row layout
2215 - cmap - column layout
2216 
2217    Level: advanced
2218 
2219 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2220 @*/
2221 PetscErrorCode MatSetLayouts(Mat A,PetscLayout rmap,PetscLayout cmap)
2222 {
2223   PetscFunctionBegin;
2224   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2225   PetscCall(PetscLayoutReference(rmap,&A->rmap));
2226   PetscCall(PetscLayoutReference(cmap,&A->cmap));
2227   PetscFunctionReturn(0);
2228 }
2229 
2230 /*@
2231    MatGetLayouts - Gets the PetscLayout objects for rows and columns
2232 
2233    Not Collective
2234 
2235    Input Parameter:
2236 .  A - the matrix
2237 
2238    Output Parameters:
2239 + rmap - row layout
2240 - cmap - column layout
2241 
2242    Level: advanced
2243 
2244 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2245 @*/
2246 PetscErrorCode MatGetLayouts(Mat A,PetscLayout *rmap,PetscLayout *cmap)
2247 {
2248   PetscFunctionBegin;
2249   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2250   PetscValidType(A,1);
2251   if (rmap) {
2252     PetscValidPointer(rmap,2);
2253     *rmap = A->rmap;
2254   }
2255   if (cmap) {
2256     PetscValidPointer(cmap,3);
2257     *cmap = A->cmap;
2258   }
2259   PetscFunctionReturn(0);
2260 }
2261 
2262 /*@C
2263    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2264    using a local numbering of the nodes.
2265 
2266    Not Collective
2267 
2268    Input Parameters:
2269 +  mat - the matrix
2270 .  nrow, irow - number of rows and their local indices
2271 .  ncol, icol - number of columns and their local indices
2272 .  y -  a logically two-dimensional array of values
2273 -  addv - either INSERT_VALUES or ADD_VALUES, where
2274    ADD_VALUES adds values to any existing entries, and
2275    INSERT_VALUES replaces existing entries with new values
2276 
2277    Notes:
2278    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2279       MatSetUp() before using this routine
2280 
2281    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine
2282 
2283    Calls to MatSetValuesLocal() with the INSERT_VALUES and ADD_VALUES
2284    options cannot be mixed without intervening calls to the assembly
2285    routines.
2286 
2287    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2288    MUST be called after all calls to MatSetValuesLocal() have been completed.
2289 
2290    Level: intermediate
2291 
2292    Developer Notes:
2293     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2294                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2295 
2296 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2297           `MatSetValueLocal()`, `MatGetValuesLocal()`
2298 @*/
2299 PetscErrorCode MatSetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2300 {
2301   PetscFunctionBeginHot;
2302   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2303   PetscValidType(mat,1);
2304   MatCheckPreallocated(mat,1);
2305   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2306   PetscValidIntPointer(irow,3);
2307   PetscValidIntPointer(icol,5);
2308   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2309   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2310   if (PetscDefined(USE_DEBUG)) {
2311     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2312     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2313   }
2314 
2315   if (mat->assembled) {
2316     mat->was_assembled = PETSC_TRUE;
2317     mat->assembled     = PETSC_FALSE;
2318   }
2319   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
2320   if (mat->ops->setvalueslocal) {
2321     PetscCall((*mat->ops->setvalueslocal)(mat,nrow,irow,ncol,icol,y,addv));
2322   } else {
2323     PetscInt       buf[8192],*bufr=NULL,*bufc=NULL;
2324     const PetscInt *irowm,*icolm;
2325 
2326     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2327       bufr  = buf;
2328       bufc  = buf + nrow;
2329       irowm = bufr;
2330       icolm = bufc;
2331     } else {
2332       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2333       irowm = bufr;
2334       icolm = bufc;
2335     }
2336     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,bufr));
2337     else irowm = irow;
2338     if (mat->cmap->mapping) {
2339       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2340         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,bufc));
2341       } else icolm = irowm;
2342     } else icolm = icol;
2343     PetscCall(MatSetValues(mat,nrow,irowm,ncol,icolm,y,addv));
2344     if (bufr != buf) PetscCall(PetscFree2(bufr,bufc));
2345   }
2346   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
2347   PetscFunctionReturn(0);
2348 }
2349 
2350 /*@C
2351    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2352    using a local ordering of the nodes a block at a time.
2353 
2354    Not Collective
2355 
2356    Input Parameters:
2357 +  x - the matrix
2358 .  nrow, irow - number of rows and their local indices
2359 .  ncol, icol - number of columns and their local indices
2360 .  y -  a logically two-dimensional array of values
2361 -  addv - either INSERT_VALUES or ADD_VALUES, where
2362    ADD_VALUES adds values to any existing entries, and
2363    INSERT_VALUES replaces existing entries with new values
2364 
2365    Notes:
2366    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2367       MatSetUp() before using this routine
2368 
2369    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetBlockSize() and MatSetLocalToGlobalMapping()
2370       before using this routineBefore calling MatSetValuesLocal(), the user must first set the
2371 
2372    Calls to MatSetValuesBlockedLocal() with the INSERT_VALUES and ADD_VALUES
2373    options cannot be mixed without intervening calls to the assembly
2374    routines.
2375 
2376    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2377    MUST be called after all calls to MatSetValuesBlockedLocal() have been completed.
2378 
2379    Level: intermediate
2380 
2381    Developer Notes:
2382     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2383                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2384 
2385 .seealso: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2386           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2387 @*/
2388 PetscErrorCode MatSetValuesBlockedLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2389 {
2390   PetscFunctionBeginHot;
2391   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2392   PetscValidType(mat,1);
2393   MatCheckPreallocated(mat,1);
2394   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2395   PetscValidIntPointer(irow,3);
2396   PetscValidIntPointer(icol,5);
2397   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2398   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2399   if (PetscDefined(USE_DEBUG)) {
2400     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2401     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2402   }
2403 
2404   if (mat->assembled) {
2405     mat->was_assembled = PETSC_TRUE;
2406     mat->assembled     = PETSC_FALSE;
2407   }
2408   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2409     PetscInt irbs, rbs;
2410     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2411     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&irbs));
2412     PetscCheck(rbs == irbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT,rbs,irbs);
2413   }
2414   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2415     PetscInt icbs, cbs;
2416     PetscCall(MatGetBlockSizes(mat,NULL,&cbs));
2417     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&icbs));
2418     PetscCheck(cbs == icbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT,cbs,icbs);
2419   }
2420   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
2421   if (mat->ops->setvaluesblockedlocal) {
2422     PetscCall((*mat->ops->setvaluesblockedlocal)(mat,nrow,irow,ncol,icol,y,addv));
2423   } else {
2424     PetscInt       buf[8192],*bufr=NULL,*bufc=NULL;
2425     const PetscInt *irowm,*icolm;
2426 
2427     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2428       bufr  = buf;
2429       bufc  = buf + nrow;
2430       irowm = bufr;
2431       icolm = bufc;
2432     } else {
2433       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2434       irowm = bufr;
2435       icolm = bufc;
2436     }
2437     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping,nrow,irow,bufr));
2438     else irowm = irow;
2439     if (mat->cmap->mapping) {
2440       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2441         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping,ncol,icol,bufc));
2442       } else icolm = irowm;
2443     } else icolm = icol;
2444     PetscCall(MatSetValuesBlocked(mat,nrow,irowm,ncol,icolm,y,addv));
2445     if (bufr != buf) PetscCall(PetscFree2(bufr,bufc));
2446   }
2447   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
2448   PetscFunctionReturn(0);
2449 }
2450 
2451 /*@
2452    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2453 
2454    Collective on Mat
2455 
2456    Input Parameters:
2457 +  mat - the matrix
2458 -  x   - the vector to be multiplied
2459 
2460    Output Parameters:
2461 .  y - the result
2462 
2463    Notes:
2464    The vectors x and y cannot be the same.  I.e., one cannot
2465    call MatMult(A,y,y).
2466 
2467    Level: developer
2468 
2469 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2470 @*/
2471 PetscErrorCode MatMultDiagonalBlock(Mat mat,Vec x,Vec y)
2472 {
2473   PetscFunctionBegin;
2474   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2475   PetscValidType(mat,1);
2476   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2477   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2478 
2479   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2480   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2481   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2482   MatCheckPreallocated(mat,1);
2483 
2484   PetscCheck(mat->ops->multdiagonalblock,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply defined",((PetscObject)mat)->type_name);
2485   PetscCall((*mat->ops->multdiagonalblock)(mat,x,y));
2486   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2487   PetscFunctionReturn(0);
2488 }
2489 
2490 /* --------------------------------------------------------*/
2491 /*@
2492    MatMult - Computes the matrix-vector product, y = Ax.
2493 
2494    Neighbor-wise Collective on Mat
2495 
2496    Input Parameters:
2497 +  mat - the matrix
2498 -  x   - the vector to be multiplied
2499 
2500    Output Parameters:
2501 .  y - the result
2502 
2503    Notes:
2504    The vectors x and y cannot be the same.  I.e., one cannot
2505    call MatMult(A,y,y).
2506 
2507    Level: beginner
2508 
2509 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2510 @*/
2511 PetscErrorCode MatMult(Mat mat,Vec x,Vec y)
2512 {
2513   PetscFunctionBegin;
2514   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2515   PetscValidType(mat,1);
2516   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2517   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2518   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2519   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2520   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2521   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
2522   PetscCheck(mat->rmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,y->map->N);
2523   PetscCheck(mat->cmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,x->map->n);
2524   PetscCheck(mat->rmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,y->map->n);
2525   PetscCall(VecSetErrorIfLocked(y,3));
2526   if (mat->erroriffailure) PetscCall(VecValidValues(x,2,PETSC_TRUE));
2527   MatCheckPreallocated(mat,1);
2528 
2529   PetscCall(VecLockReadPush(x));
2530   PetscCheck(mat->ops->mult,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply defined",((PetscObject)mat)->type_name);
2531   PetscCall(PetscLogEventBegin(MAT_Mult,mat,x,y,0));
2532   PetscCall((*mat->ops->mult)(mat,x,y));
2533   PetscCall(PetscLogEventEnd(MAT_Mult,mat,x,y,0));
2534   if (mat->erroriffailure) PetscCall(VecValidValues(y,3,PETSC_FALSE));
2535   PetscCall(VecLockReadPop(x));
2536   PetscFunctionReturn(0);
2537 }
2538 
2539 /*@
2540    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2541 
2542    Neighbor-wise Collective on Mat
2543 
2544    Input Parameters:
2545 +  mat - the matrix
2546 -  x   - the vector to be multiplied
2547 
2548    Output Parameters:
2549 .  y - the result
2550 
2551    Notes:
2552    The vectors x and y cannot be the same.  I.e., one cannot
2553    call MatMultTranspose(A,y,y).
2554 
2555    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2556    use MatMultHermitianTranspose()
2557 
2558    Level: beginner
2559 
2560 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2561 @*/
2562 PetscErrorCode MatMultTranspose(Mat mat,Vec x,Vec y)
2563 {
2564   PetscErrorCode (*op)(Mat,Vec,Vec) = NULL;
2565 
2566   PetscFunctionBegin;
2567   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2568   PetscValidType(mat,1);
2569   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2570   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2571 
2572   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2573   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2574   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2575   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
2576   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
2577   PetscCheck(mat->cmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,y->map->n);
2578   PetscCheck(mat->rmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,x->map->n);
2579   if (mat->erroriffailure) PetscCall(VecValidValues(x,2,PETSC_TRUE));
2580   MatCheckPreallocated(mat,1);
2581 
2582   if (!mat->ops->multtranspose) {
2583     if (mat->symmetric && mat->ops->mult) op = mat->ops->mult;
2584     PetscCheck(op,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined",((PetscObject)mat)->type_name);
2585   } else op = mat->ops->multtranspose;
2586   PetscCall(PetscLogEventBegin(MAT_MultTranspose,mat,x,y,0));
2587   PetscCall(VecLockReadPush(x));
2588   PetscCall((*op)(mat,x,y));
2589   PetscCall(VecLockReadPop(x));
2590   PetscCall(PetscLogEventEnd(MAT_MultTranspose,mat,x,y,0));
2591   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2592   if (mat->erroriffailure) PetscCall(VecValidValues(y,3,PETSC_FALSE));
2593   PetscFunctionReturn(0);
2594 }
2595 
2596 /*@
2597    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2598 
2599    Neighbor-wise Collective on Mat
2600 
2601    Input Parameters:
2602 +  mat - the matrix
2603 -  x   - the vector to be multilplied
2604 
2605    Output Parameters:
2606 .  y - the result
2607 
2608    Notes:
2609    The vectors x and y cannot be the same.  I.e., one cannot
2610    call MatMultHermitianTranspose(A,y,y).
2611 
2612    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2613 
2614    For real numbers MatMultTranspose() and MatMultHermitianTranspose() are identical.
2615 
2616    Level: beginner
2617 
2618 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2619 @*/
2620 PetscErrorCode MatMultHermitianTranspose(Mat mat,Vec x,Vec y)
2621 {
2622   PetscFunctionBegin;
2623   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2624   PetscValidType(mat,1);
2625   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2626   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2627 
2628   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2629   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2630   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2631   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
2632   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
2633   PetscCheck(mat->cmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,y->map->n);
2634   PetscCheck(mat->rmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,x->map->n);
2635   MatCheckPreallocated(mat,1);
2636 
2637   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose,mat,x,y,0));
2638 #if defined(PETSC_USE_COMPLEX)
2639   if (mat->ops->multhermitiantranspose || (mat->hermitian && mat->ops->mult)) {
2640     PetscCall(VecLockReadPush(x));
2641     if (mat->ops->multhermitiantranspose) {
2642       PetscCall((*mat->ops->multhermitiantranspose)(mat,x,y));
2643     } else {
2644       PetscCall((*mat->ops->mult)(mat,x,y));
2645     }
2646     PetscCall(VecLockReadPop(x));
2647   } else {
2648     Vec w;
2649     PetscCall(VecDuplicate(x,&w));
2650     PetscCall(VecCopy(x,w));
2651     PetscCall(VecConjugate(w));
2652     PetscCall(MatMultTranspose(mat,w,y));
2653     PetscCall(VecDestroy(&w));
2654     PetscCall(VecConjugate(y));
2655   }
2656   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2657 #else
2658   PetscCall(MatMultTranspose(mat,x,y));
2659 #endif
2660   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose,mat,x,y,0));
2661   PetscFunctionReturn(0);
2662 }
2663 
2664 /*@
2665     MatMultAdd -  Computes v3 = v2 + A * v1.
2666 
2667     Neighbor-wise Collective on Mat
2668 
2669     Input Parameters:
2670 +   mat - the matrix
2671 -   v1, v2 - the vectors
2672 
2673     Output Parameters:
2674 .   v3 - the result
2675 
2676     Notes:
2677     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2678     call MatMultAdd(A,v1,v2,v1).
2679 
2680     Level: beginner
2681 
2682 .seealso: `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2683 @*/
2684 PetscErrorCode MatMultAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2685 {
2686   PetscFunctionBegin;
2687   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2688   PetscValidType(mat,1);
2689   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2690   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2691   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2692 
2693   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2694   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2695   PetscCheck(mat->cmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v1->map->N);
2696   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2697      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2698   PetscCheck(mat->rmap->n == v3->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,v3->map->n);
2699   PetscCheck(mat->rmap->n == v2->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,v2->map->n);
2700   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2701   MatCheckPreallocated(mat,1);
2702 
2703   PetscCheck(mat->ops->multadd,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No MatMultAdd() for matrix type %s",((PetscObject)mat)->type_name);
2704   PetscCall(PetscLogEventBegin(MAT_MultAdd,mat,v1,v2,v3));
2705   PetscCall(VecLockReadPush(v1));
2706   PetscCall((*mat->ops->multadd)(mat,v1,v2,v3));
2707   PetscCall(VecLockReadPop(v1));
2708   PetscCall(PetscLogEventEnd(MAT_MultAdd,mat,v1,v2,v3));
2709   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2710   PetscFunctionReturn(0);
2711 }
2712 
2713 /*@
2714    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2715 
2716    Neighbor-wise Collective on Mat
2717 
2718    Input Parameters:
2719 +  mat - the matrix
2720 -  v1, v2 - the vectors
2721 
2722    Output Parameters:
2723 .  v3 - the result
2724 
2725    Notes:
2726    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2727    call MatMultTransposeAdd(A,v1,v2,v1).
2728 
2729    Level: beginner
2730 
2731 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2732 @*/
2733 PetscErrorCode MatMultTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2734 {
2735   PetscErrorCode (*op)(Mat,Vec,Vec,Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2736 
2737   PetscFunctionBegin;
2738   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2739   PetscValidType(mat,1);
2740   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2741   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2742   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2743 
2744   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2745   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2746   PetscCheck(mat->rmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v1->map->N);
2747   PetscCheck(mat->cmap->N == v2->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v2->map->N);
2748   PetscCheck(mat->cmap->N == v3->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v3->map->N);
2749   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2750   PetscCheck(op,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2751   MatCheckPreallocated(mat,1);
2752 
2753   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd,mat,v1,v2,v3));
2754   PetscCall(VecLockReadPush(v1));
2755   PetscCall((*op)(mat,v1,v2,v3));
2756   PetscCall(VecLockReadPop(v1));
2757   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd,mat,v1,v2,v3));
2758   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2759   PetscFunctionReturn(0);
2760 }
2761 
2762 /*@
2763    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2764 
2765    Neighbor-wise Collective on Mat
2766 
2767    Input Parameters:
2768 +  mat - the matrix
2769 -  v1, v2 - the vectors
2770 
2771    Output Parameters:
2772 .  v3 - the result
2773 
2774    Notes:
2775    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2776    call MatMultHermitianTransposeAdd(A,v1,v2,v1).
2777 
2778    Level: beginner
2779 
2780 .seealso: `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2781 @*/
2782 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2783 {
2784   PetscFunctionBegin;
2785   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2786   PetscValidType(mat,1);
2787   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2788   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2789   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2790 
2791   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2792   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2793   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2794   PetscCheck(mat->rmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v1->map->N);
2795   PetscCheck(mat->cmap->N == v2->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v2->map->N);
2796   PetscCheck(mat->cmap->N == v3->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v3->map->N);
2797   MatCheckPreallocated(mat,1);
2798 
2799   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3));
2800   PetscCall(VecLockReadPush(v1));
2801   if (mat->ops->multhermitiantransposeadd) {
2802     PetscCall((*mat->ops->multhermitiantransposeadd)(mat,v1,v2,v3));
2803   } else {
2804     Vec w,z;
2805     PetscCall(VecDuplicate(v1,&w));
2806     PetscCall(VecCopy(v1,w));
2807     PetscCall(VecConjugate(w));
2808     PetscCall(VecDuplicate(v3,&z));
2809     PetscCall(MatMultTranspose(mat,w,z));
2810     PetscCall(VecDestroy(&w));
2811     PetscCall(VecConjugate(z));
2812     if (v2 != v3) {
2813       PetscCall(VecWAXPY(v3,1.0,v2,z));
2814     } else {
2815       PetscCall(VecAXPY(v3,1.0,z));
2816     }
2817     PetscCall(VecDestroy(&z));
2818   }
2819   PetscCall(VecLockReadPop(v1));
2820   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3));
2821   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2822   PetscFunctionReturn(0);
2823 }
2824 
2825 /*@C
2826    MatGetFactorType - gets the type of factorization it is
2827 
2828    Not Collective
2829 
2830    Input Parameters:
2831 .  mat - the matrix
2832 
2833    Output Parameters:
2834 .  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2835 
2836    Level: intermediate
2837 
2838 .seealso: `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`
2839 @*/
2840 PetscErrorCode MatGetFactorType(Mat mat,MatFactorType *t)
2841 {
2842   PetscFunctionBegin;
2843   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2844   PetscValidType(mat,1);
2845   PetscValidPointer(t,2);
2846   *t = mat->factortype;
2847   PetscFunctionReturn(0);
2848 }
2849 
2850 /*@C
2851    MatSetFactorType - sets the type of factorization it is
2852 
2853    Logically Collective on Mat
2854 
2855    Input Parameters:
2856 +  mat - the matrix
2857 -  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2858 
2859    Level: intermediate
2860 
2861 .seealso: `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`
2862 @*/
2863 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2864 {
2865   PetscFunctionBegin;
2866   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2867   PetscValidType(mat,1);
2868   mat->factortype = t;
2869   PetscFunctionReturn(0);
2870 }
2871 
2872 /* ------------------------------------------------------------*/
2873 /*@C
2874    MatGetInfo - Returns information about matrix storage (number of
2875    nonzeros, memory, etc.).
2876 
2877    Collective on Mat if MAT_GLOBAL_MAX or MAT_GLOBAL_SUM is used as the flag
2878 
2879    Input Parameter:
2880 .  mat - the matrix
2881 
2882    Output Parameters:
2883 +  flag - flag indicating the type of parameters to be returned
2884    (MAT_LOCAL - local matrix, MAT_GLOBAL_MAX - maximum over all processors,
2885    MAT_GLOBAL_SUM - sum over all processors)
2886 -  info - matrix information context
2887 
2888    Notes:
2889    The MatInfo context contains a variety of matrix data, including
2890    number of nonzeros allocated and used, number of mallocs during
2891    matrix assembly, etc.  Additional information for factored matrices
2892    is provided (such as the fill ratio, number of mallocs during
2893    factorization, etc.).  Much of this info is printed to PETSC_STDOUT
2894    when using the runtime options
2895 $       -info -mat_view ::ascii_info
2896 
2897    Example for C/C++ Users:
2898    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2899    data within the MatInfo context.  For example,
2900 .vb
2901       MatInfo info;
2902       Mat     A;
2903       double  mal, nz_a, nz_u;
2904 
2905       MatGetInfo(A,MAT_LOCAL,&info);
2906       mal  = info.mallocs;
2907       nz_a = info.nz_allocated;
2908 .ve
2909 
2910    Example for Fortran Users:
2911    Fortran users should declare info as a double precision
2912    array of dimension MAT_INFO_SIZE, and then extract the parameters
2913    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2914    a complete list of parameter names.
2915 .vb
2916       double  precision info(MAT_INFO_SIZE)
2917       double  precision mal, nz_a
2918       Mat     A
2919       integer ierr
2920 
2921       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2922       mal = info(MAT_INFO_MALLOCS)
2923       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2924 .ve
2925 
2926     Level: intermediate
2927 
2928     Developer Note: fortran interface is not autogenerated as the f90
2929     interface definition cannot be generated correctly [due to MatInfo]
2930 
2931 .seealso: `MatStashGetInfo()`
2932 
2933 @*/
2934 PetscErrorCode MatGetInfo(Mat mat,MatInfoType flag,MatInfo *info)
2935 {
2936   PetscFunctionBegin;
2937   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2938   PetscValidType(mat,1);
2939   PetscValidPointer(info,3);
2940   PetscCheck(mat->ops->getinfo,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2941   MatCheckPreallocated(mat,1);
2942   PetscCall((*mat->ops->getinfo)(mat,flag,info));
2943   PetscFunctionReturn(0);
2944 }
2945 
2946 /*
2947    This is used by external packages where it is not easy to get the info from the actual
2948    matrix factorization.
2949 */
2950 PetscErrorCode MatGetInfo_External(Mat A,MatInfoType flag,MatInfo *info)
2951 {
2952   PetscFunctionBegin;
2953   PetscCall(PetscMemzero(info,sizeof(MatInfo)));
2954   PetscFunctionReturn(0);
2955 }
2956 
2957 /* ----------------------------------------------------------*/
2958 
2959 /*@C
2960    MatLUFactor - Performs in-place LU factorization of matrix.
2961 
2962    Collective on Mat
2963 
2964    Input Parameters:
2965 +  mat - the matrix
2966 .  row - row permutation
2967 .  col - column permutation
2968 -  info - options for factorization, includes
2969 $          fill - expected fill as ratio of original fill.
2970 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2971 $                   Run with the option -info to determine an optimal value to use
2972 
2973    Notes:
2974    Most users should employ the simplified KSP interface for linear solvers
2975    instead of working directly with matrix algebra routines such as this.
2976    See, e.g., KSPCreate().
2977 
2978    This changes the state of the matrix to a factored matrix; it cannot be used
2979    for example with MatSetValues() unless one first calls MatSetUnfactored().
2980 
2981    Level: developer
2982 
2983 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2984           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2985 
2986     Developer Note: fortran interface is not autogenerated as the f90
2987     interface definition cannot be generated correctly [due to MatFactorInfo]
2988 
2989 @*/
2990 PetscErrorCode MatLUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
2991 {
2992   MatFactorInfo  tinfo;
2993 
2994   PetscFunctionBegin;
2995   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2996   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
2997   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
2998   if (info) PetscValidPointer(info,4);
2999   PetscValidType(mat,1);
3000   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3001   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3002   PetscCheck(mat->ops->lufactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3003   MatCheckPreallocated(mat,1);
3004   if (!info) {
3005     PetscCall(MatFactorInfoInitialize(&tinfo));
3006     info = &tinfo;
3007   }
3008 
3009   PetscCall(PetscLogEventBegin(MAT_LUFactor,mat,row,col,0));
3010   PetscCall((*mat->ops->lufactor)(mat,row,col,info));
3011   PetscCall(PetscLogEventEnd(MAT_LUFactor,mat,row,col,0));
3012   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3013   PetscFunctionReturn(0);
3014 }
3015 
3016 /*@C
3017    MatILUFactor - Performs in-place ILU factorization of matrix.
3018 
3019    Collective on Mat
3020 
3021    Input Parameters:
3022 +  mat - the matrix
3023 .  row - row permutation
3024 .  col - column permutation
3025 -  info - structure containing
3026 $      levels - number of levels of fill.
3027 $      expected fill - as ratio of original fill.
3028 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3029                 missing diagonal entries)
3030 
3031    Notes:
3032    Probably really in-place only when level of fill is zero, otherwise allocates
3033    new space to store factored matrix and deletes previous memory.
3034 
3035    Most users should employ the simplified KSP interface for linear solvers
3036    instead of working directly with matrix algebra routines such as this.
3037    See, e.g., KSPCreate().
3038 
3039    Level: developer
3040 
3041 .seealso: `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3042 
3043     Developer Note: fortran interface is not autogenerated as the f90
3044     interface definition cannot be generated correctly [due to MatFactorInfo]
3045 
3046 @*/
3047 PetscErrorCode MatILUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
3048 {
3049   PetscFunctionBegin;
3050   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3051   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
3052   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3053   PetscValidPointer(info,4);
3054   PetscValidType(mat,1);
3055   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
3056   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3057   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3058   PetscCheck(mat->ops->ilufactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3059   MatCheckPreallocated(mat,1);
3060 
3061   PetscCall(PetscLogEventBegin(MAT_ILUFactor,mat,row,col,0));
3062   PetscCall((*mat->ops->ilufactor)(mat,row,col,info));
3063   PetscCall(PetscLogEventEnd(MAT_ILUFactor,mat,row,col,0));
3064   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3065   PetscFunctionReturn(0);
3066 }
3067 
3068 /*@C
3069    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3070    Call this routine before calling MatLUFactorNumeric().
3071 
3072    Collective on Mat
3073 
3074    Input Parameters:
3075 +  fact - the factor matrix obtained with MatGetFactor()
3076 .  mat - the matrix
3077 .  row, col - row and column permutations
3078 -  info - options for factorization, includes
3079 $          fill - expected fill as ratio of original fill.
3080 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3081 $                   Run with the option -info to determine an optimal value to use
3082 
3083    Notes:
3084     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
3085 
3086    Most users should employ the simplified KSP interface for linear solvers
3087    instead of working directly with matrix algebra routines such as this.
3088    See, e.g., KSPCreate().
3089 
3090    Level: developer
3091 
3092 .seealso: `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3093 
3094     Developer Note: fortran interface is not autogenerated as the f90
3095     interface definition cannot be generated correctly [due to MatFactorInfo]
3096 
3097 @*/
3098 PetscErrorCode MatLUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
3099 {
3100   MatFactorInfo  tinfo;
3101 
3102   PetscFunctionBegin;
3103   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3104   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
3105   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
3106   if (info) PetscValidPointer(info,5);
3107   PetscValidType(mat,2);
3108   PetscValidPointer(fact,1);
3109   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3110   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3111   if (!(fact)->ops->lufactorsymbolic) {
3112     MatSolverType stype;
3113     PetscCall(MatFactorGetSolverType(fact,&stype));
3114     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic LU using solver package %s",((PetscObject)mat)->type_name,stype);
3115   }
3116   MatCheckPreallocated(mat,2);
3117   if (!info) {
3118     PetscCall(MatFactorInfoInitialize(&tinfo));
3119     info = &tinfo;
3120   }
3121 
3122   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic,mat,row,col,0));
3123   PetscCall((fact->ops->lufactorsymbolic)(fact,mat,row,col,info));
3124   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic,mat,row,col,0));
3125   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3126   PetscFunctionReturn(0);
3127 }
3128 
3129 /*@C
3130    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3131    Call this routine after first calling MatLUFactorSymbolic().
3132 
3133    Collective on Mat
3134 
3135    Input Parameters:
3136 +  fact - the factor matrix obtained with MatGetFactor()
3137 .  mat - the matrix
3138 -  info - options for factorization
3139 
3140    Notes:
3141    See MatLUFactor() for in-place factorization.  See
3142    MatCholeskyFactorNumeric() for the symmetric, positive definite case.
3143 
3144    Most users should employ the simplified KSP interface for linear solvers
3145    instead of working directly with matrix algebra routines such as this.
3146    See, e.g., KSPCreate().
3147 
3148    Level: developer
3149 
3150 .seealso: `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3151 
3152     Developer Note: fortran interface is not autogenerated as the f90
3153     interface definition cannot be generated correctly [due to MatFactorInfo]
3154 
3155 @*/
3156 PetscErrorCode MatLUFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3157 {
3158   MatFactorInfo  tinfo;
3159 
3160   PetscFunctionBegin;
3161   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3162   PetscValidType(mat,2);
3163   PetscValidPointer(fact,1);
3164   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3165   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3166   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3167 
3168   PetscCheck((fact)->ops->lufactornumeric,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric LU",((PetscObject)mat)->type_name);
3169   MatCheckPreallocated(mat,2);
3170   if (!info) {
3171     PetscCall(MatFactorInfoInitialize(&tinfo));
3172     info = &tinfo;
3173   }
3174 
3175   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric,mat,fact,0,0));
3176   else PetscCall(PetscLogEventBegin(MAT_LUFactor,mat,fact,0,0));
3177   PetscCall((fact->ops->lufactornumeric)(fact,mat,info));
3178   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric,mat,fact,0,0));
3179   else PetscCall(PetscLogEventEnd(MAT_LUFactor,mat,fact,0,0));
3180   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3181   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3182   PetscFunctionReturn(0);
3183 }
3184 
3185 /*@C
3186    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3187    symmetric matrix.
3188 
3189    Collective on Mat
3190 
3191    Input Parameters:
3192 +  mat - the matrix
3193 .  perm - row and column permutations
3194 -  f - expected fill as ratio of original fill
3195 
3196    Notes:
3197    See MatLUFactor() for the nonsymmetric case.  See also
3198    MatCholeskyFactorSymbolic(), and MatCholeskyFactorNumeric().
3199 
3200    Most users should employ the simplified KSP interface for linear solvers
3201    instead of working directly with matrix algebra routines such as this.
3202    See, e.g., KSPCreate().
3203 
3204    Level: developer
3205 
3206 .seealso: `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3207           `MatGetOrdering()`
3208 
3209     Developer Note: fortran interface is not autogenerated as the f90
3210     interface definition cannot be generated correctly [due to MatFactorInfo]
3211 
3212 @*/
3213 PetscErrorCode MatCholeskyFactor(Mat mat,IS perm,const MatFactorInfo *info)
3214 {
3215   MatFactorInfo  tinfo;
3216 
3217   PetscFunctionBegin;
3218   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3219   PetscValidType(mat,1);
3220   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,2);
3221   if (info) PetscValidPointer(info,3);
3222   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3223   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3224   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3225   PetscCheck(mat->ops->choleskyfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"In-place factorization for Mat type %s is not supported, try out-of-place factorization. See MatCholeskyFactorSymbolic/Numeric",((PetscObject)mat)->type_name);
3226   MatCheckPreallocated(mat,1);
3227   if (!info) {
3228     PetscCall(MatFactorInfoInitialize(&tinfo));
3229     info = &tinfo;
3230   }
3231 
3232   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor,mat,perm,0,0));
3233   PetscCall((*mat->ops->choleskyfactor)(mat,perm,info));
3234   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor,mat,perm,0,0));
3235   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3236   PetscFunctionReturn(0);
3237 }
3238 
3239 /*@C
3240    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3241    of a symmetric matrix.
3242 
3243    Collective on Mat
3244 
3245    Input Parameters:
3246 +  fact - the factor matrix obtained with MatGetFactor()
3247 .  mat - the matrix
3248 .  perm - row and column permutations
3249 -  info - options for factorization, includes
3250 $          fill - expected fill as ratio of original fill.
3251 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3252 $                   Run with the option -info to determine an optimal value to use
3253 
3254    Notes:
3255    See MatLUFactorSymbolic() for the nonsymmetric case.  See also
3256    MatCholeskyFactor() and MatCholeskyFactorNumeric().
3257 
3258    Most users should employ the simplified KSP interface for linear solvers
3259    instead of working directly with matrix algebra routines such as this.
3260    See, e.g., KSPCreate().
3261 
3262    Level: developer
3263 
3264 .seealso: `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3265           `MatGetOrdering()`
3266 
3267     Developer Note: fortran interface is not autogenerated as the f90
3268     interface definition cannot be generated correctly [due to MatFactorInfo]
3269 
3270 @*/
3271 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
3272 {
3273   MatFactorInfo  tinfo;
3274 
3275   PetscFunctionBegin;
3276   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3277   PetscValidType(mat,2);
3278   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
3279   if (info) PetscValidPointer(info,4);
3280   PetscValidPointer(fact,1);
3281   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3282   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3283   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3284   if (!(fact)->ops->choleskyfactorsymbolic) {
3285     MatSolverType stype;
3286     PetscCall(MatFactorGetSolverType(fact,&stype));
3287     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s symbolic factor Cholesky using solver package %s",((PetscObject)mat)->type_name,stype);
3288   }
3289   MatCheckPreallocated(mat,2);
3290   if (!info) {
3291     PetscCall(MatFactorInfoInitialize(&tinfo));
3292     info = &tinfo;
3293   }
3294 
3295   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic,mat,perm,0,0));
3296   PetscCall((fact->ops->choleskyfactorsymbolic)(fact,mat,perm,info));
3297   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic,mat,perm,0,0));
3298   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3299   PetscFunctionReturn(0);
3300 }
3301 
3302 /*@C
3303    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3304    of a symmetric matrix. Call this routine after first calling
3305    MatCholeskyFactorSymbolic().
3306 
3307    Collective on Mat
3308 
3309    Input Parameters:
3310 +  fact - the factor matrix obtained with MatGetFactor()
3311 .  mat - the initial matrix
3312 .  info - options for factorization
3313 -  fact - the symbolic factor of mat
3314 
3315    Notes:
3316    Most users should employ the simplified KSP interface for linear solvers
3317    instead of working directly with matrix algebra routines such as this.
3318    See, e.g., KSPCreate().
3319 
3320    Level: developer
3321 
3322 .seealso: `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3323 
3324     Developer Note: fortran interface is not autogenerated as the f90
3325     interface definition cannot be generated correctly [due to MatFactorInfo]
3326 
3327 @*/
3328 PetscErrorCode MatCholeskyFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3329 {
3330   MatFactorInfo  tinfo;
3331 
3332   PetscFunctionBegin;
3333   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3334   PetscValidType(mat,2);
3335   PetscValidPointer(fact,1);
3336   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3337   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3338   PetscCheck((fact)->ops->choleskyfactornumeric,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric factor Cholesky",((PetscObject)mat)->type_name);
3339   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3340   MatCheckPreallocated(mat,2);
3341   if (!info) {
3342     PetscCall(MatFactorInfoInitialize(&tinfo));
3343     info = &tinfo;
3344   }
3345 
3346   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric,mat,fact,0,0));
3347   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor,mat,fact,0,0));
3348   PetscCall((fact->ops->choleskyfactornumeric)(fact,mat,info));
3349   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric,mat,fact,0,0));
3350   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor,mat,fact,0,0));
3351   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3352   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3353   PetscFunctionReturn(0);
3354 }
3355 
3356 /*@
3357    MatQRFactor - Performs in-place QR factorization of matrix.
3358 
3359    Collective on Mat
3360 
3361    Input Parameters:
3362 +  mat - the matrix
3363 .  col - column permutation
3364 -  info - options for factorization, includes
3365 $          fill - expected fill as ratio of original fill.
3366 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3367 $                   Run with the option -info to determine an optimal value to use
3368 
3369    Notes:
3370    Most users should employ the simplified KSP interface for linear solvers
3371    instead of working directly with matrix algebra routines such as this.
3372    See, e.g., KSPCreate().
3373 
3374    This changes the state of the matrix to a factored matrix; it cannot be used
3375    for example with MatSetValues() unless one first calls MatSetUnfactored().
3376 
3377    Level: developer
3378 
3379 .seealso: `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3380           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3381 
3382     Developer Note: fortran interface is not autogenerated as the f90
3383     interface definition cannot be generated correctly [due to MatFactorInfo]
3384 
3385 @*/
3386 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3387 {
3388   PetscFunctionBegin;
3389   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3390   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,2);
3391   if (info) PetscValidPointer(info,3);
3392   PetscValidType(mat,1);
3393   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3394   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3395   MatCheckPreallocated(mat,1);
3396   PetscCall(PetscLogEventBegin(MAT_QRFactor,mat,col,0,0));
3397   PetscUseMethod(mat,"MatQRFactor_C", (Mat,IS,const MatFactorInfo*), (mat, col, info));
3398   PetscCall(PetscLogEventEnd(MAT_QRFactor,mat,col,0,0));
3399   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3400   PetscFunctionReturn(0);
3401 }
3402 
3403 /*@
3404    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3405    Call this routine before calling MatQRFactorNumeric().
3406 
3407    Collective on Mat
3408 
3409    Input Parameters:
3410 +  fact - the factor matrix obtained with MatGetFactor()
3411 .  mat - the matrix
3412 .  col - column permutation
3413 -  info - options for factorization, includes
3414 $          fill - expected fill as ratio of original fill.
3415 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3416 $                   Run with the option -info to determine an optimal value to use
3417 
3418    Most users should employ the simplified KSP interface for linear solvers
3419    instead of working directly with matrix algebra routines such as this.
3420    See, e.g., KSPCreate().
3421 
3422    Level: developer
3423 
3424 .seealso: `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3425 
3426     Developer Note: fortran interface is not autogenerated as the f90
3427     interface definition cannot be generated correctly [due to MatFactorInfo]
3428 
3429 @*/
3430 PetscErrorCode MatQRFactorSymbolic(Mat fact,Mat mat,IS col,const MatFactorInfo *info)
3431 {
3432   MatFactorInfo  tinfo;
3433 
3434   PetscFunctionBegin;
3435   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3436   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3437   if (info) PetscValidPointer(info,4);
3438   PetscValidType(mat,2);
3439   PetscValidPointer(fact,1);
3440   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3441   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3442   MatCheckPreallocated(mat,2);
3443   if (!info) {
3444     PetscCall(MatFactorInfoInitialize(&tinfo));
3445     info = &tinfo;
3446   }
3447 
3448   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic,fact,mat,col,0));
3449   PetscUseMethod(fact,"MatQRFactorSymbolic_C", (Mat,Mat,IS,const MatFactorInfo*), (fact, mat, col, info));
3450   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic,fact,mat,col,0));
3451   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3452   PetscFunctionReturn(0);
3453 }
3454 
3455 /*@
3456    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3457    Call this routine after first calling MatQRFactorSymbolic().
3458 
3459    Collective on Mat
3460 
3461    Input Parameters:
3462 +  fact - the factor matrix obtained with MatGetFactor()
3463 .  mat - the matrix
3464 -  info - options for factorization
3465 
3466    Notes:
3467    See MatQRFactor() for in-place factorization.
3468 
3469    Most users should employ the simplified KSP interface for linear solvers
3470    instead of working directly with matrix algebra routines such as this.
3471    See, e.g., KSPCreate().
3472 
3473    Level: developer
3474 
3475 .seealso: `MatQRFactorSymbolic()`, `MatLUFactor()`
3476 
3477     Developer Note: fortran interface is not autogenerated as the f90
3478     interface definition cannot be generated correctly [due to MatFactorInfo]
3479 
3480 @*/
3481 PetscErrorCode MatQRFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3482 {
3483   MatFactorInfo  tinfo;
3484 
3485   PetscFunctionBegin;
3486   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3487   PetscValidType(mat,2);
3488   PetscValidPointer(fact,1);
3489   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3490   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3491   PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3492 
3493   MatCheckPreallocated(mat,2);
3494   if (!info) {
3495     PetscCall(MatFactorInfoInitialize(&tinfo));
3496     info = &tinfo;
3497   }
3498 
3499   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric,mat,fact,0,0));
3500   else  PetscCall(PetscLogEventBegin(MAT_QRFactor,mat,fact,0,0));
3501   PetscUseMethod(fact,"MatQRFactorNumeric_C", (Mat,Mat,const MatFactorInfo*), (fact, mat, info));
3502   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric,mat,fact,0,0));
3503   else PetscCall(PetscLogEventEnd(MAT_QRFactor,mat,fact,0,0));
3504   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3505   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3506   PetscFunctionReturn(0);
3507 }
3508 
3509 /* ----------------------------------------------------------------*/
3510 /*@
3511    MatSolve - Solves A x = b, given a factored matrix.
3512 
3513    Neighbor-wise Collective on Mat
3514 
3515    Input Parameters:
3516 +  mat - the factored matrix
3517 -  b - the right-hand-side vector
3518 
3519    Output Parameter:
3520 .  x - the result vector
3521 
3522    Notes:
3523    The vectors b and x cannot be the same.  I.e., one cannot
3524    call MatSolve(A,x,x).
3525 
3526    Notes:
3527    Most users should employ the simplified KSP interface for linear solvers
3528    instead of working directly with matrix algebra routines such as this.
3529    See, e.g., KSPCreate().
3530 
3531    Level: developer
3532 
3533 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3534 @*/
3535 PetscErrorCode MatSolve(Mat mat,Vec b,Vec x)
3536 {
3537   PetscFunctionBegin;
3538   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3539   PetscValidType(mat,1);
3540   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3541   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3542   PetscCheckSameComm(mat,1,b,2);
3543   PetscCheckSameComm(mat,1,x,3);
3544   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3545   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3546   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3547   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3548   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3549   MatCheckPreallocated(mat,1);
3550 
3551   PetscCall(PetscLogEventBegin(MAT_Solve,mat,b,x,0));
3552   if (mat->factorerrortype) {
3553     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
3554     PetscCall(VecSetInf(x));
3555   } else {
3556     PetscCheck(mat->ops->solve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3557     PetscCall((*mat->ops->solve)(mat,b,x));
3558   }
3559   PetscCall(PetscLogEventEnd(MAT_Solve,mat,b,x,0));
3560   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3561   PetscFunctionReturn(0);
3562 }
3563 
3564 static PetscErrorCode MatMatSolve_Basic(Mat A,Mat B,Mat X,PetscBool trans)
3565 {
3566   Vec            b,x;
3567   PetscInt       N,i;
3568   PetscErrorCode (*f)(Mat,Vec,Vec);
3569   PetscBool      Abound,Bneedconv = PETSC_FALSE,Xneedconv = PETSC_FALSE;
3570 
3571   PetscFunctionBegin;
3572   if (A->factorerrortype) {
3573     PetscCall(PetscInfo(A,"MatFactorError %d\n",A->factorerrortype));
3574     PetscCall(MatSetInf(X));
3575     PetscFunctionReturn(0);
3576   }
3577   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3578   PetscCheck(f,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
3579   PetscCall(MatBoundToCPU(A,&Abound));
3580   if (!Abound) {
3581     PetscCall(PetscObjectTypeCompareAny((PetscObject)B,&Bneedconv,MATSEQDENSE,MATMPIDENSE,""));
3582     PetscCall(PetscObjectTypeCompareAny((PetscObject)X,&Xneedconv,MATSEQDENSE,MATMPIDENSE,""));
3583   }
3584   if (Bneedconv) {
3585     PetscCall(MatConvert(B,MATDENSECUDA,MAT_INPLACE_MATRIX,&B));
3586   }
3587   if (Xneedconv) {
3588     PetscCall(MatConvert(X,MATDENSECUDA,MAT_INPLACE_MATRIX,&X));
3589   }
3590   PetscCall(MatGetSize(B,NULL,&N));
3591   for (i=0; i<N; i++) {
3592     PetscCall(MatDenseGetColumnVecRead(B,i,&b));
3593     PetscCall(MatDenseGetColumnVecWrite(X,i,&x));
3594     PetscCall((*f)(A,b,x));
3595     PetscCall(MatDenseRestoreColumnVecWrite(X,i,&x));
3596     PetscCall(MatDenseRestoreColumnVecRead(B,i,&b));
3597   }
3598   if (Bneedconv) {
3599     PetscCall(MatConvert(B,MATDENSE,MAT_INPLACE_MATRIX,&B));
3600   }
3601   if (Xneedconv) {
3602     PetscCall(MatConvert(X,MATDENSE,MAT_INPLACE_MATRIX,&X));
3603   }
3604   PetscFunctionReturn(0);
3605 }
3606 
3607 /*@
3608    MatMatSolve - Solves A X = B, given a factored matrix.
3609 
3610    Neighbor-wise Collective on Mat
3611 
3612    Input Parameters:
3613 +  A - the factored matrix
3614 -  B - the right-hand-side matrix MATDENSE (or sparse -- when using MUMPS)
3615 
3616    Output Parameter:
3617 .  X - the result matrix (dense matrix)
3618 
3619    Notes:
3620    If B is a MATDENSE matrix then one can call MatMatSolve(A,B,B) except with MKL_CPARDISO;
3621    otherwise, B and X cannot be the same.
3622 
3623    Notes:
3624    Most users should usually employ the simplified KSP interface for linear solvers
3625    instead of working directly with matrix algebra routines such as this.
3626    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3627    at a time.
3628 
3629    Level: developer
3630 
3631 .seealso: `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3632 @*/
3633 PetscErrorCode MatMatSolve(Mat A,Mat B,Mat X)
3634 {
3635   PetscFunctionBegin;
3636   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3637   PetscValidType(A,1);
3638   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3639   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3640   PetscCheckSameComm(A,1,B,2);
3641   PetscCheckSameComm(A,1,X,3);
3642   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3643   PetscCheck(A->rmap->N == B->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N);
3644   PetscCheck(X->cmap->N == B->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as rhs matrix");
3645   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3646   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3647   MatCheckPreallocated(A,1);
3648 
3649   PetscCall(PetscLogEventBegin(MAT_MatSolve,A,B,X,0));
3650   if (!A->ops->matsolve) {
3651     PetscCall(PetscInfo(A,"Mat type %s using basic MatMatSolve\n",((PetscObject)A)->type_name));
3652     PetscCall(MatMatSolve_Basic(A,B,X,PETSC_FALSE));
3653   } else {
3654     PetscCall((*A->ops->matsolve)(A,B,X));
3655   }
3656   PetscCall(PetscLogEventEnd(MAT_MatSolve,A,B,X,0));
3657   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3658   PetscFunctionReturn(0);
3659 }
3660 
3661 /*@
3662    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3663 
3664    Neighbor-wise Collective on Mat
3665 
3666    Input Parameters:
3667 +  A - the factored matrix
3668 -  B - the right-hand-side matrix  (dense matrix)
3669 
3670    Output Parameter:
3671 .  X - the result matrix (dense matrix)
3672 
3673    Notes:
3674    The matrices B and X cannot be the same.  I.e., one cannot
3675    call MatMatSolveTranspose(A,X,X).
3676 
3677    Notes:
3678    Most users should usually employ the simplified KSP interface for linear solvers
3679    instead of working directly with matrix algebra routines such as this.
3680    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3681    at a time.
3682 
3683    When using SuperLU_Dist or MUMPS as a parallel solver, PETSc will use their functionality to solve multiple right hand sides simultaneously.
3684 
3685    Level: developer
3686 
3687 .seealso: `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3688 @*/
3689 PetscErrorCode MatMatSolveTranspose(Mat A,Mat B,Mat X)
3690 {
3691   PetscFunctionBegin;
3692   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3693   PetscValidType(A,1);
3694   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3695   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3696   PetscCheckSameComm(A,1,B,2);
3697   PetscCheckSameComm(A,1,X,3);
3698   PetscCheck(X != B,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3699   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3700   PetscCheck(A->rmap->N == B->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N);
3701   PetscCheck(A->rmap->n == B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->n,B->rmap->n);
3702   PetscCheck(X->cmap->N >= B->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as rhs matrix");
3703   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3704   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3705   MatCheckPreallocated(A,1);
3706 
3707   PetscCall(PetscLogEventBegin(MAT_MatSolve,A,B,X,0));
3708   if (!A->ops->matsolvetranspose) {
3709     PetscCall(PetscInfo(A,"Mat type %s using basic MatMatSolveTranspose\n",((PetscObject)A)->type_name));
3710     PetscCall(MatMatSolve_Basic(A,B,X,PETSC_TRUE));
3711   } else {
3712     PetscCall((*A->ops->matsolvetranspose)(A,B,X));
3713   }
3714   PetscCall(PetscLogEventEnd(MAT_MatSolve,A,B,X,0));
3715   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3716   PetscFunctionReturn(0);
3717 }
3718 
3719 /*@
3720    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3721 
3722    Neighbor-wise Collective on Mat
3723 
3724    Input Parameters:
3725 +  A - the factored matrix
3726 -  Bt - the transpose of right-hand-side matrix
3727 
3728    Output Parameter:
3729 .  X - the result matrix (dense matrix)
3730 
3731    Notes:
3732    Most users should usually employ the simplified KSP interface for linear solvers
3733    instead of working directly with matrix algebra routines such as this.
3734    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3735    at a time.
3736 
3737    For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row format on the host processor and call MatMatTransposeSolve() to implement MUMPS' MatMatSolve().
3738 
3739    Level: developer
3740 
3741 .seealso: `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3742 @*/
3743 PetscErrorCode MatMatTransposeSolve(Mat A,Mat Bt,Mat X)
3744 {
3745   PetscFunctionBegin;
3746   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3747   PetscValidType(A,1);
3748   PetscValidHeaderSpecific(Bt,MAT_CLASSID,2);
3749   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3750   PetscCheckSameComm(A,1,Bt,2);
3751   PetscCheckSameComm(A,1,X,3);
3752 
3753   PetscCheck(X != Bt,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3754   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3755   PetscCheck(A->rmap->N == Bt->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,Bt->cmap->N);
3756   PetscCheck(X->cmap->N >= Bt->rmap->N,PetscObjectComm((PetscObject)X),PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as row number of the rhs matrix");
3757   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3758   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3759   MatCheckPreallocated(A,1);
3760 
3761   PetscCheck(A->ops->mattransposesolve,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
3762   PetscCall(PetscLogEventBegin(MAT_MatTrSolve,A,Bt,X,0));
3763   PetscCall((*A->ops->mattransposesolve)(A,Bt,X));
3764   PetscCall(PetscLogEventEnd(MAT_MatTrSolve,A,Bt,X,0));
3765   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3766   PetscFunctionReturn(0);
3767 }
3768 
3769 /*@
3770    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3771                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3772 
3773    Neighbor-wise Collective on Mat
3774 
3775    Input Parameters:
3776 +  mat - the factored matrix
3777 -  b - the right-hand-side vector
3778 
3779    Output Parameter:
3780 .  x - the result vector
3781 
3782    Notes:
3783    MatSolve() should be used for most applications, as it performs
3784    a forward solve followed by a backward solve.
3785 
3786    The vectors b and x cannot be the same,  i.e., one cannot
3787    call MatForwardSolve(A,x,x).
3788 
3789    For matrix in seqsbaij format with block size larger than 1,
3790    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3791    MatForwardSolve() solves U^T*D y = b, and
3792    MatBackwardSolve() solves U x = y.
3793    Thus they do not provide a symmetric preconditioner.
3794 
3795    Most users should employ the simplified KSP interface for linear solvers
3796    instead of working directly with matrix algebra routines such as this.
3797    See, e.g., KSPCreate().
3798 
3799    Level: developer
3800 
3801 .seealso: `MatSolve()`, `MatBackwardSolve()`
3802 @*/
3803 PetscErrorCode MatForwardSolve(Mat mat,Vec b,Vec x)
3804 {
3805   PetscFunctionBegin;
3806   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3807   PetscValidType(mat,1);
3808   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3809   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3810   PetscCheckSameComm(mat,1,b,2);
3811   PetscCheckSameComm(mat,1,x,3);
3812   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3813   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3814   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3815   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3816   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3817   MatCheckPreallocated(mat,1);
3818 
3819   PetscCheck(mat->ops->forwardsolve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3820   PetscCall(PetscLogEventBegin(MAT_ForwardSolve,mat,b,x,0));
3821   PetscCall((*mat->ops->forwardsolve)(mat,b,x));
3822   PetscCall(PetscLogEventEnd(MAT_ForwardSolve,mat,b,x,0));
3823   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3824   PetscFunctionReturn(0);
3825 }
3826 
3827 /*@
3828    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3829                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3830 
3831    Neighbor-wise Collective on Mat
3832 
3833    Input Parameters:
3834 +  mat - the factored matrix
3835 -  b - the right-hand-side vector
3836 
3837    Output Parameter:
3838 .  x - the result vector
3839 
3840    Notes:
3841    MatSolve() should be used for most applications, as it performs
3842    a forward solve followed by a backward solve.
3843 
3844    The vectors b and x cannot be the same.  I.e., one cannot
3845    call MatBackwardSolve(A,x,x).
3846 
3847    For matrix in seqsbaij format with block size larger than 1,
3848    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3849    MatForwardSolve() solves U^T*D y = b, and
3850    MatBackwardSolve() solves U x = y.
3851    Thus they do not provide a symmetric preconditioner.
3852 
3853    Most users should employ the simplified KSP interface for linear solvers
3854    instead of working directly with matrix algebra routines such as this.
3855    See, e.g., KSPCreate().
3856 
3857    Level: developer
3858 
3859 .seealso: `MatSolve()`, `MatForwardSolve()`
3860 @*/
3861 PetscErrorCode MatBackwardSolve(Mat mat,Vec b,Vec x)
3862 {
3863   PetscFunctionBegin;
3864   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3865   PetscValidType(mat,1);
3866   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3867   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3868   PetscCheckSameComm(mat,1,b,2);
3869   PetscCheckSameComm(mat,1,x,3);
3870   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3871   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3872   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3873   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3874   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3875   MatCheckPreallocated(mat,1);
3876 
3877   PetscCheck(mat->ops->backwardsolve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3878   PetscCall(PetscLogEventBegin(MAT_BackwardSolve,mat,b,x,0));
3879   PetscCall((*mat->ops->backwardsolve)(mat,b,x));
3880   PetscCall(PetscLogEventEnd(MAT_BackwardSolve,mat,b,x,0));
3881   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3882   PetscFunctionReturn(0);
3883 }
3884 
3885 /*@
3886    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3887 
3888    Neighbor-wise Collective on Mat
3889 
3890    Input Parameters:
3891 +  mat - the factored matrix
3892 .  b - the right-hand-side vector
3893 -  y - the vector to be added to
3894 
3895    Output Parameter:
3896 .  x - the result vector
3897 
3898    Notes:
3899    The vectors b and x cannot be the same.  I.e., one cannot
3900    call MatSolveAdd(A,x,y,x).
3901 
3902    Most users should employ the simplified KSP interface for linear solvers
3903    instead of working directly with matrix algebra routines such as this.
3904    See, e.g., KSPCreate().
3905 
3906    Level: developer
3907 
3908 .seealso: `MatSolve()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3909 @*/
3910 PetscErrorCode MatSolveAdd(Mat mat,Vec b,Vec y,Vec x)
3911 {
3912   PetscScalar    one = 1.0;
3913   Vec            tmp;
3914 
3915   PetscFunctionBegin;
3916   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3917   PetscValidType(mat,1);
3918   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3919   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3920   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
3921   PetscCheckSameComm(mat,1,b,2);
3922   PetscCheckSameComm(mat,1,y,3);
3923   PetscCheckSameComm(mat,1,x,4);
3924   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3925   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3926   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3927   PetscCheck(mat->rmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,y->map->N);
3928   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3929   PetscCheck(x->map->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,x->map->n,y->map->n);
3930   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3931    MatCheckPreallocated(mat,1);
3932 
3933   PetscCall(PetscLogEventBegin(MAT_SolveAdd,mat,b,x,y));
3934   if (mat->factorerrortype) {
3935 
3936     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
3937     PetscCall(VecSetInf(x));
3938   } else if (mat->ops->solveadd) {
3939     PetscCall((*mat->ops->solveadd)(mat,b,y,x));
3940   } else {
3941     /* do the solve then the add manually */
3942     if (x != y) {
3943       PetscCall(MatSolve(mat,b,x));
3944       PetscCall(VecAXPY(x,one,y));
3945     } else {
3946       PetscCall(VecDuplicate(x,&tmp));
3947       PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp));
3948       PetscCall(VecCopy(x,tmp));
3949       PetscCall(MatSolve(mat,b,x));
3950       PetscCall(VecAXPY(x,one,tmp));
3951       PetscCall(VecDestroy(&tmp));
3952     }
3953   }
3954   PetscCall(PetscLogEventEnd(MAT_SolveAdd,mat,b,x,y));
3955   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3956   PetscFunctionReturn(0);
3957 }
3958 
3959 /*@
3960    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3961 
3962    Neighbor-wise Collective on Mat
3963 
3964    Input Parameters:
3965 +  mat - the factored matrix
3966 -  b - the right-hand-side vector
3967 
3968    Output Parameter:
3969 .  x - the result vector
3970 
3971    Notes:
3972    The vectors b and x cannot be the same.  I.e., one cannot
3973    call MatSolveTranspose(A,x,x).
3974 
3975    Most users should employ the simplified KSP interface for linear solvers
3976    instead of working directly with matrix algebra routines such as this.
3977    See, e.g., KSPCreate().
3978 
3979    Level: developer
3980 
3981 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3982 @*/
3983 PetscErrorCode MatSolveTranspose(Mat mat,Vec b,Vec x)
3984 {
3985   PetscErrorCode (*f)(Mat,Vec,Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3986 
3987   PetscFunctionBegin;
3988   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3989   PetscValidType(mat,1);
3990   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3991   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3992   PetscCheckSameComm(mat,1,b,2);
3993   PetscCheckSameComm(mat,1,x,3);
3994   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3995   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
3996   PetscCheck(mat->cmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,b->map->N);
3997   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3998   MatCheckPreallocated(mat,1);
3999   PetscCall(PetscLogEventBegin(MAT_SolveTranspose,mat,b,x,0));
4000   if (mat->factorerrortype) {
4001     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
4002     PetscCall(VecSetInf(x));
4003   } else {
4004     PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s",((PetscObject)mat)->type_name);
4005     PetscCall((*f)(mat,b,x));
4006   }
4007   PetscCall(PetscLogEventEnd(MAT_SolveTranspose,mat,b,x,0));
4008   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4009   PetscFunctionReturn(0);
4010 }
4011 
4012 /*@
4013    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4014                       factored matrix.
4015 
4016    Neighbor-wise Collective on Mat
4017 
4018    Input Parameters:
4019 +  mat - the factored matrix
4020 .  b - the right-hand-side vector
4021 -  y - the vector to be added to
4022 
4023    Output Parameter:
4024 .  x - the result vector
4025 
4026    Notes:
4027    The vectors b and x cannot be the same.  I.e., one cannot
4028    call MatSolveTransposeAdd(A,x,y,x).
4029 
4030    Most users should employ the simplified KSP interface for linear solvers
4031    instead of working directly with matrix algebra routines such as this.
4032    See, e.g., KSPCreate().
4033 
4034    Level: developer
4035 
4036 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4037 @*/
4038 PetscErrorCode MatSolveTransposeAdd(Mat mat,Vec b,Vec y,Vec x)
4039 {
4040   PetscScalar    one = 1.0;
4041   Vec            tmp;
4042   PetscErrorCode (*f)(Mat,Vec,Vec,Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4043 
4044   PetscFunctionBegin;
4045   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4046   PetscValidType(mat,1);
4047   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
4048   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4049   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
4050   PetscCheckSameComm(mat,1,b,2);
4051   PetscCheckSameComm(mat,1,y,3);
4052   PetscCheckSameComm(mat,1,x,4);
4053   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
4054   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
4055   PetscCheck(mat->cmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,b->map->N);
4056   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
4057   PetscCheck(x->map->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,x->map->n,y->map->n);
4058   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4059   MatCheckPreallocated(mat,1);
4060 
4061   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd,mat,b,x,y));
4062   if (mat->factorerrortype) {
4063     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
4064     PetscCall(VecSetInf(x));
4065   } else if (f) {
4066     PetscCall((*f)(mat,b,y,x));
4067   } else {
4068     /* do the solve then the add manually */
4069     if (x != y) {
4070       PetscCall(MatSolveTranspose(mat,b,x));
4071       PetscCall(VecAXPY(x,one,y));
4072     } else {
4073       PetscCall(VecDuplicate(x,&tmp));
4074       PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp));
4075       PetscCall(VecCopy(x,tmp));
4076       PetscCall(MatSolveTranspose(mat,b,x));
4077       PetscCall(VecAXPY(x,one,tmp));
4078       PetscCall(VecDestroy(&tmp));
4079     }
4080   }
4081   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd,mat,b,x,y));
4082   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4083   PetscFunctionReturn(0);
4084 }
4085 /* ----------------------------------------------------------------*/
4086 
4087 /*@
4088    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4089 
4090    Neighbor-wise Collective on Mat
4091 
4092    Input Parameters:
4093 +  mat - the matrix
4094 .  b - the right hand side
4095 .  omega - the relaxation factor
4096 .  flag - flag indicating the type of SOR (see below)
4097 .  shift -  diagonal shift
4098 .  its - the number of iterations
4099 -  lits - the number of local iterations
4100 
4101    Output Parameter:
4102 .  x - the solution (can contain an initial guess, use option SOR_ZERO_INITIAL_GUESS to indicate no guess)
4103 
4104    SOR Flags:
4105 +     SOR_FORWARD_SWEEP - forward SOR
4106 .     SOR_BACKWARD_SWEEP - backward SOR
4107 .     SOR_SYMMETRIC_SWEEP - SSOR (symmetric SOR)
4108 .     SOR_LOCAL_FORWARD_SWEEP - local forward SOR
4109 .     SOR_LOCAL_BACKWARD_SWEEP - local forward SOR
4110 .     SOR_LOCAL_SYMMETRIC_SWEEP - local SSOR
4111 .     SOR_APPLY_UPPER, SOR_APPLY_LOWER - applies
4112          upper/lower triangular part of matrix to
4113          vector (with omega)
4114 -     SOR_ZERO_INITIAL_GUESS - zero initial guess
4115 
4116    Notes:
4117    SOR_LOCAL_FORWARD_SWEEP, SOR_LOCAL_BACKWARD_SWEEP, and
4118    SOR_LOCAL_SYMMETRIC_SWEEP perform separate independent smoothings
4119    on each processor.
4120 
4121    Application programmers will not generally use MatSOR() directly,
4122    but instead will employ the KSP/PC interface.
4123 
4124    Notes:
4125     for BAIJ, SBAIJ, and AIJ matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4126 
4127    Notes for Advanced Users:
4128    The flags are implemented as bitwise inclusive or operations.
4129    For example, use (SOR_ZERO_INITIAL_GUESS | SOR_SYMMETRIC_SWEEP)
4130    to specify a zero initial guess for SSOR.
4131 
4132    Most users should employ the simplified KSP interface for linear solvers
4133    instead of working directly with matrix algebra routines such as this.
4134    See, e.g., KSPCreate().
4135 
4136    Vectors x and b CANNOT be the same
4137 
4138    Developer Note: We should add block SOR support for AIJ matrices with block size set to great than one and no inodes
4139 
4140    Level: developer
4141 
4142 @*/
4143 PetscErrorCode MatSOR(Mat mat,Vec b,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec x)
4144 {
4145   PetscFunctionBegin;
4146   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4147   PetscValidType(mat,1);
4148   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4149   PetscValidHeaderSpecific(x,VEC_CLASSID,8);
4150   PetscCheckSameComm(mat,1,b,2);
4151   PetscCheckSameComm(mat,1,x,8);
4152   PetscCheck(mat->ops->sor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4153   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4154   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4155   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
4156   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
4157   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
4158   PetscCheck(its > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %" PetscInt_FMT " positive",its);
4159   PetscCheck(lits > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires local its %" PetscInt_FMT " positive",lits);
4160   PetscCheck(b != x,PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"b and x vector cannot be the same");
4161 
4162   MatCheckPreallocated(mat,1);
4163   PetscCall(PetscLogEventBegin(MAT_SOR,mat,b,x,0));
4164   PetscCall((*mat->ops->sor)(mat,b,omega,flag,shift,its,lits,x));
4165   PetscCall(PetscLogEventEnd(MAT_SOR,mat,b,x,0));
4166   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4167   PetscFunctionReturn(0);
4168 }
4169 
4170 /*
4171       Default matrix copy routine.
4172 */
4173 PetscErrorCode MatCopy_Basic(Mat A,Mat B,MatStructure str)
4174 {
4175   PetscInt          i,rstart = 0,rend = 0,nz;
4176   const PetscInt    *cwork;
4177   const PetscScalar *vwork;
4178 
4179   PetscFunctionBegin;
4180   if (B->assembled) {
4181     PetscCall(MatZeroEntries(B));
4182   }
4183   if (str == SAME_NONZERO_PATTERN) {
4184     PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
4185     for (i=rstart; i<rend; i++) {
4186       PetscCall(MatGetRow(A,i,&nz,&cwork,&vwork));
4187       PetscCall(MatSetValues(B,1,&i,nz,cwork,vwork,INSERT_VALUES));
4188       PetscCall(MatRestoreRow(A,i,&nz,&cwork,&vwork));
4189     }
4190   } else {
4191     PetscCall(MatAYPX(B,0.0,A,str));
4192   }
4193   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
4194   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
4195   PetscFunctionReturn(0);
4196 }
4197 
4198 /*@
4199    MatCopy - Copies a matrix to another matrix.
4200 
4201    Collective on Mat
4202 
4203    Input Parameters:
4204 +  A - the matrix
4205 -  str - SAME_NONZERO_PATTERN or DIFFERENT_NONZERO_PATTERN
4206 
4207    Output Parameter:
4208 .  B - where the copy is put
4209 
4210    Notes:
4211    If you use SAME_NONZERO_PATTERN then the two matrices must have the same nonzero pattern or the routine will crash.
4212 
4213    MatCopy() copies the matrix entries of a matrix to another existing
4214    matrix (after first zeroing the second matrix).  A related routine is
4215    MatConvert(), which first creates a new matrix and then copies the data.
4216 
4217    Level: intermediate
4218 
4219 .seealso: `MatConvert()`, `MatDuplicate()`
4220 @*/
4221 PetscErrorCode MatCopy(Mat A,Mat B,MatStructure str)
4222 {
4223   PetscInt       i;
4224 
4225   PetscFunctionBegin;
4226   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4227   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4228   PetscValidType(A,1);
4229   PetscValidType(B,2);
4230   PetscCheckSameComm(A,1,B,2);
4231   MatCheckPreallocated(B,2);
4232   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4233   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4234   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);
4235   MatCheckPreallocated(A,1);
4236   if (A == B) PetscFunctionReturn(0);
4237 
4238   PetscCall(PetscLogEventBegin(MAT_Copy,A,B,0,0));
4239   if (A->ops->copy) {
4240     PetscCall((*A->ops->copy)(A,B,str));
4241   } else { /* generic conversion */
4242     PetscCall(MatCopy_Basic(A,B,str));
4243   }
4244 
4245   B->stencil.dim = A->stencil.dim;
4246   B->stencil.noc = A->stencil.noc;
4247   for (i=0; i<=A->stencil.dim; i++) {
4248     B->stencil.dims[i]   = A->stencil.dims[i];
4249     B->stencil.starts[i] = A->stencil.starts[i];
4250   }
4251 
4252   PetscCall(PetscLogEventEnd(MAT_Copy,A,B,0,0));
4253   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4254   PetscFunctionReturn(0);
4255 }
4256 
4257 /*@C
4258    MatConvert - Converts a matrix to another matrix, either of the same
4259    or different type.
4260 
4261    Collective on Mat
4262 
4263    Input Parameters:
4264 +  mat - the matrix
4265 .  newtype - new matrix type.  Use MATSAME to create a new matrix of the
4266    same type as the original matrix.
4267 -  reuse - denotes if the destination matrix is to be created or reused.
4268    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
4269    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).
4270 
4271    Output Parameter:
4272 .  M - pointer to place new matrix
4273 
4274    Notes:
4275    MatConvert() first creates a new matrix and then copies the data from
4276    the first matrix.  A related routine is MatCopy(), which copies the matrix
4277    entries of one matrix to another already existing matrix context.
4278 
4279    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4280    the MPI communicator of the generated matrix is always the same as the communicator
4281    of the input matrix.
4282 
4283    Level: intermediate
4284 
4285 .seealso: `MatCopy()`, `MatDuplicate()`
4286 @*/
4287 PetscErrorCode MatConvert(Mat mat,MatType newtype,MatReuse reuse,Mat *M)
4288 {
4289   PetscBool      sametype,issame,flg,issymmetric,ishermitian;
4290   char           convname[256],mtype[256];
4291   Mat            B;
4292 
4293   PetscFunctionBegin;
4294   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4295   PetscValidType(mat,1);
4296   PetscValidPointer(M,4);
4297   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4298   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4299   MatCheckPreallocated(mat,1);
4300 
4301   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matconvert_type",mtype,sizeof(mtype),&flg));
4302   if (flg) newtype = mtype;
4303 
4304   PetscCall(PetscObjectTypeCompare((PetscObject)mat,newtype,&sametype));
4305   PetscCall(PetscStrcmp(newtype,"same",&issame));
4306   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M),PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires same input and output matrix");
4307   PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M),PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4308 
4309   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4310     PetscCall(PetscInfo(mat,"Early return for inplace %s %d %d\n",((PetscObject)mat)->type_name,sametype,issame));
4311     PetscFunctionReturn(0);
4312   }
4313 
4314   /* Cache Mat options because some converter use MatHeaderReplace  */
4315   issymmetric = mat->symmetric;
4316   ishermitian = mat->hermitian;
4317 
4318   if ((sametype || issame) && (reuse==MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4319     PetscCall(PetscInfo(mat,"Calling duplicate for initial matrix %s %d %d\n",((PetscObject)mat)->type_name,sametype,issame));
4320     PetscCall((*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M));
4321   } else {
4322     PetscErrorCode (*conv)(Mat, MatType,MatReuse,Mat*)=NULL;
4323     const char     *prefix[3] = {"seq","mpi",""};
4324     PetscInt       i;
4325     /*
4326        Order of precedence:
4327        0) See if newtype is a superclass of the current matrix.
4328        1) See if a specialized converter is known to the current matrix.
4329        2) See if a specialized converter is known to the desired matrix class.
4330        3) See if a good general converter is registered for the desired class
4331           (as of 6/27/03 only MATMPIADJ falls into this category).
4332        4) See if a good general converter is known for the current matrix.
4333        5) Use a really basic converter.
4334     */
4335 
4336     /* 0) See if newtype is a superclass of the current matrix.
4337           i.e mat is mpiaij and newtype is aij */
4338     for (i=0; i<2; i++) {
4339       PetscCall(PetscStrncpy(convname,prefix[i],sizeof(convname)));
4340       PetscCall(PetscStrlcat(convname,newtype,sizeof(convname)));
4341       PetscCall(PetscStrcmp(convname,((PetscObject)mat)->type_name,&flg));
4342       PetscCall(PetscInfo(mat,"Check superclass %s %s -> %d\n",convname,((PetscObject)mat)->type_name,flg));
4343       if (flg) {
4344         if (reuse == MAT_INPLACE_MATRIX) {
4345           PetscCall(PetscInfo(mat,"Early return\n"));
4346           PetscFunctionReturn(0);
4347         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4348           PetscCall(PetscInfo(mat,"Calling MatDuplicate\n"));
4349           PetscCall((*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M));
4350           PetscFunctionReturn(0);
4351         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4352           PetscCall(PetscInfo(mat,"Calling MatCopy\n"));
4353           PetscCall(MatCopy(mat,*M,SAME_NONZERO_PATTERN));
4354           PetscFunctionReturn(0);
4355         }
4356       }
4357     }
4358     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4359     for (i=0; i<3; i++) {
4360       PetscCall(PetscStrncpy(convname,"MatConvert_",sizeof(convname)));
4361       PetscCall(PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname)));
4362       PetscCall(PetscStrlcat(convname,"_",sizeof(convname)));
4363       PetscCall(PetscStrlcat(convname,prefix[i],sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname,issame ? ((PetscObject)mat)->type_name : newtype,sizeof(convname)));
4365       PetscCall(PetscStrlcat(convname,"_C",sizeof(convname)));
4366       PetscCall(PetscObjectQueryFunction((PetscObject)mat,convname,&conv));
4367       PetscCall(PetscInfo(mat,"Check specialized (1) %s (%s) -> %d\n",convname,((PetscObject)mat)->type_name,!!conv));
4368       if (conv) goto foundconv;
4369     }
4370 
4371     /* 2)  See if a specialized converter is known to the desired matrix class. */
4372     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&B));
4373     PetscCall(MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
4374     PetscCall(MatSetType(B,newtype));
4375     for (i=0; i<3; i++) {
4376       PetscCall(PetscStrncpy(convname,"MatConvert_",sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname,"_",sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname,prefix[i],sizeof(convname)));
4380       PetscCall(PetscStrlcat(convname,newtype,sizeof(convname)));
4381       PetscCall(PetscStrlcat(convname,"_C",sizeof(convname)));
4382       PetscCall(PetscObjectQueryFunction((PetscObject)B,convname,&conv));
4383       PetscCall(PetscInfo(mat,"Check specialized (2) %s (%s) -> %d\n",convname,((PetscObject)B)->type_name,!!conv));
4384       if (conv) {
4385         PetscCall(MatDestroy(&B));
4386         goto foundconv;
4387       }
4388     }
4389 
4390     /* 3) See if a good general converter is registered for the desired class */
4391     conv = B->ops->convertfrom;
4392     PetscCall(PetscInfo(mat,"Check convertfrom (%s) -> %d\n",((PetscObject)B)->type_name,!!conv));
4393     PetscCall(MatDestroy(&B));
4394     if (conv) goto foundconv;
4395 
4396     /* 4) See if a good general converter is known for the current matrix */
4397     if (mat->ops->convert) conv = mat->ops->convert;
4398     PetscCall(PetscInfo(mat,"Check general convert (%s) -> %d\n",((PetscObject)mat)->type_name,!!conv));
4399     if (conv) goto foundconv;
4400 
4401     /* 5) Use a really basic converter. */
4402     PetscCall(PetscInfo(mat,"Using MatConvert_Basic\n"));
4403     conv = MatConvert_Basic;
4404 
4405 foundconv:
4406     PetscCall(PetscLogEventBegin(MAT_Convert,mat,0,0,0));
4407     PetscCall((*conv)(mat,newtype,reuse,M));
4408     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4409       /* the block sizes must be same if the mappings are copied over */
4410       (*M)->rmap->bs = mat->rmap->bs;
4411       (*M)->cmap->bs = mat->cmap->bs;
4412       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4413       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4414       (*M)->rmap->mapping = mat->rmap->mapping;
4415       (*M)->cmap->mapping = mat->cmap->mapping;
4416     }
4417     (*M)->stencil.dim = mat->stencil.dim;
4418     (*M)->stencil.noc = mat->stencil.noc;
4419     for (i=0; i<=mat->stencil.dim; i++) {
4420       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4421       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4422     }
4423     PetscCall(PetscLogEventEnd(MAT_Convert,mat,0,0,0));
4424   }
4425   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4426 
4427   /* Copy Mat options */
4428   if (issymmetric) {
4429     PetscCall(MatSetOption(*M,MAT_SYMMETRIC,PETSC_TRUE));
4430   }
4431   if (ishermitian) {
4432     PetscCall(MatSetOption(*M,MAT_HERMITIAN,PETSC_TRUE));
4433   }
4434   PetscFunctionReturn(0);
4435 }
4436 
4437 /*@C
4438    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4439 
4440    Not Collective
4441 
4442    Input Parameter:
4443 .  mat - the matrix, must be a factored matrix
4444 
4445    Output Parameter:
4446 .   type - the string name of the package (do not free this string)
4447 
4448    Notes:
4449       In Fortran you pass in a empty string and the package name will be copied into it.
4450     (Make sure the string is long enough)
4451 
4452    Level: intermediate
4453 
4454 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4455 @*/
4456 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4457 {
4458   PetscErrorCode (*conv)(Mat,MatSolverType*);
4459 
4460   PetscFunctionBegin;
4461   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4462   PetscValidType(mat,1);
4463   PetscValidPointer(type,2);
4464   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
4465   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorGetSolverType_C",&conv));
4466   if (conv) PetscCall((*conv)(mat,type));
4467   else *type = MATSOLVERPETSC;
4468   PetscFunctionReturn(0);
4469 }
4470 
4471 typedef struct _MatSolverTypeForSpecifcType* MatSolverTypeForSpecifcType;
4472 struct _MatSolverTypeForSpecifcType {
4473   MatType                        mtype;
4474   /* no entry for MAT_FACTOR_NONE */
4475   PetscErrorCode                 (*createfactor[MAT_FACTOR_NUM_TYPES-1])(Mat,MatFactorType,Mat*);
4476   MatSolverTypeForSpecifcType next;
4477 };
4478 
4479 typedef struct _MatSolverTypeHolder* MatSolverTypeHolder;
4480 struct _MatSolverTypeHolder {
4481   char                        *name;
4482   MatSolverTypeForSpecifcType handlers;
4483   MatSolverTypeHolder         next;
4484 };
4485 
4486 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4487 
4488 /*@C
4489    MatSolverTypeRegister - Registers a MatSolverType that works for a particular matrix type
4490 
4491    Input Parameters:
4492 +    package - name of the package, for example petsc or superlu
4493 .    mtype - the matrix type that works with this package
4494 .    ftype - the type of factorization supported by the package
4495 -    createfactor - routine that will create the factored matrix ready to be used
4496 
4497     Level: intermediate
4498 
4499 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4500 @*/
4501 PetscErrorCode MatSolverTypeRegister(MatSolverType package,MatType mtype,MatFactorType ftype,PetscErrorCode (*createfactor)(Mat,MatFactorType,Mat*))
4502 {
4503   MatSolverTypeHolder         next = MatSolverTypeHolders,prev = NULL;
4504   PetscBool                   flg;
4505   MatSolverTypeForSpecifcType inext,iprev = NULL;
4506 
4507   PetscFunctionBegin;
4508   PetscCall(MatInitializePackage());
4509   if (!next) {
4510     PetscCall(PetscNew(&MatSolverTypeHolders));
4511     PetscCall(PetscStrallocpy(package,&MatSolverTypeHolders->name));
4512     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4513     PetscCall(PetscStrallocpy(mtype,(char **)&MatSolverTypeHolders->handlers->mtype));
4514     MatSolverTypeHolders->handlers->createfactor[(int)ftype-1] = createfactor;
4515     PetscFunctionReturn(0);
4516   }
4517   while (next) {
4518     PetscCall(PetscStrcasecmp(package,next->name,&flg));
4519     if (flg) {
4520       PetscCheck(next->handlers,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatSolverTypeHolder is missing handlers");
4521       inext = next->handlers;
4522       while (inext) {
4523         PetscCall(PetscStrcasecmp(mtype,inext->mtype,&flg));
4524         if (flg) {
4525           inext->createfactor[(int)ftype-1] = createfactor;
4526           PetscFunctionReturn(0);
4527         }
4528         iprev = inext;
4529         inext = inext->next;
4530       }
4531       PetscCall(PetscNew(&iprev->next));
4532       PetscCall(PetscStrallocpy(mtype,(char **)&iprev->next->mtype));
4533       iprev->next->createfactor[(int)ftype-1] = createfactor;
4534       PetscFunctionReturn(0);
4535     }
4536     prev = next;
4537     next = next->next;
4538   }
4539   PetscCall(PetscNew(&prev->next));
4540   PetscCall(PetscStrallocpy(package,&prev->next->name));
4541   PetscCall(PetscNew(&prev->next->handlers));
4542   PetscCall(PetscStrallocpy(mtype,(char **)&prev->next->handlers->mtype));
4543   prev->next->handlers->createfactor[(int)ftype-1] = createfactor;
4544   PetscFunctionReturn(0);
4545 }
4546 
4547 /*@C
4548    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4549 
4550    Input Parameters:
4551 +    type - name of the package, for example petsc or superlu
4552 .    ftype - the type of factorization supported by the type
4553 -    mtype - the matrix type that works with this type
4554 
4555    Output Parameters:
4556 +   foundtype - PETSC_TRUE if the type was registered
4557 .   foundmtype - PETSC_TRUE if the type supports the requested mtype
4558 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4559 
4560     Level: intermediate
4561 
4562 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4563 @*/
4564 PetscErrorCode MatSolverTypeGet(MatSolverType type,MatType mtype,MatFactorType ftype,PetscBool *foundtype,PetscBool *foundmtype,PetscErrorCode (**createfactor)(Mat,MatFactorType,Mat*))
4565 {
4566   MatSolverTypeHolder         next = MatSolverTypeHolders;
4567   PetscBool                   flg;
4568   MatSolverTypeForSpecifcType inext;
4569 
4570   PetscFunctionBegin;
4571   if (foundtype) *foundtype = PETSC_FALSE;
4572   if (foundmtype) *foundmtype = PETSC_FALSE;
4573   if (createfactor) *createfactor = NULL;
4574 
4575   if (type) {
4576     while (next) {
4577       PetscCall(PetscStrcasecmp(type,next->name,&flg));
4578       if (flg) {
4579         if (foundtype) *foundtype = PETSC_TRUE;
4580         inext = next->handlers;
4581         while (inext) {
4582           PetscCall(PetscStrbeginswith(mtype,inext->mtype,&flg));
4583           if (flg) {
4584             if (foundmtype) *foundmtype = PETSC_TRUE;
4585             if (createfactor)  *createfactor  = inext->createfactor[(int)ftype-1];
4586             PetscFunctionReturn(0);
4587           }
4588           inext = inext->next;
4589         }
4590       }
4591       next = next->next;
4592     }
4593   } else {
4594     while (next) {
4595       inext = next->handlers;
4596       while (inext) {
4597         PetscCall(PetscStrcmp(mtype,inext->mtype,&flg));
4598         if (flg && inext->createfactor[(int)ftype-1]) {
4599           if (foundtype) *foundtype = PETSC_TRUE;
4600           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4601           if (createfactor) *createfactor = inext->createfactor[(int)ftype-1];
4602           PetscFunctionReturn(0);
4603         }
4604         inext = inext->next;
4605       }
4606       next = next->next;
4607     }
4608     /* try with base classes inext->mtype */
4609     next = MatSolverTypeHolders;
4610     while (next) {
4611       inext = next->handlers;
4612       while (inext) {
4613         PetscCall(PetscStrbeginswith(mtype,inext->mtype,&flg));
4614         if (flg && inext->createfactor[(int)ftype-1]) {
4615           if (foundtype) *foundtype = PETSC_TRUE;
4616           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4617           if (createfactor) *createfactor = inext->createfactor[(int)ftype-1];
4618           PetscFunctionReturn(0);
4619         }
4620         inext = inext->next;
4621       }
4622       next = next->next;
4623     }
4624   }
4625   PetscFunctionReturn(0);
4626 }
4627 
4628 PetscErrorCode MatSolverTypeDestroy(void)
4629 {
4630   MatSolverTypeHolder         next = MatSolverTypeHolders,prev;
4631   MatSolverTypeForSpecifcType inext,iprev;
4632 
4633   PetscFunctionBegin;
4634   while (next) {
4635     PetscCall(PetscFree(next->name));
4636     inext = next->handlers;
4637     while (inext) {
4638       PetscCall(PetscFree(inext->mtype));
4639       iprev = inext;
4640       inext = inext->next;
4641       PetscCall(PetscFree(iprev));
4642     }
4643     prev = next;
4644     next = next->next;
4645     PetscCall(PetscFree(prev));
4646   }
4647   MatSolverTypeHolders = NULL;
4648   PetscFunctionReturn(0);
4649 }
4650 
4651 /*@C
4652    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in MatLUFactorSymbolic(), MatCholeskyFactorSymbolic()
4653 
4654    Logically Collective on Mat
4655 
4656    Input Parameters:
4657 .  mat - the matrix
4658 
4659    Output Parameters:
4660 .  flg - PETSC_TRUE if uses the ordering
4661 
4662    Notes:
4663       Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4664       packages do not, thus we want to skip generating the ordering when it is not needed or used.
4665 
4666    Level: developer
4667 
4668 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4669 @*/
4670 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4671 {
4672   PetscFunctionBegin;
4673   *flg = mat->canuseordering;
4674   PetscFunctionReturn(0);
4675 }
4676 
4677 /*@C
4678    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4679 
4680    Logically Collective on Mat
4681 
4682    Input Parameters:
4683 .  mat - the matrix
4684 
4685    Output Parameters:
4686 .  otype - the preferred type
4687 
4688    Level: developer
4689 
4690 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4691 @*/
4692 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4693 {
4694   PetscFunctionBegin;
4695   *otype = mat->preferredordering[ftype];
4696   PetscCheck(*otype,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatFactor did not have a preferred ordering");
4697   PetscFunctionReturn(0);
4698 }
4699 
4700 /*@C
4701    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4702 
4703    Collective on Mat
4704 
4705    Input Parameters:
4706 +  mat - the matrix
4707 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4708 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4709 
4710    Output Parameters:
4711 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4712 
4713    Notes:
4714       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4715      such as pastix, superlu, mumps etc.
4716 
4717       PETSc must have been ./configure to use the external solver, using the option --download-package
4718 
4719       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4720       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4721       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4722 
4723    Developer Notes:
4724       This should actually be called MatCreateFactor() since it creates a new factor object
4725 
4726    Level: intermediate
4727 
4728 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`
4729 @*/
4730 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type,MatFactorType ftype,Mat *f)
4731 {
4732   PetscBool      foundtype,foundmtype;
4733   PetscErrorCode (*conv)(Mat,MatFactorType,Mat*);
4734 
4735   PetscFunctionBegin;
4736   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4737   PetscValidType(mat,1);
4738 
4739   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4740   MatCheckPreallocated(mat,1);
4741 
4742   PetscCall(MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,&foundtype,&foundmtype,&conv));
4743   if (!foundtype) {
4744     if (type) {
4745       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);
4746     } else {
4747       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);
4748     }
4749   }
4750   PetscCheck(foundmtype,PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"MatSolverType %s does not support matrix type %s",type,((PetscObject)mat)->type_name);
4751   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);
4752 
4753   PetscCall((*conv)(mat,ftype,f));
4754   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f,mat->factorprefix));
4755   PetscFunctionReturn(0);
4756 }
4757 
4758 /*@C
4759    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4760 
4761    Not Collective
4762 
4763    Input Parameters:
4764 +  mat - the matrix
4765 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4766 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4767 
4768    Output Parameter:
4769 .    flg - PETSC_TRUE if the factorization is available
4770 
4771    Notes:
4772       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4773      such as pastix, superlu, mumps etc.
4774 
4775       PETSc must have been ./configure to use the external solver, using the option --download-package
4776 
4777    Developer Notes:
4778       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4779 
4780    Level: intermediate
4781 
4782 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`
4783 @*/
4784 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type,MatFactorType ftype,PetscBool  *flg)
4785 {
4786   PetscErrorCode (*gconv)(Mat,MatFactorType,Mat*);
4787 
4788   PetscFunctionBegin;
4789   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4790   PetscValidType(mat,1);
4791   PetscValidBoolPointer(flg,4);
4792 
4793   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4794   MatCheckPreallocated(mat,1);
4795 
4796   PetscCall(MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,NULL,NULL,&gconv));
4797   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4798   PetscFunctionReturn(0);
4799 }
4800 
4801 /*@
4802    MatDuplicate - Duplicates a matrix including the non-zero structure.
4803 
4804    Collective on Mat
4805 
4806    Input Parameters:
4807 +  mat - the matrix
4808 -  op - One of MAT_DO_NOT_COPY_VALUES, MAT_COPY_VALUES, or MAT_SHARE_NONZERO_PATTERN.
4809         See the manual page for MatDuplicateOption for an explanation of these options.
4810 
4811    Output Parameter:
4812 .  M - pointer to place new matrix
4813 
4814    Level: intermediate
4815 
4816    Notes:
4817     You cannot change the nonzero pattern for the parent or child matrix if you use MAT_SHARE_NONZERO_PATTERN.
4818     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.
4819     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.
4820 
4821 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4822 @*/
4823 PetscErrorCode MatDuplicate(Mat mat,MatDuplicateOption op,Mat *M)
4824 {
4825   Mat            B;
4826   VecType        vtype;
4827   PetscInt       i;
4828   PetscObject    dm;
4829   void           (*viewf)(void);
4830 
4831   PetscFunctionBegin;
4832   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4833   PetscValidType(mat,1);
4834   PetscValidPointer(M,3);
4835   PetscCheck(op != MAT_COPY_VALUES || mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MAT_COPY_VALUES not allowed for unassembled matrix");
4836   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4837   MatCheckPreallocated(mat,1);
4838 
4839   *M = NULL;
4840   PetscCheck(mat->ops->duplicate,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not written for matrix type %s",((PetscObject)mat)->type_name);
4841   PetscCall(PetscLogEventBegin(MAT_Convert,mat,0,0,0));
4842   PetscCall((*mat->ops->duplicate)(mat,op,M));
4843   PetscCall(PetscLogEventEnd(MAT_Convert,mat,0,0,0));
4844   B    = *M;
4845 
4846   PetscCall(MatGetOperation(mat,MATOP_VIEW,&viewf));
4847   if (viewf) {
4848     PetscCall(MatSetOperation(B,MATOP_VIEW,viewf));
4849   }
4850   PetscCall(MatGetVecType(mat,&vtype));
4851   PetscCall(MatSetVecType(B,vtype));
4852 
4853   B->stencil.dim = mat->stencil.dim;
4854   B->stencil.noc = mat->stencil.noc;
4855   for (i=0; i<=mat->stencil.dim; i++) {
4856     B->stencil.dims[i]   = mat->stencil.dims[i];
4857     B->stencil.starts[i] = mat->stencil.starts[i];
4858   }
4859 
4860   B->nooffproczerorows = mat->nooffproczerorows;
4861   B->nooffprocentries  = mat->nooffprocentries;
4862 
4863   PetscCall(PetscObjectQuery((PetscObject) mat, "__PETSc_dm", &dm));
4864   if (dm) {
4865     PetscCall(PetscObjectCompose((PetscObject) B, "__PETSc_dm", dm));
4866   }
4867   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4868   PetscFunctionReturn(0);
4869 }
4870 
4871 /*@
4872    MatGetDiagonal - Gets the diagonal of a matrix.
4873 
4874    Logically Collective on Mat
4875 
4876    Input Parameters:
4877 +  mat - the matrix
4878 -  v - the vector for storing the diagonal
4879 
4880    Output Parameter:
4881 .  v - the diagonal of the matrix
4882 
4883    Level: intermediate
4884 
4885    Note:
4886    Currently only correct in parallel for square matrices.
4887 
4888 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4889 @*/
4890 PetscErrorCode MatGetDiagonal(Mat mat,Vec v)
4891 {
4892   PetscFunctionBegin;
4893   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4894   PetscValidType(mat,1);
4895   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4896   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4897   PetscCheck(mat->ops->getdiagonal,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4898   MatCheckPreallocated(mat,1);
4899 
4900   PetscCall((*mat->ops->getdiagonal)(mat,v));
4901   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4902   PetscFunctionReturn(0);
4903 }
4904 
4905 /*@C
4906    MatGetRowMin - Gets the minimum value (of the real part) of each
4907         row of the matrix
4908 
4909    Logically Collective on Mat
4910 
4911    Input Parameter:
4912 .  mat - the matrix
4913 
4914    Output Parameters:
4915 +  v - the vector for storing the maximums
4916 -  idx - the indices of the column found for each row (optional)
4917 
4918    Level: intermediate
4919 
4920    Notes:
4921     The result of this call are the same as if one converted the matrix to dense format
4922       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4923 
4924     This code is only implemented for a couple of matrix formats.
4925 
4926 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`,
4927           `MatGetRowMax()`
4928 @*/
4929 PetscErrorCode MatGetRowMin(Mat mat,Vec v,PetscInt idx[])
4930 {
4931   PetscFunctionBegin;
4932   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4933   PetscValidType(mat,1);
4934   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4935   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4936 
4937   if (!mat->cmap->N) {
4938     PetscCall(VecSet(v,PETSC_MAX_REAL));
4939     if (idx) {
4940       PetscInt i,m = mat->rmap->n;
4941       for (i=0; i<m; i++) idx[i] = -1;
4942     }
4943   } else {
4944     PetscCheck(mat->ops->getrowmin,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4945     MatCheckPreallocated(mat,1);
4946   }
4947   PetscCall((*mat->ops->getrowmin)(mat,v,idx));
4948   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4949   PetscFunctionReturn(0);
4950 }
4951 
4952 /*@C
4953    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4954         row of the matrix
4955 
4956    Logically Collective on Mat
4957 
4958    Input Parameter:
4959 .  mat - the matrix
4960 
4961    Output Parameters:
4962 +  v - the vector for storing the minimums
4963 -  idx - the indices of the column found for each row (or NULL if not needed)
4964 
4965    Level: intermediate
4966 
4967    Notes:
4968     if a row is completely empty or has only 0.0 values then the idx[] value for that
4969     row is 0 (the first column).
4970 
4971     This code is only implemented for a couple of matrix formats.
4972 
4973 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4974 @*/
4975 PetscErrorCode MatGetRowMinAbs(Mat mat,Vec v,PetscInt idx[])
4976 {
4977   PetscFunctionBegin;
4978   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4979   PetscValidType(mat,1);
4980   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4981   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4982   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4983 
4984   if (!mat->cmap->N) {
4985     PetscCall(VecSet(v,0.0));
4986     if (idx) {
4987       PetscInt i,m = mat->rmap->n;
4988       for (i=0; i<m; i++) idx[i] = -1;
4989     }
4990   } else {
4991     PetscCheck(mat->ops->getrowminabs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4992     MatCheckPreallocated(mat,1);
4993     if (idx) PetscCall(PetscArrayzero(idx,mat->rmap->n));
4994     PetscCall((*mat->ops->getrowminabs)(mat,v,idx));
4995   }
4996   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4997   PetscFunctionReturn(0);
4998 }
4999 
5000 /*@C
5001    MatGetRowMax - Gets the maximum value (of the real part) of each
5002         row of the matrix
5003 
5004    Logically Collective on Mat
5005 
5006    Input Parameter:
5007 .  mat - the matrix
5008 
5009    Output Parameters:
5010 +  v - the vector for storing the maximums
5011 -  idx - the indices of the column found for each row (optional)
5012 
5013    Level: intermediate
5014 
5015    Notes:
5016     The result of this call are the same as if one converted the matrix to dense format
5017       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5018 
5019     This code is only implemented for a couple of matrix formats.
5020 
5021 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5022 @*/
5023 PetscErrorCode MatGetRowMax(Mat mat,Vec v,PetscInt idx[])
5024 {
5025   PetscFunctionBegin;
5026   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5027   PetscValidType(mat,1);
5028   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5029   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5030 
5031   if (!mat->cmap->N) {
5032     PetscCall(VecSet(v,PETSC_MIN_REAL));
5033     if (idx) {
5034       PetscInt i,m = mat->rmap->n;
5035       for (i=0; i<m; i++) idx[i] = -1;
5036     }
5037   } else {
5038     PetscCheck(mat->ops->getrowmax,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5039     MatCheckPreallocated(mat,1);
5040     PetscCall((*mat->ops->getrowmax)(mat,v,idx));
5041   }
5042   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5043   PetscFunctionReturn(0);
5044 }
5045 
5046 /*@C
5047    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5048         row of the matrix
5049 
5050    Logically Collective on Mat
5051 
5052    Input Parameter:
5053 .  mat - the matrix
5054 
5055    Output Parameters:
5056 +  v - the vector for storing the maximums
5057 -  idx - the indices of the column found for each row (or NULL if not needed)
5058 
5059    Level: intermediate
5060 
5061    Notes:
5062     if a row is completely empty or has only 0.0 values then the idx[] value for that
5063     row is 0 (the first column).
5064 
5065     This code is only implemented for a couple of matrix formats.
5066 
5067 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`
5068 @*/
5069 PetscErrorCode MatGetRowMaxAbs(Mat mat,Vec v,PetscInt idx[])
5070 {
5071   PetscFunctionBegin;
5072   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5073   PetscValidType(mat,1);
5074   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5075   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5076 
5077   if (!mat->cmap->N) {
5078     PetscCall(VecSet(v,0.0));
5079     if (idx) {
5080       PetscInt i,m = mat->rmap->n;
5081       for (i=0; i<m; i++) idx[i] = -1;
5082     }
5083   } else {
5084     PetscCheck(mat->ops->getrowmaxabs,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5085     MatCheckPreallocated(mat,1);
5086     if (idx) PetscCall(PetscArrayzero(idx,mat->rmap->n));
5087     PetscCall((*mat->ops->getrowmaxabs)(mat,v,idx));
5088   }
5089   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5090   PetscFunctionReturn(0);
5091 }
5092 
5093 /*@
5094    MatGetRowSum - Gets the sum of each row of the matrix
5095 
5096    Logically or Neighborhood Collective on Mat
5097 
5098    Input Parameters:
5099 .  mat - the matrix
5100 
5101    Output Parameter:
5102 .  v - the vector for storing the sum of rows
5103 
5104    Level: intermediate
5105 
5106    Notes:
5107     This code is slow since it is not currently specialized for different formats
5108 
5109 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`
5110 @*/
5111 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5112 {
5113   Vec            ones;
5114 
5115   PetscFunctionBegin;
5116   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5117   PetscValidType(mat,1);
5118   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5119   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5120   MatCheckPreallocated(mat,1);
5121   PetscCall(MatCreateVecs(mat,&ones,NULL));
5122   PetscCall(VecSet(ones,1.));
5123   PetscCall(MatMult(mat,ones,v));
5124   PetscCall(VecDestroy(&ones));
5125   PetscFunctionReturn(0);
5126 }
5127 
5128 /*@
5129    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5130 
5131    Collective on Mat
5132 
5133    Input Parameters:
5134 +  mat - the matrix to transpose
5135 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5136 
5137    Output Parameter:
5138 .  B - the transpose
5139 
5140    Notes:
5141      If you use MAT_INPLACE_MATRIX then you must pass in &mat for B
5142 
5143      MAT_REUSE_MATRIX causes the B matrix from a previous call to this function with MAT_INITIAL_MATRIX to be used
5144 
5145      Consider using MatCreateTranspose() instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5146 
5147    Level: intermediate
5148 
5149 .seealso: `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5150 @*/
5151 PetscErrorCode MatTranspose(Mat mat,MatReuse reuse,Mat *B)
5152 {
5153   PetscFunctionBegin;
5154   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5155   PetscValidType(mat,1);
5156   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5157   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5158   PetscCheck(mat->ops->transpose,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5159   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires last matrix to match first");
5160   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Perhaps you mean MAT_INPLACE_MATRIX");
5161   MatCheckPreallocated(mat,1);
5162 
5163   PetscCall(PetscLogEventBegin(MAT_Transpose,mat,0,0,0));
5164   PetscCall((*mat->ops->transpose)(mat,reuse,B));
5165   PetscCall(PetscLogEventEnd(MAT_Transpose,mat,0,0,0));
5166   if (B) PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5167   PetscFunctionReturn(0);
5168 }
5169 
5170 /*@
5171    MatIsTranspose - Test whether a matrix is another one's transpose,
5172         or its own, in which case it tests symmetry.
5173 
5174    Collective on Mat
5175 
5176    Input Parameters:
5177 +  A - the matrix to test
5178 -  B - the matrix to test against, this can equal the first parameter
5179 
5180    Output Parameters:
5181 .  flg - the result
5182 
5183    Notes:
5184    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5185    has a running time of the order of the number of nonzeros; the parallel
5186    test involves parallel copies of the block-offdiagonal parts of the matrix.
5187 
5188    Level: intermediate
5189 
5190 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5191 @*/
5192 PetscErrorCode MatIsTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5193 {
5194   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5195 
5196   PetscFunctionBegin;
5197   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5198   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5199   PetscValidBoolPointer(flg,4);
5200   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsTranspose_C",&f));
5201   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsTranspose_C",&g));
5202   *flg = PETSC_FALSE;
5203   if (f && g) {
5204     PetscCheck(f == g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for symmetry test");
5205     PetscCall((*f)(A,B,tol,flg));
5206   } else {
5207     MatType mattype;
5208 
5209     PetscCall(MatGetType(f ? B : A,&mattype));
5210     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for transpose",mattype);
5211   }
5212   PetscFunctionReturn(0);
5213 }
5214 
5215 /*@
5216    MatHermitianTranspose - Computes an in-place or out-of-place transpose of a matrix in complex conjugate.
5217 
5218    Collective on Mat
5219 
5220    Input Parameters:
5221 +  mat - the matrix to transpose and complex conjugate
5222 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5223 
5224    Output Parameter:
5225 .  B - the Hermitian
5226 
5227    Level: intermediate
5228 
5229 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5230 @*/
5231 PetscErrorCode MatHermitianTranspose(Mat mat,MatReuse reuse,Mat *B)
5232 {
5233   PetscFunctionBegin;
5234   PetscCall(MatTranspose(mat,reuse,B));
5235 #if defined(PETSC_USE_COMPLEX)
5236   PetscCall(MatConjugate(*B));
5237 #endif
5238   PetscFunctionReturn(0);
5239 }
5240 
5241 /*@
5242    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5243 
5244    Collective on Mat
5245 
5246    Input Parameters:
5247 +  A - the matrix to test
5248 -  B - the matrix to test against, this can equal the first parameter
5249 
5250    Output Parameters:
5251 .  flg - the result
5252 
5253    Notes:
5254    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5255    has a running time of the order of the number of nonzeros; the parallel
5256    test involves parallel copies of the block-offdiagonal parts of the matrix.
5257 
5258    Level: intermediate
5259 
5260 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5261 @*/
5262 PetscErrorCode MatIsHermitianTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5263 {
5264   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5265 
5266   PetscFunctionBegin;
5267   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5268   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5269   PetscValidBoolPointer(flg,4);
5270   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsHermitianTranspose_C",&f));
5271   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsHermitianTranspose_C",&g));
5272   if (f && g) {
5273     PetscCheck(f != g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for Hermitian test");
5274     PetscCall((*f)(A,B,tol,flg));
5275   }
5276   PetscFunctionReturn(0);
5277 }
5278 
5279 /*@
5280    MatPermute - Creates a new matrix with rows and columns permuted from the
5281    original.
5282 
5283    Collective on Mat
5284 
5285    Input Parameters:
5286 +  mat - the matrix to permute
5287 .  row - row permutation, each processor supplies only the permutation for its rows
5288 -  col - column permutation, each processor supplies only the permutation for its columns
5289 
5290    Output Parameters:
5291 .  B - the permuted matrix
5292 
5293    Level: advanced
5294 
5295    Note:
5296    The index sets map from row/col of permuted matrix to row/col of original matrix.
5297    The index sets should be on the same communicator as Mat and have the same local sizes.
5298 
5299    Developer Note:
5300      If you want to implement MatPermute for a matrix type, and your approach doesn't
5301      exploit the fact that row and col are permutations, consider implementing the
5302      more general MatCreateSubMatrix() instead.
5303 
5304 .seealso: `MatGetOrdering()`, `ISAllGather()`
5305 
5306 @*/
5307 PetscErrorCode MatPermute(Mat mat,IS row,IS col,Mat *B)
5308 {
5309   PetscFunctionBegin;
5310   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5311   PetscValidType(mat,1);
5312   PetscValidHeaderSpecific(row,IS_CLASSID,2);
5313   PetscValidHeaderSpecific(col,IS_CLASSID,3);
5314   PetscValidPointer(B,4);
5315   PetscCheckSameComm(mat,1,row,2);
5316   if (row != col) PetscCheckSameComm(row,2,col,3);
5317   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5318   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5319   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatPermute not available for Mat type %s",((PetscObject)mat)->type_name);
5320   MatCheckPreallocated(mat,1);
5321 
5322   if (mat->ops->permute) {
5323     PetscCall((*mat->ops->permute)(mat,row,col,B));
5324     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5325   } else {
5326     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5327   }
5328   PetscFunctionReturn(0);
5329 }
5330 
5331 /*@
5332    MatEqual - Compares two matrices.
5333 
5334    Collective on Mat
5335 
5336    Input Parameters:
5337 +  A - the first matrix
5338 -  B - the second matrix
5339 
5340    Output Parameter:
5341 .  flg - PETSC_TRUE if the matrices are equal; PETSC_FALSE otherwise.
5342 
5343    Level: intermediate
5344 
5345 @*/
5346 PetscErrorCode MatEqual(Mat A,Mat B,PetscBool *flg)
5347 {
5348   PetscFunctionBegin;
5349   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5350   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5351   PetscValidType(A,1);
5352   PetscValidType(B,2);
5353   PetscValidBoolPointer(flg,3);
5354   PetscCheckSameComm(A,1,B,2);
5355   MatCheckPreallocated(A,1);
5356   MatCheckPreallocated(B,2);
5357   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5358   PetscCheck(B->assembled,PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5359   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N,A->cmap->N,B->cmap->N);
5360   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5361     PetscCall((*A->ops->equal)(A,B,flg));
5362   } else {
5363     PetscCall(MatMultEqual(A,B,10,flg));
5364   }
5365   PetscFunctionReturn(0);
5366 }
5367 
5368 /*@
5369    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5370    matrices that are stored as vectors.  Either of the two scaling
5371    matrices can be NULL.
5372 
5373    Collective on Mat
5374 
5375    Input Parameters:
5376 +  mat - the matrix to be scaled
5377 .  l - the left scaling vector (or NULL)
5378 -  r - the right scaling vector (or NULL)
5379 
5380    Notes:
5381    MatDiagonalScale() computes A = LAR, where
5382    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5383    The L scales the rows of the matrix, the R scales the columns of the matrix.
5384 
5385    Level: intermediate
5386 
5387 .seealso: `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5388 @*/
5389 PetscErrorCode MatDiagonalScale(Mat mat,Vec l,Vec r)
5390 {
5391   PetscFunctionBegin;
5392   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5393   PetscValidType(mat,1);
5394   if (l) {PetscValidHeaderSpecific(l,VEC_CLASSID,2);PetscCheckSameComm(mat,1,l,2);}
5395   if (r) {PetscValidHeaderSpecific(r,VEC_CLASSID,3);PetscCheckSameComm(mat,1,r,3);}
5396   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5397   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5398   MatCheckPreallocated(mat,1);
5399   if (!l && !r) PetscFunctionReturn(0);
5400 
5401   PetscCheck(mat->ops->diagonalscale,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5402   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5403   PetscCall((*mat->ops->diagonalscale)(mat,l,r));
5404   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5405   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5406   if (l != r && mat->symmetric) mat->symmetric = PETSC_FALSE;
5407   PetscFunctionReturn(0);
5408 }
5409 
5410 /*@
5411     MatScale - Scales all elements of a matrix by a given number.
5412 
5413     Logically Collective on Mat
5414 
5415     Input Parameters:
5416 +   mat - the matrix to be scaled
5417 -   a  - the scaling value
5418 
5419     Output Parameter:
5420 .   mat - the scaled matrix
5421 
5422     Level: intermediate
5423 
5424 .seealso: `MatDiagonalScale()`
5425 @*/
5426 PetscErrorCode MatScale(Mat mat,PetscScalar a)
5427 {
5428   PetscFunctionBegin;
5429   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5430   PetscValidType(mat,1);
5431   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5432   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5433   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5434   PetscValidLogicalCollectiveScalar(mat,a,2);
5435   MatCheckPreallocated(mat,1);
5436 
5437   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5438   if (a != (PetscScalar)1.0) {
5439     PetscCall((*mat->ops->scale)(mat,a));
5440     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5441   }
5442   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5443   PetscFunctionReturn(0);
5444 }
5445 
5446 /*@
5447    MatNorm - Calculates various norms of a matrix.
5448 
5449    Collective on Mat
5450 
5451    Input Parameters:
5452 +  mat - the matrix
5453 -  type - the type of norm, NORM_1, NORM_FROBENIUS, NORM_INFINITY
5454 
5455    Output Parameter:
5456 .  nrm - the resulting norm
5457 
5458    Level: intermediate
5459 
5460 @*/
5461 PetscErrorCode MatNorm(Mat mat,NormType type,PetscReal *nrm)
5462 {
5463   PetscFunctionBegin;
5464   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5465   PetscValidType(mat,1);
5466   PetscValidRealPointer(nrm,3);
5467 
5468   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5469   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5470   PetscCheck(mat->ops->norm,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5471   MatCheckPreallocated(mat,1);
5472 
5473   PetscCall((*mat->ops->norm)(mat,type,nrm));
5474   PetscFunctionReturn(0);
5475 }
5476 
5477 /*
5478      This variable is used to prevent counting of MatAssemblyBegin() that
5479    are called from within a MatAssemblyEnd().
5480 */
5481 static PetscInt MatAssemblyEnd_InUse = 0;
5482 /*@
5483    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5484    be called after completing all calls to MatSetValues().
5485 
5486    Collective on Mat
5487 
5488    Input Parameters:
5489 +  mat - the matrix
5490 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5491 
5492    Notes:
5493    MatSetValues() generally caches the values.  The matrix is ready to
5494    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5495    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5496    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5497    using the matrix.
5498 
5499    ALL processes that share a matrix MUST call MatAssemblyBegin() and MatAssemblyEnd() the SAME NUMBER of times, and each time with the
5500    same flag of MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY for all processes. Thus you CANNOT locally change from ADD_VALUES to INSERT_VALUES, that is
5501    a global collective operation requring all processes that share the matrix.
5502 
5503    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5504    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5505    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5506 
5507    Level: beginner
5508 
5509 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5510 @*/
5511 PetscErrorCode MatAssemblyBegin(Mat mat,MatAssemblyType type)
5512 {
5513   PetscFunctionBegin;
5514   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5515   PetscValidType(mat,1);
5516   MatCheckPreallocated(mat,1);
5517   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5518   if (mat->assembled) {
5519     mat->was_assembled = PETSC_TRUE;
5520     mat->assembled     = PETSC_FALSE;
5521   }
5522 
5523   if (!MatAssemblyEnd_InUse) {
5524     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin,mat,0,0,0));
5525     if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5526     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin,mat,0,0,0));
5527   } else if (mat->ops->assemblybegin) {
5528     PetscCall((*mat->ops->assemblybegin)(mat,type));
5529   }
5530   PetscFunctionReturn(0);
5531 }
5532 
5533 /*@
5534    MatAssembled - Indicates if a matrix has been assembled and is ready for
5535      use; for example, in matrix-vector product.
5536 
5537    Not Collective
5538 
5539    Input Parameter:
5540 .  mat - the matrix
5541 
5542    Output Parameter:
5543 .  assembled - PETSC_TRUE or PETSC_FALSE
5544 
5545    Level: advanced
5546 
5547 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5548 @*/
5549 PetscErrorCode MatAssembled(Mat mat,PetscBool *assembled)
5550 {
5551   PetscFunctionBegin;
5552   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5553   PetscValidBoolPointer(assembled,2);
5554   *assembled = mat->assembled;
5555   PetscFunctionReturn(0);
5556 }
5557 
5558 /*@
5559    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5560    be called after MatAssemblyBegin().
5561 
5562    Collective on Mat
5563 
5564    Input Parameters:
5565 +  mat - the matrix
5566 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5567 
5568    Options Database Keys:
5569 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatEndAssembly()
5570 .  -mat_view ::ascii_info_detail - Prints more detailed info
5571 .  -mat_view - Prints matrix in ASCII format
5572 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5573 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
5574 .  -display <name> - Sets display name (default is host)
5575 .  -draw_pause <sec> - Sets number of seconds to pause after display
5576 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab)
5577 .  -viewer_socket_machine <machine> - Machine to use for socket
5578 .  -viewer_socket_port <port> - Port number to use for socket
5579 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5580 
5581    Notes:
5582    MatSetValues() generally caches the values.  The matrix is ready to
5583    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5584    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5585    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5586    using the matrix.
5587 
5588    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5589    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5590    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5591 
5592    Level: beginner
5593 
5594 .seealso: `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5595 @*/
5596 PetscErrorCode MatAssemblyEnd(Mat mat,MatAssemblyType type)
5597 {
5598   static PetscInt inassm = 0;
5599   PetscBool       flg    = PETSC_FALSE;
5600 
5601   PetscFunctionBegin;
5602   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5603   PetscValidType(mat,1);
5604 
5605   inassm++;
5606   MatAssemblyEnd_InUse++;
5607   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5608     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd,mat,0,0,0));
5609     if (mat->ops->assemblyend) {
5610       PetscCall((*mat->ops->assemblyend)(mat,type));
5611     }
5612     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd,mat,0,0,0));
5613   } else if (mat->ops->assemblyend) {
5614     PetscCall((*mat->ops->assemblyend)(mat,type));
5615   }
5616 
5617   /* Flush assembly is not a true assembly */
5618   if (type != MAT_FLUSH_ASSEMBLY) {
5619     mat->num_ass++;
5620     mat->assembled        = PETSC_TRUE;
5621     mat->ass_nonzerostate = mat->nonzerostate;
5622   }
5623 
5624   mat->insertmode = NOT_SET_VALUES;
5625   MatAssemblyEnd_InUse--;
5626   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5627   if (!mat->symmetric_eternal) {
5628     mat->symmetric_set              = PETSC_FALSE;
5629     mat->hermitian_set              = PETSC_FALSE;
5630     mat->structurally_symmetric_set = PETSC_FALSE;
5631   }
5632   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5633     PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5634 
5635     if (mat->checksymmetryonassembly) {
5636       PetscCall(MatIsSymmetric(mat,mat->checksymmetrytol,&flg));
5637       if (flg) {
5638         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5639       } else {
5640         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is not symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5641       }
5642     }
5643     if (mat->nullsp && mat->checknullspaceonassembly) {
5644       PetscCall(MatNullSpaceTest(mat->nullsp,mat,NULL));
5645     }
5646   }
5647   inassm--;
5648   PetscFunctionReturn(0);
5649 }
5650 
5651 /*@
5652    MatSetOption - Sets a parameter option for a matrix. Some options
5653    may be specific to certain storage formats.  Some options
5654    determine how values will be inserted (or added). Sorted,
5655    row-oriented input will generally assemble the fastest. The default
5656    is row-oriented.
5657 
5658    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5659 
5660    Input Parameters:
5661 +  mat - the matrix
5662 .  option - the option, one of those listed below (and possibly others),
5663 -  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5664 
5665   Options Describing Matrix Structure:
5666 +    MAT_SPD - symmetric positive definite
5667 .    MAT_SYMMETRIC - symmetric in terms of both structure and value
5668 .    MAT_HERMITIAN - transpose is the complex conjugation
5669 .    MAT_STRUCTURALLY_SYMMETRIC - symmetric nonzero structure
5670 -    MAT_SYMMETRY_ETERNAL - if you would like the symmetry/Hermitian flag
5671                             you set to be kept with all future use of the matrix
5672                             including after MatAssemblyBegin/End() which could
5673                             potentially change the symmetry structure, i.e. you
5674                             KNOW the matrix will ALWAYS have the property you set.
5675                             Note that setting this flag alone implies nothing about whether the matrix is symmetric/Hermitian;
5676                             the relevant flags must be set independently.
5677 
5678    Options For Use with MatSetValues():
5679    Insert a logically dense subblock, which can be
5680 .    MAT_ROW_ORIENTED - row-oriented (default)
5681 
5682    Note these options reflect the data you pass in with MatSetValues(); it has
5683    nothing to do with how the data is stored internally in the matrix
5684    data structure.
5685 
5686    When (re)assembling a matrix, we can restrict the input for
5687    efficiency/debugging purposes.  These options include
5688 +    MAT_NEW_NONZERO_LOCATIONS - additional insertions will be allowed if they generate a new nonzero (slow)
5689 .    MAT_FORCE_DIAGONAL_ENTRIES - forces diagonal entries to be allocated
5690 .    MAT_IGNORE_OFF_PROC_ENTRIES - drops off-processor entries
5691 .    MAT_NEW_NONZERO_LOCATION_ERR - generates an error for new matrix entry
5692 .    MAT_USE_HASH_TABLE - uses a hash table to speed up matrix assembly
5693 .    MAT_NO_OFF_PROC_ENTRIES - you know each process will only set values for its own rows, will generate an error if
5694         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5695         performance for very large process counts.
5696 -    MAT_SUBSET_OFF_PROC_ENTRIES - you know that the first assembly after setting this flag will set a superset
5697         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5698         functions, instead sending only neighbor messages.
5699 
5700    Notes:
5701    Except for MAT_UNUSED_NONZERO_LOCATION_ERR and  MAT_ROW_ORIENTED all processes that share the matrix must pass the same value in flg!
5702 
5703    Some options are relevant only for particular matrix types and
5704    are thus ignored by others.  Other options are not supported by
5705    certain matrix types and will generate an error message if set.
5706 
5707    If using a Fortran 77 module to compute a matrix, one may need to
5708    use the column-oriented option (or convert to the row-oriented
5709    format).
5710 
5711    MAT_NEW_NONZERO_LOCATIONS set to PETSC_FALSE indicates that any add or insertion
5712    that would generate a new entry in the nonzero structure is instead
5713    ignored.  Thus, if memory has not alredy been allocated for this particular
5714    data, then the insertion is ignored. For dense matrices, in which
5715    the entire array is allocated, no entries are ever ignored.
5716    Set after the first MatAssemblyEnd(). If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5717 
5718    MAT_NEW_NONZERO_LOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5719    that would generate a new entry in the nonzero structure instead produces
5720    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
5721 
5722    MAT_NEW_NONZERO_ALLOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5723    that would generate a new entry that has not been preallocated will
5724    instead produce an error. (Currently supported for AIJ and BAIJ formats
5725    only.) This is a useful flag when debugging matrix memory preallocation.
5726    If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5727 
5728    MAT_IGNORE_OFF_PROC_ENTRIES set to PETSC_TRUE indicates entries destined for
5729    other processors should be dropped, rather than stashed.
5730    This is useful if you know that the "owning" processor is also
5731    always generating the correct matrix entries, so that PETSc need
5732    not transfer duplicate entries generated on another processor.
5733 
5734    MAT_USE_HASH_TABLE indicates that a hash table be used to improve the
5735    searches during matrix assembly. When this flag is set, the hash table
5736    is created during the first Matrix Assembly. This hash table is
5737    used the next time through, during MatSetVaules()/MatSetVaulesBlocked()
5738    to improve the searching of indices. MAT_NEW_NONZERO_LOCATIONS flag
5739    should be used with MAT_USE_HASH_TABLE flag. This option is currently
5740    supported by MATMPIBAIJ format only.
5741 
5742    MAT_KEEP_NONZERO_PATTERN indicates when MatZeroRows() is called the zeroed entries
5743    are kept in the nonzero structure
5744 
5745    MAT_IGNORE_ZERO_ENTRIES - for AIJ/IS matrices this will stop zero values from creating
5746    a zero location in the matrix
5747 
5748    MAT_USE_INODES - indicates using inode version of the code - works with AIJ matrix types
5749 
5750    MAT_NO_OFF_PROC_ZERO_ROWS - you know each process will only zero its own rows. This avoids all reductions in the
5751         zero row routines and thus improves performance for very large process counts.
5752 
5753    MAT_IGNORE_LOWER_TRIANGULAR - For SBAIJ matrices will ignore any insertions you make in the lower triangular
5754         part of the matrix (since they should match the upper triangular part).
5755 
5756    MAT_SORTED_FULL - each process provides exactly its local rows; all column indices for a given row are passed in a
5757                      single call to MatSetValues(), preallocation is perfect, row oriented, INSERT_VALUES is used. Common
5758                      with finite difference schemes with non-periodic boundary conditions.
5759 
5760    Level: intermediate
5761 
5762 .seealso: `MatOption`, `Mat`
5763 
5764 @*/
5765 PetscErrorCode MatSetOption(Mat mat,MatOption op,PetscBool flg)
5766 {
5767   PetscFunctionBegin;
5768   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5769   if (op > 0) {
5770     PetscValidLogicalCollectiveEnum(mat,op,2);
5771     PetscValidLogicalCollectiveBool(mat,flg,3);
5772   }
5773 
5774   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);
5775 
5776   switch (op) {
5777   case MAT_FORCE_DIAGONAL_ENTRIES:
5778     mat->force_diagonals = flg;
5779     PetscFunctionReturn(0);
5780   case MAT_NO_OFF_PROC_ENTRIES:
5781     mat->nooffprocentries = flg;
5782     PetscFunctionReturn(0);
5783   case MAT_SUBSET_OFF_PROC_ENTRIES:
5784     mat->assembly_subset = flg;
5785     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5786 #if !defined(PETSC_HAVE_MPIUNI)
5787       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5788 #endif
5789       mat->stash.first_assembly_done = PETSC_FALSE;
5790     }
5791     PetscFunctionReturn(0);
5792   case MAT_NO_OFF_PROC_ZERO_ROWS:
5793     mat->nooffproczerorows = flg;
5794     PetscFunctionReturn(0);
5795   case MAT_SPD:
5796     mat->spd_set = PETSC_TRUE;
5797     mat->spd     = flg;
5798     if (flg) {
5799       mat->symmetric                  = PETSC_TRUE;
5800       mat->structurally_symmetric     = PETSC_TRUE;
5801       mat->symmetric_set              = PETSC_TRUE;
5802       mat->structurally_symmetric_set = PETSC_TRUE;
5803     }
5804     break;
5805   case MAT_SYMMETRIC:
5806     mat->symmetric = flg;
5807     if (flg) mat->structurally_symmetric = PETSC_TRUE;
5808     mat->symmetric_set              = PETSC_TRUE;
5809     mat->structurally_symmetric_set = flg;
5810 #if !defined(PETSC_USE_COMPLEX)
5811     mat->hermitian     = flg;
5812     mat->hermitian_set = PETSC_TRUE;
5813 #endif
5814     break;
5815   case MAT_HERMITIAN:
5816     mat->hermitian = flg;
5817     if (flg) mat->structurally_symmetric = PETSC_TRUE;
5818     mat->hermitian_set              = PETSC_TRUE;
5819     mat->structurally_symmetric_set = flg;
5820 #if !defined(PETSC_USE_COMPLEX)
5821     mat->symmetric     = flg;
5822     mat->symmetric_set = PETSC_TRUE;
5823 #endif
5824     break;
5825   case MAT_STRUCTURALLY_SYMMETRIC:
5826     mat->structurally_symmetric     = flg;
5827     mat->structurally_symmetric_set = PETSC_TRUE;
5828     break;
5829   case MAT_SYMMETRY_ETERNAL:
5830     mat->symmetric_eternal = flg;
5831     break;
5832   case MAT_STRUCTURE_ONLY:
5833     mat->structure_only = flg;
5834     break;
5835   case MAT_SORTED_FULL:
5836     mat->sortedfull = flg;
5837     break;
5838   default:
5839     break;
5840   }
5841   if (mat->ops->setoption) {
5842     PetscCall((*mat->ops->setoption)(mat,op,flg));
5843   }
5844   PetscFunctionReturn(0);
5845 }
5846 
5847 /*@
5848    MatGetOption - Gets a parameter option that has been set for a matrix.
5849 
5850    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5851 
5852    Input Parameters:
5853 +  mat - the matrix
5854 -  option - the option, this only responds to certain options, check the code for which ones
5855 
5856    Output Parameter:
5857 .  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5858 
5859     Notes:
5860     Can only be called after MatSetSizes() and MatSetType() have been set.
5861 
5862    Level: intermediate
5863 
5864 .seealso: `MatOption`, `MatSetOption()`
5865 
5866 @*/
5867 PetscErrorCode MatGetOption(Mat mat,MatOption op,PetscBool *flg)
5868 {
5869   PetscFunctionBegin;
5870   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5871   PetscValidType(mat,1);
5872 
5873   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);
5874   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()");
5875 
5876   switch (op) {
5877   case MAT_NO_OFF_PROC_ENTRIES:
5878     *flg = mat->nooffprocentries;
5879     break;
5880   case MAT_NO_OFF_PROC_ZERO_ROWS:
5881     *flg = mat->nooffproczerorows;
5882     break;
5883   case MAT_SYMMETRIC:
5884     *flg = mat->symmetric;
5885     break;
5886   case MAT_HERMITIAN:
5887     *flg = mat->hermitian;
5888     break;
5889   case MAT_STRUCTURALLY_SYMMETRIC:
5890     *flg = mat->structurally_symmetric;
5891     break;
5892   case MAT_SYMMETRY_ETERNAL:
5893     *flg = mat->symmetric_eternal;
5894     break;
5895   case MAT_SPD:
5896     *flg = mat->spd;
5897     break;
5898   default:
5899     break;
5900   }
5901   PetscFunctionReturn(0);
5902 }
5903 
5904 /*@
5905    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5906    this routine retains the old nonzero structure.
5907 
5908    Logically Collective on Mat
5909 
5910    Input Parameters:
5911 .  mat - the matrix
5912 
5913    Level: intermediate
5914 
5915    Notes:
5916     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.
5917    See the Performance chapter of the users manual for information on preallocating matrices.
5918 
5919 .seealso: `MatZeroRows()`
5920 @*/
5921 PetscErrorCode MatZeroEntries(Mat mat)
5922 {
5923   PetscFunctionBegin;
5924   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5925   PetscValidType(mat,1);
5926   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5927   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");
5928   PetscCheck(mat->ops->zeroentries,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5929   MatCheckPreallocated(mat,1);
5930 
5931   PetscCall(PetscLogEventBegin(MAT_ZeroEntries,mat,0,0,0));
5932   PetscCall((*mat->ops->zeroentries)(mat));
5933   PetscCall(PetscLogEventEnd(MAT_ZeroEntries,mat,0,0,0));
5934   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5935   PetscFunctionReturn(0);
5936 }
5937 
5938 /*@
5939    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5940    of a set of rows and columns of a matrix.
5941 
5942    Collective on Mat
5943 
5944    Input Parameters:
5945 +  mat - the matrix
5946 .  numRows - the number of rows to remove
5947 .  rows - the global row indices
5948 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5949 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5950 -  b - optional vector of right hand side, that will be adjusted by provided solution
5951 
5952    Notes:
5953    This does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5954 
5955    The user can set a value in the diagonal entry (or for the AIJ and
5956    row formats can optionally remove the main diagonal entry from the
5957    nonzero structure as well, by passing 0.0 as the final argument).
5958 
5959    For the parallel case, all processes that share the matrix (i.e.,
5960    those in the communicator used for matrix creation) MUST call this
5961    routine, regardless of whether any rows being zeroed are owned by
5962    them.
5963 
5964    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5965    list only rows local to itself).
5966 
5967    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
5968 
5969    Level: intermediate
5970 
5971 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5972           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5973 @*/
5974 PetscErrorCode MatZeroRowsColumns(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
5975 {
5976   PetscFunctionBegin;
5977   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5978   PetscValidType(mat,1);
5979   if (numRows) PetscValidIntPointer(rows,3);
5980   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5981   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5982   PetscCheck(mat->ops->zerorowscolumns,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5983   MatCheckPreallocated(mat,1);
5984 
5985   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,rows,diag,x,b));
5986   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5987   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5988   PetscFunctionReturn(0);
5989 }
5990 
5991 /*@
5992    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5993    of a set of rows and columns of a matrix.
5994 
5995    Collective on Mat
5996 
5997    Input Parameters:
5998 +  mat - the matrix
5999 .  is - the rows to zero
6000 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6001 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6002 -  b - optional vector of right hand side, that will be adjusted by provided solution
6003 
6004    Notes:
6005    This does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6006 
6007    The user can set a value in the diagonal entry (or for the AIJ and
6008    row formats can optionally remove the main diagonal entry from the
6009    nonzero structure as well, by passing 0.0 as the final argument).
6010 
6011    For the parallel case, all processes that share the matrix (i.e.,
6012    those in the communicator used for matrix creation) MUST call this
6013    routine, regardless of whether any rows being zeroed are owned by
6014    them.
6015 
6016    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6017    list only rows local to itself).
6018 
6019    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
6020 
6021    Level: intermediate
6022 
6023 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6024           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6025 @*/
6026 PetscErrorCode MatZeroRowsColumnsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6027 {
6028   PetscInt       numRows;
6029   const PetscInt *rows;
6030 
6031   PetscFunctionBegin;
6032   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6033   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6034   PetscValidType(mat,1);
6035   PetscValidType(is,2);
6036   PetscCall(ISGetLocalSize(is,&numRows));
6037   PetscCall(ISGetIndices(is,&rows));
6038   PetscCall(MatZeroRowsColumns(mat,numRows,rows,diag,x,b));
6039   PetscCall(ISRestoreIndices(is,&rows));
6040   PetscFunctionReturn(0);
6041 }
6042 
6043 /*@
6044    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6045    of a set of rows of a matrix.
6046 
6047    Collective on Mat
6048 
6049    Input Parameters:
6050 +  mat - the matrix
6051 .  numRows - the number of rows to remove
6052 .  rows - the global row indices
6053 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6054 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6055 -  b - optional vector of right hand side, that will be adjusted by provided solution
6056 
6057    Notes:
6058    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6059    but does not release memory.  For the dense and block diagonal
6060    formats this does not alter the nonzero structure.
6061 
6062    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6063    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6064    merely zeroed.
6065 
6066    The user can set a value in the diagonal entry (or for the AIJ and
6067    row formats can optionally remove the main diagonal entry from the
6068    nonzero structure as well, by passing 0.0 as the final argument).
6069 
6070    For the parallel case, all processes that share the matrix (i.e.,
6071    those in the communicator used for matrix creation) MUST call this
6072    routine, regardless of whether any rows being zeroed are owned by
6073    them.
6074 
6075    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6076    list only rows local to itself).
6077 
6078    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6079    owns that are to be zeroed. This saves a global synchronization in the implementation.
6080 
6081    Level: intermediate
6082 
6083 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6084           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6085 @*/
6086 PetscErrorCode MatZeroRows(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6087 {
6088   PetscFunctionBegin;
6089   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6090   PetscValidType(mat,1);
6091   if (numRows) PetscValidIntPointer(rows,3);
6092   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6093   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6094   PetscCheck(mat->ops->zerorows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6095   MatCheckPreallocated(mat,1);
6096 
6097   PetscCall((*mat->ops->zerorows)(mat,numRows,rows,diag,x,b));
6098   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
6099   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6100   PetscFunctionReturn(0);
6101 }
6102 
6103 /*@
6104    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6105    of a set of rows of a matrix.
6106 
6107    Collective on Mat
6108 
6109    Input Parameters:
6110 +  mat - the matrix
6111 .  is - index set of rows to remove (if NULL then no row is removed)
6112 .  diag - value put in all diagonals of eliminated rows
6113 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6114 -  b - optional vector of right hand side, that will be adjusted by provided solution
6115 
6116    Notes:
6117    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6118    but does not release memory.  For the dense and block diagonal
6119    formats this does not alter the nonzero structure.
6120 
6121    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6122    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6123    merely zeroed.
6124 
6125    The user can set a value in the diagonal entry (or for the AIJ and
6126    row formats can optionally remove the main diagonal entry from the
6127    nonzero structure as well, by passing 0.0 as the final argument).
6128 
6129    For the parallel case, all processes that share the matrix (i.e.,
6130    those in the communicator used for matrix creation) MUST call this
6131    routine, regardless of whether any rows being zeroed are owned by
6132    them.
6133 
6134    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6135    list only rows local to itself).
6136 
6137    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6138    owns that are to be zeroed. This saves a global synchronization in the implementation.
6139 
6140    Level: intermediate
6141 
6142 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6143           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6144 @*/
6145 PetscErrorCode MatZeroRowsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6146 {
6147   PetscInt       numRows = 0;
6148   const PetscInt *rows = NULL;
6149 
6150   PetscFunctionBegin;
6151   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6152   PetscValidType(mat,1);
6153   if (is) {
6154     PetscValidHeaderSpecific(is,IS_CLASSID,2);
6155     PetscCall(ISGetLocalSize(is,&numRows));
6156     PetscCall(ISGetIndices(is,&rows));
6157   }
6158   PetscCall(MatZeroRows(mat,numRows,rows,diag,x,b));
6159   if (is) {
6160     PetscCall(ISRestoreIndices(is,&rows));
6161   }
6162   PetscFunctionReturn(0);
6163 }
6164 
6165 /*@
6166    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6167    of a set of rows of a matrix. These rows must be local to the process.
6168 
6169    Collective on Mat
6170 
6171    Input Parameters:
6172 +  mat - the matrix
6173 .  numRows - the number of rows to remove
6174 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6175 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6176 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6177 -  b - optional vector of right hand side, that will be adjusted by provided solution
6178 
6179    Notes:
6180    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6181    but does not release memory.  For the dense and block diagonal
6182    formats this does not alter the nonzero structure.
6183 
6184    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6185    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6186    merely zeroed.
6187 
6188    The user can set a value in the diagonal entry (or for the AIJ and
6189    row formats can optionally remove the main diagonal entry from the
6190    nonzero structure as well, by passing 0.0 as the final argument).
6191 
6192    For the parallel case, all processes that share the matrix (i.e.,
6193    those in the communicator used for matrix creation) MUST call this
6194    routine, regardless of whether any rows being zeroed are owned by
6195    them.
6196 
6197    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6198    list only rows local to itself).
6199 
6200    The grid coordinates are across the entire grid, not just the local portion
6201 
6202    In Fortran idxm and idxn should be declared as
6203 $     MatStencil idxm(4,m)
6204    and the values inserted using
6205 $    idxm(MatStencil_i,1) = i
6206 $    idxm(MatStencil_j,1) = j
6207 $    idxm(MatStencil_k,1) = k
6208 $    idxm(MatStencil_c,1) = c
6209    etc
6210 
6211    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6212    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6213    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6214    DM_BOUNDARY_PERIODIC boundary type.
6215 
6216    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
6217    a single value per point) you can skip filling those indices.
6218 
6219    Level: intermediate
6220 
6221 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6222           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6223 @*/
6224 PetscErrorCode MatZeroRowsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6225 {
6226   PetscInt       dim     = mat->stencil.dim;
6227   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6228   PetscInt       *dims   = mat->stencil.dims+1;
6229   PetscInt       *starts = mat->stencil.starts;
6230   PetscInt       *dxm    = (PetscInt*) rows;
6231   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6232 
6233   PetscFunctionBegin;
6234   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6235   PetscValidType(mat,1);
6236   if (numRows) PetscValidPointer(rows,3);
6237 
6238   PetscCall(PetscMalloc1(numRows, &jdxm));
6239   for (i = 0; i < numRows; ++i) {
6240     /* Skip unused dimensions (they are ordered k, j, i, c) */
6241     for (j = 0; j < 3-sdim; ++j) dxm++;
6242     /* Local index in X dir */
6243     tmp = *dxm++ - starts[0];
6244     /* Loop over remaining dimensions */
6245     for (j = 0; j < dim-1; ++j) {
6246       /* If nonlocal, set index to be negative */
6247       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6248       /* Update local index */
6249       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6250     }
6251     /* Skip component slot if necessary */
6252     if (mat->stencil.noc) dxm++;
6253     /* Local row number */
6254     if (tmp >= 0) {
6255       jdxm[numNewRows++] = tmp;
6256     }
6257   }
6258   PetscCall(MatZeroRowsLocal(mat,numNewRows,jdxm,diag,x,b));
6259   PetscCall(PetscFree(jdxm));
6260   PetscFunctionReturn(0);
6261 }
6262 
6263 /*@
6264    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6265    of a set of rows and columns of a matrix.
6266 
6267    Collective on Mat
6268 
6269    Input Parameters:
6270 +  mat - the matrix
6271 .  numRows - the number of rows/columns to remove
6272 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6273 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6274 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6275 -  b - optional vector of right hand side, that will be adjusted by provided solution
6276 
6277    Notes:
6278    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6279    but does not release memory.  For the dense and block diagonal
6280    formats this does not alter the nonzero structure.
6281 
6282    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6283    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6284    merely zeroed.
6285 
6286    The user can set a value in the diagonal entry (or for the AIJ and
6287    row formats can optionally remove the main diagonal entry from the
6288    nonzero structure as well, by passing 0.0 as the final argument).
6289 
6290    For the parallel case, all processes that share the matrix (i.e.,
6291    those in the communicator used for matrix creation) MUST call this
6292    routine, regardless of whether any rows being zeroed are owned by
6293    them.
6294 
6295    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6296    list only rows local to itself, but the row/column numbers are given in local numbering).
6297 
6298    The grid coordinates are across the entire grid, not just the local portion
6299 
6300    In Fortran idxm and idxn should be declared as
6301 $     MatStencil idxm(4,m)
6302    and the values inserted using
6303 $    idxm(MatStencil_i,1) = i
6304 $    idxm(MatStencil_j,1) = j
6305 $    idxm(MatStencil_k,1) = k
6306 $    idxm(MatStencil_c,1) = c
6307    etc
6308 
6309    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6310    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6311    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6312    DM_BOUNDARY_PERIODIC boundary type.
6313 
6314    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
6315    a single value per point) you can skip filling those indices.
6316 
6317    Level: intermediate
6318 
6319 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6320           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6321 @*/
6322 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6323 {
6324   PetscInt       dim     = mat->stencil.dim;
6325   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6326   PetscInt       *dims   = mat->stencil.dims+1;
6327   PetscInt       *starts = mat->stencil.starts;
6328   PetscInt       *dxm    = (PetscInt*) rows;
6329   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6330 
6331   PetscFunctionBegin;
6332   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6333   PetscValidType(mat,1);
6334   if (numRows) PetscValidPointer(rows,3);
6335 
6336   PetscCall(PetscMalloc1(numRows, &jdxm));
6337   for (i = 0; i < numRows; ++i) {
6338     /* Skip unused dimensions (they are ordered k, j, i, c) */
6339     for (j = 0; j < 3-sdim; ++j) dxm++;
6340     /* Local index in X dir */
6341     tmp = *dxm++ - starts[0];
6342     /* Loop over remaining dimensions */
6343     for (j = 0; j < dim-1; ++j) {
6344       /* If nonlocal, set index to be negative */
6345       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6346       /* Update local index */
6347       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6348     }
6349     /* Skip component slot if necessary */
6350     if (mat->stencil.noc) dxm++;
6351     /* Local row number */
6352     if (tmp >= 0) {
6353       jdxm[numNewRows++] = tmp;
6354     }
6355   }
6356   PetscCall(MatZeroRowsColumnsLocal(mat,numNewRows,jdxm,diag,x,b));
6357   PetscCall(PetscFree(jdxm));
6358   PetscFunctionReturn(0);
6359 }
6360 
6361 /*@C
6362    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6363    of a set of rows of a matrix; using local numbering of rows.
6364 
6365    Collective on Mat
6366 
6367    Input Parameters:
6368 +  mat - the matrix
6369 .  numRows - the number of rows to remove
6370 .  rows - the local row indices
6371 .  diag - value put in all diagonals of eliminated rows
6372 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6373 -  b - optional vector of right hand side, that will be adjusted by provided solution
6374 
6375    Notes:
6376    Before calling MatZeroRowsLocal(), the user must first set the
6377    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6378 
6379    For the AIJ matrix formats this removes the old nonzero structure,
6380    but does not release memory.  For the dense and block diagonal
6381    formats this does not alter the nonzero structure.
6382 
6383    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6384    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6385    merely zeroed.
6386 
6387    The user can set a value in the diagonal entry (or for the AIJ and
6388    row formats can optionally remove the main diagonal entry from the
6389    nonzero structure as well, by passing 0.0 as the final argument).
6390 
6391    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6392    owns that are to be zeroed. This saves a global synchronization in the implementation.
6393 
6394    Level: intermediate
6395 
6396 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6397           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6398 @*/
6399 PetscErrorCode MatZeroRowsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6400 {
6401   PetscFunctionBegin;
6402   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6403   PetscValidType(mat,1);
6404   if (numRows) PetscValidIntPointer(rows,3);
6405   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6406   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6407   MatCheckPreallocated(mat,1);
6408 
6409   if (mat->ops->zerorowslocal) {
6410     PetscCall((*mat->ops->zerorowslocal)(mat,numRows,rows,diag,x,b));
6411   } else {
6412     IS             is, newis;
6413     const PetscInt *newRows;
6414 
6415     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6416     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6417     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping,is,&newis));
6418     PetscCall(ISGetIndices(newis,&newRows));
6419     PetscCall((*mat->ops->zerorows)(mat,numRows,newRows,diag,x,b));
6420     PetscCall(ISRestoreIndices(newis,&newRows));
6421     PetscCall(ISDestroy(&newis));
6422     PetscCall(ISDestroy(&is));
6423   }
6424   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6425   PetscFunctionReturn(0);
6426 }
6427 
6428 /*@
6429    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6430    of a set of rows of a matrix; using local numbering of rows.
6431 
6432    Collective on Mat
6433 
6434    Input Parameters:
6435 +  mat - the matrix
6436 .  is - index set of rows to remove
6437 .  diag - value put in all diagonals of eliminated rows
6438 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6439 -  b - optional vector of right hand side, that will be adjusted by provided solution
6440 
6441    Notes:
6442    Before calling MatZeroRowsLocalIS(), the user must first set the
6443    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6444 
6445    For the AIJ matrix formats this removes the old nonzero structure,
6446    but does not release memory.  For the dense and block diagonal
6447    formats this does not alter the nonzero structure.
6448 
6449    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6450    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6451    merely zeroed.
6452 
6453    The user can set a value in the diagonal entry (or for the AIJ and
6454    row formats can optionally remove the main diagonal entry from the
6455    nonzero structure as well, by passing 0.0 as the final argument).
6456 
6457    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6458    owns that are to be zeroed. This saves a global synchronization in the implementation.
6459 
6460    Level: intermediate
6461 
6462 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6463           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6464 @*/
6465 PetscErrorCode MatZeroRowsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6466 {
6467   PetscInt       numRows;
6468   const PetscInt *rows;
6469 
6470   PetscFunctionBegin;
6471   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6472   PetscValidType(mat,1);
6473   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6474   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6475   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6476   MatCheckPreallocated(mat,1);
6477 
6478   PetscCall(ISGetLocalSize(is,&numRows));
6479   PetscCall(ISGetIndices(is,&rows));
6480   PetscCall(MatZeroRowsLocal(mat,numRows,rows,diag,x,b));
6481   PetscCall(ISRestoreIndices(is,&rows));
6482   PetscFunctionReturn(0);
6483 }
6484 
6485 /*@
6486    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6487    of a set of rows and columns of a matrix; using local numbering of rows.
6488 
6489    Collective on Mat
6490 
6491    Input Parameters:
6492 +  mat - the matrix
6493 .  numRows - the number of rows to remove
6494 .  rows - the global row indices
6495 .  diag - value put in all diagonals of eliminated rows
6496 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6497 -  b - optional vector of right hand side, that will be adjusted by provided solution
6498 
6499    Notes:
6500    Before calling MatZeroRowsColumnsLocal(), the user must first set the
6501    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6502 
6503    The user can set a value in the diagonal entry (or for the AIJ and
6504    row formats can optionally remove the main diagonal entry from the
6505    nonzero structure as well, by passing 0.0 as the final argument).
6506 
6507    Level: intermediate
6508 
6509 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6510           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6511 @*/
6512 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6513 {
6514   IS             is, newis;
6515   const PetscInt *newRows;
6516 
6517   PetscFunctionBegin;
6518   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6519   PetscValidType(mat,1);
6520   if (numRows) PetscValidIntPointer(rows,3);
6521   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6522   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6523   MatCheckPreallocated(mat,1);
6524 
6525   PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6526   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6527   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping,is,&newis));
6528   PetscCall(ISGetIndices(newis,&newRows));
6529   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,newRows,diag,x,b));
6530   PetscCall(ISRestoreIndices(newis,&newRows));
6531   PetscCall(ISDestroy(&newis));
6532   PetscCall(ISDestroy(&is));
6533   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6534   PetscFunctionReturn(0);
6535 }
6536 
6537 /*@
6538    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6539    of a set of rows and columns of a matrix; using local numbering of rows.
6540 
6541    Collective on Mat
6542 
6543    Input Parameters:
6544 +  mat - the matrix
6545 .  is - index set of rows to remove
6546 .  diag - value put in all diagonals of eliminated rows
6547 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6548 -  b - optional vector of right hand side, that will be adjusted by provided solution
6549 
6550    Notes:
6551    Before calling MatZeroRowsColumnsLocalIS(), the user must first set the
6552    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6553 
6554    The user can set a value in the diagonal entry (or for the AIJ and
6555    row formats can optionally remove the main diagonal entry from the
6556    nonzero structure as well, by passing 0.0 as the final argument).
6557 
6558    Level: intermediate
6559 
6560 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6561           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6562 @*/
6563 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6564 {
6565   PetscInt       numRows;
6566   const PetscInt *rows;
6567 
6568   PetscFunctionBegin;
6569   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6570   PetscValidType(mat,1);
6571   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6572   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6573   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6574   MatCheckPreallocated(mat,1);
6575 
6576   PetscCall(ISGetLocalSize(is,&numRows));
6577   PetscCall(ISGetIndices(is,&rows));
6578   PetscCall(MatZeroRowsColumnsLocal(mat,numRows,rows,diag,x,b));
6579   PetscCall(ISRestoreIndices(is,&rows));
6580   PetscFunctionReturn(0);
6581 }
6582 
6583 /*@C
6584    MatGetSize - Returns the numbers of rows and columns in a matrix.
6585 
6586    Not Collective
6587 
6588    Input Parameter:
6589 .  mat - the matrix
6590 
6591    Output Parameters:
6592 +  m - the number of global rows
6593 -  n - the number of global columns
6594 
6595    Note: both output parameters can be NULL on input.
6596 
6597    Level: beginner
6598 
6599 .seealso: `MatGetLocalSize()`
6600 @*/
6601 PetscErrorCode MatGetSize(Mat mat,PetscInt *m,PetscInt *n)
6602 {
6603   PetscFunctionBegin;
6604   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6605   if (m) *m = mat->rmap->N;
6606   if (n) *n = mat->cmap->N;
6607   PetscFunctionReturn(0);
6608 }
6609 
6610 /*@C
6611    MatGetLocalSize - Returns the number of local rows and local columns
6612    of a matrix, that is the local size of the left and right vectors as returned by MatCreateVecs().
6613 
6614    Not Collective
6615 
6616    Input Parameter:
6617 .  mat - the matrix
6618 
6619    Output Parameters:
6620 +  m - the number of local rows
6621 -  n - the number of local columns
6622 
6623    Note: both output parameters can be NULL on input.
6624 
6625    Level: beginner
6626 
6627 .seealso: `MatGetSize()`
6628 @*/
6629 PetscErrorCode MatGetLocalSize(Mat mat,PetscInt *m,PetscInt *n)
6630 {
6631   PetscFunctionBegin;
6632   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6633   if (m) PetscValidIntPointer(m,2);
6634   if (n) PetscValidIntPointer(n,3);
6635   if (m) *m = mat->rmap->n;
6636   if (n) *n = mat->cmap->n;
6637   PetscFunctionReturn(0);
6638 }
6639 
6640 /*@C
6641    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies by that owned by
6642    this processor. (The columns of the "diagonal block")
6643 
6644    Not Collective, unless matrix has not been allocated, then collective on Mat
6645 
6646    Input Parameter:
6647 .  mat - the matrix
6648 
6649    Output Parameters:
6650 +  m - the global index of the first local column
6651 -  n - one more than the global index of the last local column
6652 
6653    Notes:
6654     both output parameters can be NULL on input.
6655 
6656    Level: developer
6657 
6658 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`
6659 
6660 @*/
6661 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat,PetscInt *m,PetscInt *n)
6662 {
6663   PetscFunctionBegin;
6664   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6665   PetscValidType(mat,1);
6666   if (m) PetscValidIntPointer(m,2);
6667   if (n) PetscValidIntPointer(n,3);
6668   MatCheckPreallocated(mat,1);
6669   if (m) *m = mat->cmap->rstart;
6670   if (n) *n = mat->cmap->rend;
6671   PetscFunctionReturn(0);
6672 }
6673 
6674 /*@C
6675    MatGetOwnershipRange - Returns the range of matrix rows owned by
6676    this processor, assuming that the matrix is laid out with the first
6677    n1 rows on the first processor, the next n2 rows on the second, etc.
6678    For certain parallel layouts this range may not be well defined.
6679 
6680    Not Collective
6681 
6682    Input Parameter:
6683 .  mat - the matrix
6684 
6685    Output Parameters:
6686 +  m - the global index of the first local row
6687 -  n - one more than the global index of the last local row
6688 
6689    Note: Both output parameters can be NULL on input.
6690 $  This function requires that the matrix be preallocated. If you have not preallocated, consider using
6691 $    PetscSplitOwnership(MPI_Comm comm, PetscInt *n, PetscInt *N)
6692 $  and then MPI_Scan() to calculate prefix sums of the local sizes.
6693 
6694    Level: beginner
6695 
6696 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`
6697 
6698 @*/
6699 PetscErrorCode MatGetOwnershipRange(Mat mat,PetscInt *m,PetscInt *n)
6700 {
6701   PetscFunctionBegin;
6702   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6703   PetscValidType(mat,1);
6704   if (m) PetscValidIntPointer(m,2);
6705   if (n) PetscValidIntPointer(n,3);
6706   MatCheckPreallocated(mat,1);
6707   if (m) *m = mat->rmap->rstart;
6708   if (n) *n = mat->rmap->rend;
6709   PetscFunctionReturn(0);
6710 }
6711 
6712 /*@C
6713    MatGetOwnershipRanges - Returns the range of matrix rows owned by
6714    each process
6715 
6716    Not Collective, unless matrix has not been allocated, then collective on Mat
6717 
6718    Input Parameters:
6719 .  mat - the matrix
6720 
6721    Output Parameters:
6722 .  ranges - start of each processors portion plus one more than the total length at the end
6723 
6724    Level: beginner
6725 
6726 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`
6727 
6728 @*/
6729 PetscErrorCode MatGetOwnershipRanges(Mat mat,const PetscInt **ranges)
6730 {
6731   PetscFunctionBegin;
6732   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6733   PetscValidType(mat,1);
6734   MatCheckPreallocated(mat,1);
6735   PetscCall(PetscLayoutGetRanges(mat->rmap,ranges));
6736   PetscFunctionReturn(0);
6737 }
6738 
6739 /*@C
6740    MatGetOwnershipRangesColumn - Returns the range of matrix columns associated with rows of a vector one multiplies by that owned by
6741    this processor. (The columns of the "diagonal blocks" for each process)
6742 
6743    Not Collective, unless matrix has not been allocated, then collective on Mat
6744 
6745    Input Parameters:
6746 .  mat - the matrix
6747 
6748    Output Parameters:
6749 .  ranges - start of each processors portion plus one more then the total length at the end
6750 
6751    Level: beginner
6752 
6753 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6754 
6755 @*/
6756 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat,const PetscInt **ranges)
6757 {
6758   PetscFunctionBegin;
6759   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6760   PetscValidType(mat,1);
6761   MatCheckPreallocated(mat,1);
6762   PetscCall(PetscLayoutGetRanges(mat->cmap,ranges));
6763   PetscFunctionReturn(0);
6764 }
6765 
6766 /*@C
6767    MatGetOwnershipIS - Get row and column ownership as index sets
6768 
6769    Not Collective
6770 
6771    Input Parameter:
6772 .  A - matrix
6773 
6774    Output Parameters:
6775 +  rows - rows in which this process owns elements
6776 -  cols - columns in which this process owns elements
6777 
6778    Level: intermediate
6779 
6780 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
6781 @*/
6782 PetscErrorCode MatGetOwnershipIS(Mat A,IS *rows,IS *cols)
6783 {
6784   PetscErrorCode (*f)(Mat,IS*,IS*);
6785 
6786   PetscFunctionBegin;
6787   MatCheckPreallocated(A,1);
6788   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatGetOwnershipIS_C",&f));
6789   if (f) {
6790     PetscCall((*f)(A,rows,cols));
6791   } else {   /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6792     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->rmap->n,A->rmap->rstart,1,rows));
6793     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->cmap->N,0,1,cols));
6794   }
6795   PetscFunctionReturn(0);
6796 }
6797 
6798 /*@C
6799    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix.
6800    Uses levels of fill only, not drop tolerance. Use MatLUFactorNumeric()
6801    to complete the factorization.
6802 
6803    Collective on Mat
6804 
6805    Input Parameters:
6806 +  mat - the matrix
6807 .  row - row permutation
6808 .  column - column permutation
6809 -  info - structure containing
6810 $      levels - number of levels of fill.
6811 $      expected fill - as ratio of original fill.
6812 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6813                 missing diagonal entries)
6814 
6815    Output Parameters:
6816 .  fact - new matrix that has been symbolically factored
6817 
6818    Notes:
6819     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
6820 
6821    Most users should employ the simplified KSP interface for linear solvers
6822    instead of working directly with matrix algebra routines such as this.
6823    See, e.g., KSPCreate().
6824 
6825    Level: developer
6826 
6827 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6828           `MatGetOrdering()`, `MatFactorInfo`
6829 
6830     Note: this uses the definition of level of fill as in Y. Saad, 2003
6831 
6832     Developer Note: fortran interface is not autogenerated as the f90
6833     interface definition cannot be generated correctly [due to MatFactorInfo]
6834 
6835    References:
6836 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6837 @*/
6838 PetscErrorCode MatILUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
6839 {
6840   PetscFunctionBegin;
6841   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6842   PetscValidType(mat,2);
6843   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
6844   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
6845   PetscValidPointer(info,5);
6846   PetscValidPointer(fact,1);
6847   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels of fill negative %" PetscInt_FMT,(PetscInt)info->levels);
6848   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6849   if (!fact->ops->ilufactorsymbolic) {
6850     MatSolverType stype;
6851     PetscCall(MatFactorGetSolverType(fact,&stype));
6852     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ILU using solver type %s",((PetscObject)mat)->type_name,stype);
6853   }
6854   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6855   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6856   MatCheckPreallocated(mat,2);
6857 
6858   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic,mat,row,col,0));
6859   PetscCall((fact->ops->ilufactorsymbolic)(fact,mat,row,col,info));
6860   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic,mat,row,col,0));
6861   PetscFunctionReturn(0);
6862 }
6863 
6864 /*@C
6865    MatICCFactorSymbolic - Performs symbolic incomplete
6866    Cholesky factorization for a symmetric matrix.  Use
6867    MatCholeskyFactorNumeric() to complete the factorization.
6868 
6869    Collective on Mat
6870 
6871    Input Parameters:
6872 +  mat - the matrix
6873 .  perm - row and column permutation
6874 -  info - structure containing
6875 $      levels - number of levels of fill.
6876 $      expected fill - as ratio of original fill.
6877 
6878    Output Parameter:
6879 .  fact - the factored matrix
6880 
6881    Notes:
6882    Most users should employ the KSP interface for linear solvers
6883    instead of working directly with matrix algebra routines such as this.
6884    See, e.g., KSPCreate().
6885 
6886    Level: developer
6887 
6888 .seealso: `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6889 
6890     Note: this uses the definition of level of fill as in Y. Saad, 2003
6891 
6892     Developer Note: fortran interface is not autogenerated as the f90
6893     interface definition cannot be generated correctly [due to MatFactorInfo]
6894 
6895    References:
6896 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6897 @*/
6898 PetscErrorCode MatICCFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
6899 {
6900   PetscFunctionBegin;
6901   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6902   PetscValidType(mat,2);
6903   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
6904   PetscValidPointer(info,4);
6905   PetscValidPointer(fact,1);
6906   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6907   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels negative %" PetscInt_FMT,(PetscInt) info->levels);
6908   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6909   if (!(fact)->ops->iccfactorsymbolic) {
6910     MatSolverType stype;
6911     PetscCall(MatFactorGetSolverType(fact,&stype));
6912     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ICC using solver type %s",((PetscObject)mat)->type_name,stype);
6913   }
6914   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6915   MatCheckPreallocated(mat,2);
6916 
6917   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic,mat,perm,0,0));
6918   PetscCall((fact->ops->iccfactorsymbolic)(fact,mat,perm,info));
6919   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic,mat,perm,0,0));
6920   PetscFunctionReturn(0);
6921 }
6922 
6923 /*@C
6924    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6925    points to an array of valid matrices, they may be reused to store the new
6926    submatrices.
6927 
6928    Collective on Mat
6929 
6930    Input Parameters:
6931 +  mat - the matrix
6932 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6933 .  irow, icol - index sets of rows and columns to extract
6934 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6935 
6936    Output Parameter:
6937 .  submat - the array of submatrices
6938 
6939    Notes:
6940    MatCreateSubMatrices() can extract ONLY sequential submatrices
6941    (from both sequential and parallel matrices). Use MatCreateSubMatrix()
6942    to extract a parallel submatrix.
6943 
6944    Some matrix types place restrictions on the row and column
6945    indices, such as that they be sorted or that they be equal to each other.
6946 
6947    The index sets may not have duplicate entries.
6948 
6949    When extracting submatrices from a parallel matrix, each processor can
6950    form a different submatrix by setting the rows and columns of its
6951    individual index sets according to the local submatrix desired.
6952 
6953    When finished using the submatrices, the user should destroy
6954    them with MatDestroySubMatrices().
6955 
6956    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
6957    original matrix has not changed from that last call to MatCreateSubMatrices().
6958 
6959    This routine creates the matrices in submat; you should NOT create them before
6960    calling it. It also allocates the array of matrix pointers submat.
6961 
6962    For BAIJ matrices the index sets must respect the block structure, that is if they
6963    request one row/column in a block, they must request all rows/columns that are in
6964    that block. For example, if the block size is 2 you cannot request just row 0 and
6965    column 0.
6966 
6967    Fortran Note:
6968    The Fortran interface is slightly different from that given below; it
6969    requires one to pass in  as submat a Mat (integer) array of size at least n+1.
6970 
6971    Level: advanced
6972 
6973 .seealso: `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6974 @*/
6975 PetscErrorCode MatCreateSubMatrices(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
6976 {
6977   PetscInt       i;
6978   PetscBool      eq;
6979 
6980   PetscFunctionBegin;
6981   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6982   PetscValidType(mat,1);
6983   if (n) {
6984     PetscValidPointer(irow,3);
6985     for (i=0; i<n; i++) PetscValidHeaderSpecific(irow[i],IS_CLASSID,3);
6986     PetscValidPointer(icol,4);
6987     for (i=0; i<n; i++) PetscValidHeaderSpecific(icol[i],IS_CLASSID,4);
6988   }
6989   PetscValidPointer(submat,6);
6990   if (n && scall == MAT_REUSE_MATRIX) {
6991     PetscValidPointer(*submat,6);
6992     for (i=0; i<n; i++) PetscValidHeaderSpecific((*submat)[i],MAT_CLASSID,6);
6993   }
6994   PetscCheck(mat->ops->createsubmatrices,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6995   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6996   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6997   MatCheckPreallocated(mat,1);
6998   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
6999   PetscCall((*mat->ops->createsubmatrices)(mat,n,irow,icol,scall,submat));
7000   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
7001   for (i=0; i<n; i++) {
7002     (*submat)[i]->factortype = MAT_FACTOR_NONE;  /* in case in place factorization was previously done on submatrix */
7003     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
7004     if (eq) {
7005       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
7006     }
7007 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
7008     if (mat->boundtocpu && mat->bindingpropagates) {
7009       PetscCall(MatBindToCPU((*submat)[i],PETSC_TRUE));
7010       PetscCall(MatSetBindingPropagates((*submat)[i],PETSC_TRUE));
7011     }
7012 #endif
7013   }
7014   PetscFunctionReturn(0);
7015 }
7016 
7017 /*@C
7018    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of IS that may live on subcomms).
7019 
7020    Collective on Mat
7021 
7022    Input Parameters:
7023 +  mat - the matrix
7024 .  n   - the number of submatrixes to be extracted
7025 .  irow, icol - index sets of rows and columns to extract
7026 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
7027 
7028    Output Parameter:
7029 .  submat - the array of submatrices
7030 
7031    Level: advanced
7032 
7033 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7034 @*/
7035 PetscErrorCode MatCreateSubMatricesMPI(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
7036 {
7037   PetscInt       i;
7038   PetscBool      eq;
7039 
7040   PetscFunctionBegin;
7041   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7042   PetscValidType(mat,1);
7043   if (n) {
7044     PetscValidPointer(irow,3);
7045     PetscValidHeaderSpecific(*irow,IS_CLASSID,3);
7046     PetscValidPointer(icol,4);
7047     PetscValidHeaderSpecific(*icol,IS_CLASSID,4);
7048   }
7049   PetscValidPointer(submat,6);
7050   if (n && scall == MAT_REUSE_MATRIX) {
7051     PetscValidPointer(*submat,6);
7052     PetscValidHeaderSpecific(**submat,MAT_CLASSID,6);
7053   }
7054   PetscCheck(mat->ops->createsubmatricesmpi,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7055   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7056   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7057   MatCheckPreallocated(mat,1);
7058 
7059   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
7060   PetscCall((*mat->ops->createsubmatricesmpi)(mat,n,irow,icol,scall,submat));
7061   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
7062   for (i=0; i<n; i++) {
7063     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
7064     if (eq) {
7065       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
7066     }
7067   }
7068   PetscFunctionReturn(0);
7069 }
7070 
7071 /*@C
7072    MatDestroyMatrices - Destroys an array of matrices.
7073 
7074    Collective on Mat
7075 
7076    Input Parameters:
7077 +  n - the number of local matrices
7078 -  mat - the matrices (note that this is a pointer to the array of matrices)
7079 
7080    Level: advanced
7081 
7082     Notes:
7083     Frees not only the matrices, but also the array that contains the matrices
7084            In Fortran will not free the array.
7085 
7086 .seealso: `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7087 @*/
7088 PetscErrorCode MatDestroyMatrices(PetscInt n,Mat *mat[])
7089 {
7090   PetscInt       i;
7091 
7092   PetscFunctionBegin;
7093   if (!*mat) PetscFunctionReturn(0);
7094   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7095   PetscValidPointer(mat,2);
7096 
7097   for (i=0; i<n; i++) {
7098     PetscCall(MatDestroy(&(*mat)[i]));
7099   }
7100 
7101   /* memory is allocated even if n = 0 */
7102   PetscCall(PetscFree(*mat));
7103   PetscFunctionReturn(0);
7104 }
7105 
7106 /*@C
7107    MatDestroySubMatrices - Destroys a set of matrices obtained with MatCreateSubMatrices().
7108 
7109    Collective on Mat
7110 
7111    Input Parameters:
7112 +  n - the number of local matrices
7113 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7114                        sequence of MatCreateSubMatrices())
7115 
7116    Level: advanced
7117 
7118     Notes:
7119     Frees not only the matrices, but also the array that contains the matrices
7120            In Fortran will not free the array.
7121 
7122 .seealso: `MatCreateSubMatrices()`
7123 @*/
7124 PetscErrorCode MatDestroySubMatrices(PetscInt n,Mat *mat[])
7125 {
7126   Mat            mat0;
7127 
7128   PetscFunctionBegin;
7129   if (!*mat) PetscFunctionReturn(0);
7130   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7131   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7132   PetscValidPointer(mat,2);
7133 
7134   mat0 = (*mat)[0];
7135   if (mat0 && mat0->ops->destroysubmatrices) {
7136     PetscCall((mat0->ops->destroysubmatrices)(n,mat));
7137   } else {
7138     PetscCall(MatDestroyMatrices(n,mat));
7139   }
7140   PetscFunctionReturn(0);
7141 }
7142 
7143 /*@C
7144    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7145 
7146    Collective on Mat
7147 
7148    Input Parameters:
7149 .  mat - the matrix
7150 
7151    Output Parameter:
7152 .  matstruct - the sequential matrix with the nonzero structure of mat
7153 
7154   Level: intermediate
7155 
7156 .seealso: `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7157 @*/
7158 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat,Mat *matstruct)
7159 {
7160   PetscFunctionBegin;
7161   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7162   PetscValidPointer(matstruct,2);
7163 
7164   PetscValidType(mat,1);
7165   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7166   MatCheckPreallocated(mat,1);
7167 
7168   PetscCheck(mat->ops->getseqnonzerostructure,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)mat)->type_name);
7169   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7170   PetscCall((*mat->ops->getseqnonzerostructure)(mat,matstruct));
7171   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7172   PetscFunctionReturn(0);
7173 }
7174 
7175 /*@C
7176    MatDestroySeqNonzeroStructure - Destroys matrix obtained with MatGetSeqNonzeroStructure().
7177 
7178    Collective on Mat
7179 
7180    Input Parameters:
7181 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7182                        sequence of MatGetSequentialNonzeroStructure())
7183 
7184    Level: advanced
7185 
7186     Notes:
7187     Frees not only the matrices, but also the array that contains the matrices
7188 
7189 .seealso: `MatGetSeqNonzeroStructure()`
7190 @*/
7191 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7192 {
7193   PetscFunctionBegin;
7194   PetscValidPointer(mat,1);
7195   PetscCall(MatDestroy(mat));
7196   PetscFunctionReturn(0);
7197 }
7198 
7199 /*@
7200    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7201    replaces the index sets by larger ones that represent submatrices with
7202    additional overlap.
7203 
7204    Collective on Mat
7205 
7206    Input Parameters:
7207 +  mat - the matrix
7208 .  n   - the number of index sets
7209 .  is  - the array of index sets (these index sets will changed during the call)
7210 -  ov  - the additional overlap requested
7211 
7212    Options Database:
7213 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7214 
7215    Level: developer
7216 
7217    Developer Note:
7218    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.
7219 
7220 .seealso: `MatCreateSubMatrices()`
7221 @*/
7222 PetscErrorCode MatIncreaseOverlap(Mat mat,PetscInt n,IS is[],PetscInt ov)
7223 {
7224   PetscInt       i,bs,cbs;
7225 
7226   PetscFunctionBegin;
7227   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7228   PetscValidType(mat,1);
7229   PetscValidLogicalCollectiveInt(mat,n,2);
7230   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7231   if (n) {
7232     PetscValidPointer(is,3);
7233     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i],IS_CLASSID,3);
7234   }
7235   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7236   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7237   MatCheckPreallocated(mat,1);
7238 
7239   if (!ov || !n) PetscFunctionReturn(0);
7240   PetscCheck(mat->ops->increaseoverlap,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7241   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7242   PetscCall((*mat->ops->increaseoverlap)(mat,n,is,ov));
7243   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7244   PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
7245   if (bs == cbs) {
7246     for (i=0; i<n; i++) {
7247       PetscCall(ISSetBlockSize(is[i],bs));
7248     }
7249   }
7250   PetscFunctionReturn(0);
7251 }
7252 
7253 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat,IS*,PetscInt);
7254 
7255 /*@
7256    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7257    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7258    additional overlap.
7259 
7260    Collective on Mat
7261 
7262    Input Parameters:
7263 +  mat - the matrix
7264 .  n   - the number of index sets
7265 .  is  - the array of index sets (these index sets will changed during the call)
7266 -  ov  - the additional overlap requested
7267 
7268    Options Database:
7269 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7270 
7271    Level: developer
7272 
7273 .seealso: `MatCreateSubMatrices()`
7274 @*/
7275 PetscErrorCode MatIncreaseOverlapSplit(Mat mat,PetscInt n,IS is[],PetscInt ov)
7276 {
7277   PetscInt       i;
7278 
7279   PetscFunctionBegin;
7280   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7281   PetscValidType(mat,1);
7282   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7283   if (n) {
7284     PetscValidPointer(is,3);
7285     PetscValidHeaderSpecific(*is,IS_CLASSID,3);
7286   }
7287   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7288   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7289   MatCheckPreallocated(mat,1);
7290   if (!ov) PetscFunctionReturn(0);
7291   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7292   for (i=0; i<n; i++) {
7293     PetscCall(MatIncreaseOverlapSplit_Single(mat,&is[i],ov));
7294   }
7295   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7296   PetscFunctionReturn(0);
7297 }
7298 
7299 /*@
7300    MatGetBlockSize - Returns the matrix block size.
7301 
7302    Not Collective
7303 
7304    Input Parameter:
7305 .  mat - the matrix
7306 
7307    Output Parameter:
7308 .  bs - block size
7309 
7310    Notes:
7311     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7312 
7313    If the block size has not been set yet this routine returns 1.
7314 
7315    Level: intermediate
7316 
7317 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7318 @*/
7319 PetscErrorCode MatGetBlockSize(Mat mat,PetscInt *bs)
7320 {
7321   PetscFunctionBegin;
7322   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7323   PetscValidIntPointer(bs,2);
7324   *bs = PetscAbs(mat->rmap->bs);
7325   PetscFunctionReturn(0);
7326 }
7327 
7328 /*@
7329    MatGetBlockSizes - Returns the matrix block row and column sizes.
7330 
7331    Not Collective
7332 
7333    Input Parameter:
7334 .  mat - the matrix
7335 
7336    Output Parameters:
7337 +  rbs - row block size
7338 -  cbs - column block size
7339 
7340    Notes:
7341     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7342     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7343 
7344    If a block size has not been set yet this routine returns 1.
7345 
7346    Level: intermediate
7347 
7348 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7349 @*/
7350 PetscErrorCode MatGetBlockSizes(Mat mat,PetscInt *rbs, PetscInt *cbs)
7351 {
7352   PetscFunctionBegin;
7353   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7354   if (rbs) PetscValidIntPointer(rbs,2);
7355   if (cbs) PetscValidIntPointer(cbs,3);
7356   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7357   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7358   PetscFunctionReturn(0);
7359 }
7360 
7361 /*@
7362    MatSetBlockSize - Sets the matrix block size.
7363 
7364    Logically Collective on Mat
7365 
7366    Input Parameters:
7367 +  mat - the matrix
7368 -  bs - block size
7369 
7370    Notes:
7371     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7372     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7373 
7374     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block size
7375     is compatible with the matrix local sizes.
7376 
7377    Level: intermediate
7378 
7379 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7380 @*/
7381 PetscErrorCode MatSetBlockSize(Mat mat,PetscInt bs)
7382 {
7383   PetscFunctionBegin;
7384   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7385   PetscValidLogicalCollectiveInt(mat,bs,2);
7386   PetscCall(MatSetBlockSizes(mat,bs,bs));
7387   PetscFunctionReturn(0);
7388 }
7389 
7390 typedef struct {
7391   PetscInt         n;
7392   IS               *is;
7393   Mat              *mat;
7394   PetscObjectState nonzerostate;
7395   Mat              C;
7396 } EnvelopeData;
7397 
7398 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7399 {
7400   for (PetscInt i=0; i<edata->n; i++) {
7401     PetscCall(ISDestroy(&edata->is[i]));
7402   }
7403   PetscCall(PetscFree(edata->is));
7404   PetscCall(PetscFree(edata));
7405   return 0;
7406 }
7407 
7408 /*
7409    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7410          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7411 
7412    Collective on mat
7413 
7414    Input Parameter:
7415 .  mat - the matrix
7416 
7417    Notes:
7418      There can be zeros within the blocks
7419 
7420      The blocks can overlap between processes, including laying on more than two processes
7421 
7422 */
7423 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7424 {
7425   PetscInt                    n,*sizes,*starts,i = 0,env = 0, tbs = 0, lblocks = 0,rstart,II,ln = 0,cnt = 0,cstart,cend;
7426   PetscInt                    *diag,*odiag,sc;
7427   VecScatter                  scatter;
7428   PetscScalar                 *seqv;
7429   const PetscScalar           *parv;
7430   const PetscInt              *ia,*ja;
7431   PetscBool                   set,flag,done;
7432   Mat                         AA = mat,A;
7433   MPI_Comm                    comm;
7434   PetscMPIInt                 rank,size,tag;
7435   MPI_Status                  status;
7436   PetscContainer              container;
7437   EnvelopeData                *edata;
7438   Vec                         seq,par;
7439   IS                          isglobal;
7440 
7441   PetscFunctionBegin;
7442   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7443   PetscCall(MatIsSymmetricKnown(mat,&set,&flag));
7444   if (!set || !flag) {
7445     /* TOO: only needs nonzero structure of transpose */
7446     PetscCall(MatTranspose(mat,MAT_INITIAL_MATRIX,&AA));
7447     PetscCall(MatAXPY(AA,1.0,mat,DIFFERENT_NONZERO_PATTERN));
7448   }
7449   PetscCall(MatAIJGetLocalMat(AA,&A));
7450   PetscCall(MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7451   PetscCheck(done,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unable to get IJ structure from matrix");
7452 
7453   PetscCall(MatGetLocalSize(mat,&n,NULL));
7454   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag));
7455   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
7456   PetscCallMPI(MPI_Comm_size(comm,&size));
7457   PetscCallMPI(MPI_Comm_rank(comm,&rank));
7458 
7459   PetscCall(PetscMalloc2(n,&sizes,n,&starts));
7460 
7461   if (rank > 0) {
7462     PetscCallMPI(MPI_Recv(&env,1,MPIU_INT,rank-1,tag,comm,&status));
7463     PetscCallMPI(MPI_Recv(&tbs,1,MPIU_INT,rank-1,tag,comm,&status));
7464   }
7465   PetscCall(MatGetOwnershipRange(mat,&rstart,NULL));
7466   for (i=0; i<n; i++) {
7467     env = PetscMax(env,ja[ia[i+1]-1]);
7468     II = rstart + i;
7469     if (env == II) {
7470       starts[lblocks]  = tbs;
7471       sizes[lblocks++] = 1 + II - tbs;
7472       tbs = 1 + II;
7473     }
7474   }
7475   if (rank < size-1) {
7476     PetscCallMPI(MPI_Send(&env,1,MPIU_INT,rank+1,tag,comm));
7477     PetscCallMPI(MPI_Send(&tbs,1,MPIU_INT,rank+1,tag,comm));
7478   }
7479 
7480   PetscCall(MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7481   if (!set || !flag) {
7482     PetscCall(MatDestroy(&AA));
7483   }
7484   PetscCall(MatDestroy(&A));
7485 
7486   PetscCall(PetscNew(&edata));
7487   PetscCall(MatGetNonzeroState(mat,&edata->nonzerostate));
7488   edata->n = lblocks;
7489   /* create IS needed for extracting blocks from the original matrix */
7490   PetscCall(PetscMalloc1(lblocks,&edata->is));
7491   for (PetscInt i=0; i<lblocks; i++) {
7492     PetscCall(ISCreateStride(PETSC_COMM_SELF,sizes[i],starts[i],1,&edata->is[i]));
7493   }
7494 
7495   /* Create the resulting inverse matrix structure with preallocation information */
7496   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&edata->C));
7497   PetscCall(MatSetSizes(edata->C,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
7498   PetscCall(MatSetBlockSizesFromMats(edata->C,mat,mat));
7499   PetscCall(MatSetType(edata->C,MATAIJ));
7500 
7501   /* Communicate the start and end of each row, from each block to the correct rank */
7502   /* TODO: Use PetscSF instead of VecScatter */
7503   for (PetscInt i=0; i<lblocks; i++) ln += sizes[i];
7504   PetscCall(VecCreateSeq(PETSC_COMM_SELF,2*ln,&seq));
7505   PetscCall(VecGetArrayWrite(seq,&seqv));
7506   for (PetscInt i=0; i<lblocks; i++) {
7507     for (PetscInt j=0; j<sizes[i]; j++) {
7508       seqv[cnt]   = starts[i];
7509       seqv[cnt+1] = starts[i] + sizes[i];
7510       cnt += 2;
7511     }
7512   }
7513   PetscCall(VecRestoreArrayWrite(seq,&seqv));
7514   PetscCallMPI(MPI_Scan(&cnt,&sc,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
7515   sc -= cnt;
7516   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat),2*mat->rmap->n,2*mat->rmap->N,&par));
7517   PetscCall(ISCreateStride(PETSC_COMM_SELF,cnt,sc,1,&isglobal));
7518   PetscCall(VecScatterCreate(seq, NULL  ,par, isglobal,&scatter));
7519   PetscCall(ISDestroy(&isglobal));
7520   PetscCall(VecScatterBegin(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7521   PetscCall(VecScatterEnd(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7522   PetscCall(VecScatterDestroy(&scatter));
7523   PetscCall(VecDestroy(&seq));
7524   PetscCall(MatGetOwnershipRangeColumn(mat,&cstart,&cend));
7525   PetscCall(PetscMalloc2(mat->rmap->n,&diag,mat->rmap->n,&odiag));
7526   PetscCall(VecGetArrayRead(par,&parv));
7527   cnt = 0;
7528   PetscCall(MatGetSize(mat,NULL,&n));
7529   for (PetscInt i=0; i<mat->rmap->n; i++) {
7530     PetscInt start,end,d = 0,od = 0;
7531 
7532     start = (PetscInt)PetscRealPart(parv[cnt]);
7533     end   = (PetscInt)PetscRealPart(parv[cnt+1]);
7534     cnt  += 2;
7535 
7536     if (start < cstart) {od += cstart - start + n - cend; d += cend - cstart;}
7537     else if (start < cend) {od += n - cend; d += cend - start;}
7538     else od += n - start;
7539     if (end <= cstart) {od -= cstart - end + n - cend; d -= cend - cstart;}
7540     else if (end < cend) {od -= n - cend; d -= cend - end;}
7541     else od -= n - end;
7542 
7543     odiag[i] = od;
7544     diag[i]  = d;
7545   }
7546   PetscCall(VecRestoreArrayRead(par,&parv));
7547   PetscCall(VecDestroy(&par));
7548   PetscCall(MatXAIJSetPreallocation(edata->C,mat->rmap->bs,diag,odiag,NULL,NULL));
7549   PetscCall(PetscFree2(diag,odiag));
7550   PetscCall(PetscFree2(sizes,starts));
7551 
7552   PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&container));
7553   PetscCall(PetscContainerSetPointer(container,edata));
7554   PetscCall(PetscContainerSetUserDestroy(container,(PetscErrorCode (*)(void*))EnvelopeDataDestroy));
7555   PetscCall(PetscObjectCompose((PetscObject)mat,"EnvelopeData",(PetscObject)container));
7556   PetscCall(PetscObjectDereference((PetscObject)container));
7557   PetscFunctionReturn(0);
7558 }
7559 
7560 /*@
7561   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7562 
7563   Collective on Mat
7564 
7565   Input Parameters:
7566 . A - the matrix
7567 
7568   Output Parameters:
7569 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7570 
7571   Notes:
7572      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7573 
7574   Level: advanced
7575 
7576 .seealso: MatInvertBlockDiagonal(), MatComputeBlockDiagonal()
7577 @*/
7578 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A,MatReuse reuse, Mat *C)
7579 {
7580   PetscContainer    container;
7581   EnvelopeData      *edata;
7582   PetscObjectState  nonzerostate;
7583 
7584   PetscFunctionBegin;
7585   PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7586   if (!container) {
7587     PetscCall(MatComputeVariableBlockEnvelope(A));
7588     PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7589   }
7590   PetscCall(PetscContainerGetPointer(container,(void**)&edata));
7591   PetscCall(MatGetNonzeroState(A,&nonzerostate));
7592   PetscCheck(nonzerostate <= edata->nonzerostate,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Cannot handle changes to matrix nonzero structure");
7593   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"C matrix must be the same as previously output");
7594 
7595   PetscCall(MatCreateSubMatrices(A,edata->n,edata->is,edata->is,MAT_INITIAL_MATRIX,&edata->mat));
7596   *C   = edata->C;
7597 
7598   for (PetscInt i=0; i<edata->n; i++) {
7599     Mat         D;
7600     PetscScalar *dvalues;
7601 
7602     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE,MAT_INITIAL_MATRIX,&D));
7603     PetscCall(MatSetOption(*C,MAT_ROW_ORIENTED,PETSC_FALSE));
7604     PetscCall(MatSeqDenseInvert(D));
7605     PetscCall(MatDenseGetArray(D,&dvalues));
7606     PetscCall(MatSetValuesIS(*C,edata->is[i],edata->is[i],dvalues,INSERT_VALUES));
7607     PetscCall(MatDestroy(&D));
7608   }
7609   PetscCall(MatDestroySubMatrices(edata->n,&edata->mat));
7610   PetscCall(MatAssemblyBegin(*C,MAT_FINAL_ASSEMBLY));
7611   PetscCall(MatAssemblyEnd(*C,MAT_FINAL_ASSEMBLY));
7612   PetscFunctionReturn(0);
7613 }
7614 
7615 /*@
7616    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7617 
7618    Logically Collective on Mat
7619 
7620    Input Parameters:
7621 +  mat - the matrix
7622 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7623 -  bsizes - the block sizes
7624 
7625    Notes:
7626     Currently used by PCVPBJACOBI for AIJ matrices
7627 
7628     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.
7629 
7630    Level: intermediate
7631 
7632 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7633 @*/
7634 PetscErrorCode MatSetVariableBlockSizes(Mat mat,PetscInt nblocks,PetscInt *bsizes)
7635 {
7636   PetscInt       i,ncnt = 0, nlocal;
7637 
7638   PetscFunctionBegin;
7639   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7640   PetscCheck(nblocks >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Number of local blocks must be great than or equal to zero");
7641   PetscCall(MatGetLocalSize(mat,&nlocal,NULL));
7642   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
7643   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);
7644   PetscCall(PetscFree(mat->bsizes));
7645   mat->nblocks = nblocks;
7646   PetscCall(PetscMalloc1(nblocks,&mat->bsizes));
7647   PetscCall(PetscArraycpy(mat->bsizes,bsizes,nblocks));
7648   PetscFunctionReturn(0);
7649 }
7650 
7651 /*@C
7652    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7653 
7654    Logically Collective on Mat
7655 
7656    Input Parameter:
7657 .  mat - the matrix
7658 
7659    Output Parameters:
7660 +  nblocks - the number of blocks on this process
7661 -  bsizes - the block sizes
7662 
7663    Notes: Currently not supported from Fortran
7664 
7665    Level: intermediate
7666 
7667 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7668 @*/
7669 PetscErrorCode MatGetVariableBlockSizes(Mat mat,PetscInt *nblocks,const PetscInt **bsizes)
7670 {
7671   PetscFunctionBegin;
7672   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7673   *nblocks = mat->nblocks;
7674   *bsizes  = mat->bsizes;
7675   PetscFunctionReturn(0);
7676 }
7677 
7678 /*@
7679    MatSetBlockSizes - Sets the matrix block row and column sizes.
7680 
7681    Logically Collective on Mat
7682 
7683    Input Parameters:
7684 +  mat - the matrix
7685 .  rbs - row block size
7686 -  cbs - column block size
7687 
7688    Notes:
7689     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7690     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7691     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7692 
7693     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block sizes
7694     are compatible with the matrix local sizes.
7695 
7696     The row and column block size determine the blocksize of the "row" and "column" vectors returned by MatCreateVecs().
7697 
7698    Level: intermediate
7699 
7700 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7701 @*/
7702 PetscErrorCode MatSetBlockSizes(Mat mat,PetscInt rbs,PetscInt cbs)
7703 {
7704   PetscFunctionBegin;
7705   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7706   PetscValidLogicalCollectiveInt(mat,rbs,2);
7707   PetscValidLogicalCollectiveInt(mat,cbs,3);
7708   if (mat->ops->setblocksizes) {
7709     PetscCall((*mat->ops->setblocksizes)(mat,rbs,cbs));
7710   }
7711   if (mat->rmap->refcnt) {
7712     ISLocalToGlobalMapping l2g = NULL;
7713     PetscLayout            nmap = NULL;
7714 
7715     PetscCall(PetscLayoutDuplicate(mat->rmap,&nmap));
7716     if (mat->rmap->mapping) {
7717       PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping,&l2g));
7718     }
7719     PetscCall(PetscLayoutDestroy(&mat->rmap));
7720     mat->rmap = nmap;
7721     mat->rmap->mapping = l2g;
7722   }
7723   if (mat->cmap->refcnt) {
7724     ISLocalToGlobalMapping l2g = NULL;
7725     PetscLayout            nmap = NULL;
7726 
7727     PetscCall(PetscLayoutDuplicate(mat->cmap,&nmap));
7728     if (mat->cmap->mapping) {
7729       PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping,&l2g));
7730     }
7731     PetscCall(PetscLayoutDestroy(&mat->cmap));
7732     mat->cmap = nmap;
7733     mat->cmap->mapping = l2g;
7734   }
7735   PetscCall(PetscLayoutSetBlockSize(mat->rmap,rbs));
7736   PetscCall(PetscLayoutSetBlockSize(mat->cmap,cbs));
7737   PetscFunctionReturn(0);
7738 }
7739 
7740 /*@
7741    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7742 
7743    Logically Collective on Mat
7744 
7745    Input Parameters:
7746 +  mat - the matrix
7747 .  fromRow - matrix from which to copy row block size
7748 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7749 
7750    Level: developer
7751 
7752 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7753 @*/
7754 PetscErrorCode MatSetBlockSizesFromMats(Mat mat,Mat fromRow,Mat fromCol)
7755 {
7756   PetscFunctionBegin;
7757   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7758   PetscValidHeaderSpecific(fromRow,MAT_CLASSID,2);
7759   PetscValidHeaderSpecific(fromCol,MAT_CLASSID,3);
7760   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap,fromRow->rmap->bs));
7761   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap,fromCol->cmap->bs));
7762   PetscFunctionReturn(0);
7763 }
7764 
7765 /*@
7766    MatResidual - Default routine to calculate the residual.
7767 
7768    Collective on Mat
7769 
7770    Input Parameters:
7771 +  mat - the matrix
7772 .  b   - the right-hand-side
7773 -  x   - the approximate solution
7774 
7775    Output Parameter:
7776 .  r - location to store the residual
7777 
7778    Level: developer
7779 
7780 .seealso: `PCMGSetResidual()`
7781 @*/
7782 PetscErrorCode MatResidual(Mat mat,Vec b,Vec x,Vec r)
7783 {
7784   PetscFunctionBegin;
7785   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7786   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
7787   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
7788   PetscValidHeaderSpecific(r,VEC_CLASSID,4);
7789   PetscValidType(mat,1);
7790   MatCheckPreallocated(mat,1);
7791   PetscCall(PetscLogEventBegin(MAT_Residual,mat,0,0,0));
7792   if (!mat->ops->residual) {
7793     PetscCall(MatMult(mat,x,r));
7794     PetscCall(VecAYPX(r,-1.0,b));
7795   } else {
7796     PetscCall((*mat->ops->residual)(mat,b,x,r));
7797   }
7798   PetscCall(PetscLogEventEnd(MAT_Residual,mat,0,0,0));
7799   PetscFunctionReturn(0);
7800 }
7801 
7802 /*@C
7803     MatGetRowIJ - Returns the compressed row storage i and j indices for sequential matrices.
7804 
7805    Collective on Mat
7806 
7807     Input Parameters:
7808 +   mat - the matrix
7809 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7810 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be   symmetrized
7811 -   inodecompressed - PETSC_TRUE or PETSC_FALSE  indicating if the nonzero structure of the
7812                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7813                  always used.
7814 
7815     Output Parameters:
7816 +   n - number of rows in the (possibly compressed) matrix
7817 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7818 .   ja - the column indices
7819 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7820            are responsible for handling the case when done == PETSC_FALSE and ia and ja are not set
7821 
7822     Level: developer
7823 
7824     Notes:
7825     You CANNOT change any of the ia[] or ja[] values.
7826 
7827     Use MatRestoreRowIJ() when you are finished accessing the ia[] and ja[] values.
7828 
7829     Fortran Notes:
7830     In Fortran use
7831 $
7832 $      PetscInt ia(1), ja(1)
7833 $      PetscOffset iia, jja
7834 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7835 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7836 
7837      or
7838 $
7839 $    PetscInt, pointer :: ia(:),ja(:)
7840 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7841 $    ! Access the ith and jth entries via ia(i) and ja(j)
7842 
7843 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7844 @*/
7845 PetscErrorCode MatGetRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7846 {
7847   PetscFunctionBegin;
7848   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7849   PetscValidType(mat,1);
7850   PetscValidIntPointer(n,5);
7851   if (ia) PetscValidPointer(ia,6);
7852   if (ja) PetscValidPointer(ja,7);
7853   PetscValidBoolPointer(done,8);
7854   MatCheckPreallocated(mat,1);
7855   if (!mat->ops->getrowij) *done = PETSC_FALSE;
7856   else {
7857     *done = PETSC_TRUE;
7858     PetscCall(PetscLogEventBegin(MAT_GetRowIJ,mat,0,0,0));
7859     PetscCall((*mat->ops->getrowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7860     PetscCall(PetscLogEventEnd(MAT_GetRowIJ,mat,0,0,0));
7861   }
7862   PetscFunctionReturn(0);
7863 }
7864 
7865 /*@C
7866     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7867 
7868     Collective on Mat
7869 
7870     Input Parameters:
7871 +   mat - the matrix
7872 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7873 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7874                 symmetrized
7875 .   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7876                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7877                  always used.
7878 .   n - number of columns in the (possibly compressed) matrix
7879 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7880 -   ja - the row indices
7881 
7882     Output Parameters:
7883 .   done - PETSC_TRUE or PETSC_FALSE, indicating whether the values have been returned
7884 
7885     Level: developer
7886 
7887 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7888 @*/
7889 PetscErrorCode MatGetColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7890 {
7891   PetscFunctionBegin;
7892   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7893   PetscValidType(mat,1);
7894   PetscValidIntPointer(n,5);
7895   if (ia) PetscValidPointer(ia,6);
7896   if (ja) PetscValidPointer(ja,7);
7897   PetscValidBoolPointer(done,8);
7898   MatCheckPreallocated(mat,1);
7899   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7900   else {
7901     *done = PETSC_TRUE;
7902     PetscCall((*mat->ops->getcolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7903   }
7904   PetscFunctionReturn(0);
7905 }
7906 
7907 /*@C
7908     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with
7909     MatGetRowIJ().
7910 
7911     Collective on Mat
7912 
7913     Input Parameters:
7914 +   mat - the matrix
7915 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7916 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7917                 symmetrized
7918 .   inodecompressed -  PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7919                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7920                  always used.
7921 .   n - size of (possibly compressed) matrix
7922 .   ia - the row pointers
7923 -   ja - the column indices
7924 
7925     Output Parameters:
7926 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7927 
7928     Note:
7929     This routine zeros out n, ia, and ja. This is to prevent accidental
7930     us of the array after it has been restored. If you pass NULL, it will
7931     not zero the pointers.  Use of ia or ja after MatRestoreRowIJ() is invalid.
7932 
7933     Level: developer
7934 
7935 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7936 @*/
7937 PetscErrorCode MatRestoreRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7938 {
7939   PetscFunctionBegin;
7940   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7941   PetscValidType(mat,1);
7942   if (ia) PetscValidPointer(ia,6);
7943   if (ja) PetscValidPointer(ja,7);
7944   PetscValidBoolPointer(done,8);
7945   MatCheckPreallocated(mat,1);
7946 
7947   if (!mat->ops->restorerowij) *done = PETSC_FALSE;
7948   else {
7949     *done = PETSC_TRUE;
7950     PetscCall((*mat->ops->restorerowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7951     if (n)  *n = 0;
7952     if (ia) *ia = NULL;
7953     if (ja) *ja = NULL;
7954   }
7955   PetscFunctionReturn(0);
7956 }
7957 
7958 /*@C
7959     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with
7960     MatGetColumnIJ().
7961 
7962     Collective on Mat
7963 
7964     Input Parameters:
7965 +   mat - the matrix
7966 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7967 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7968                 symmetrized
7969 -   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7970                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7971                  always used.
7972 
7973     Output Parameters:
7974 +   n - size of (possibly compressed) matrix
7975 .   ia - the column pointers
7976 .   ja - the row indices
7977 -   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7978 
7979     Level: developer
7980 
7981 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7982 @*/
7983 PetscErrorCode MatRestoreColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7984 {
7985   PetscFunctionBegin;
7986   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7987   PetscValidType(mat,1);
7988   if (ia) PetscValidPointer(ia,6);
7989   if (ja) PetscValidPointer(ja,7);
7990   PetscValidBoolPointer(done,8);
7991   MatCheckPreallocated(mat,1);
7992 
7993   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7994   else {
7995     *done = PETSC_TRUE;
7996     PetscCall((*mat->ops->restorecolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7997     if (n)  *n = 0;
7998     if (ia) *ia = NULL;
7999     if (ja) *ja = NULL;
8000   }
8001   PetscFunctionReturn(0);
8002 }
8003 
8004 /*@C
8005     MatColoringPatch -Used inside matrix coloring routines that
8006     use MatGetRowIJ() and/or MatGetColumnIJ().
8007 
8008     Collective on Mat
8009 
8010     Input Parameters:
8011 +   mat - the matrix
8012 .   ncolors - max color value
8013 .   n   - number of entries in colorarray
8014 -   colorarray - array indicating color for each column
8015 
8016     Output Parameters:
8017 .   iscoloring - coloring generated using colorarray information
8018 
8019     Level: developer
8020 
8021 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
8022 
8023 @*/
8024 PetscErrorCode MatColoringPatch(Mat mat,PetscInt ncolors,PetscInt n,ISColoringValue colorarray[],ISColoring *iscoloring)
8025 {
8026   PetscFunctionBegin;
8027   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8028   PetscValidType(mat,1);
8029   PetscValidIntPointer(colorarray,4);
8030   PetscValidPointer(iscoloring,5);
8031   MatCheckPreallocated(mat,1);
8032 
8033   if (!mat->ops->coloringpatch) {
8034     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat),ncolors,n,colorarray,PETSC_OWN_POINTER,iscoloring));
8035   } else {
8036     PetscCall((*mat->ops->coloringpatch)(mat,ncolors,n,colorarray,iscoloring));
8037   }
8038   PetscFunctionReturn(0);
8039 }
8040 
8041 /*@
8042    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8043 
8044    Logically Collective on Mat
8045 
8046    Input Parameter:
8047 .  mat - the factored matrix to be reset
8048 
8049    Notes:
8050    This routine should be used only with factored matrices formed by in-place
8051    factorization via ILU(0) (or by in-place LU factorization for the MATSEQDENSE
8052    format).  This option can save memory, for example, when solving nonlinear
8053    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8054    ILU(0) preconditioner.
8055 
8056    Note that one can specify in-place ILU(0) factorization by calling
8057 .vb
8058      PCType(pc,PCILU);
8059      PCFactorSeUseInPlace(pc);
8060 .ve
8061    or by using the options -pc_type ilu -pc_factor_in_place
8062 
8063    In-place factorization ILU(0) can also be used as a local
8064    solver for the blocks within the block Jacobi or additive Schwarz
8065    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8066    for details on setting local solver options.
8067 
8068    Most users should employ the simplified KSP interface for linear solvers
8069    instead of working directly with matrix algebra routines such as this.
8070    See, e.g., KSPCreate().
8071 
8072    Level: developer
8073 
8074 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8075 
8076 @*/
8077 PetscErrorCode MatSetUnfactored(Mat mat)
8078 {
8079   PetscFunctionBegin;
8080   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8081   PetscValidType(mat,1);
8082   MatCheckPreallocated(mat,1);
8083   mat->factortype = MAT_FACTOR_NONE;
8084   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
8085   PetscCall((*mat->ops->setunfactored)(mat));
8086   PetscFunctionReturn(0);
8087 }
8088 
8089 /*MC
8090     MatDenseGetArrayF90 - Accesses a matrix array from Fortran90.
8091 
8092     Synopsis:
8093     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8094 
8095     Not collective
8096 
8097     Input Parameter:
8098 .   x - matrix
8099 
8100     Output Parameters:
8101 +   xx_v - the Fortran90 pointer to the array
8102 -   ierr - error code
8103 
8104     Example of Usage:
8105 .vb
8106       PetscScalar, pointer xx_v(:,:)
8107       ....
8108       call MatDenseGetArrayF90(x,xx_v,ierr)
8109       a = xx_v(3)
8110       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8111 .ve
8112 
8113     Level: advanced
8114 
8115 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8116 
8117 M*/
8118 
8119 /*MC
8120     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8121     accessed with MatDenseGetArrayF90().
8122 
8123     Synopsis:
8124     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8125 
8126     Not collective
8127 
8128     Input Parameters:
8129 +   x - matrix
8130 -   xx_v - the Fortran90 pointer to the array
8131 
8132     Output Parameter:
8133 .   ierr - error code
8134 
8135     Example of Usage:
8136 .vb
8137        PetscScalar, pointer xx_v(:,:)
8138        ....
8139        call MatDenseGetArrayF90(x,xx_v,ierr)
8140        a = xx_v(3)
8141        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8142 .ve
8143 
8144     Level: advanced
8145 
8146 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8147 
8148 M*/
8149 
8150 /*MC
8151     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran90.
8152 
8153     Synopsis:
8154     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8155 
8156     Not collective
8157 
8158     Input Parameter:
8159 .   x - matrix
8160 
8161     Output Parameters:
8162 +   xx_v - the Fortran90 pointer to the array
8163 -   ierr - error code
8164 
8165     Example of Usage:
8166 .vb
8167       PetscScalar, pointer xx_v(:)
8168       ....
8169       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8170       a = xx_v(3)
8171       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8172 .ve
8173 
8174     Level: advanced
8175 
8176 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8177 
8178 M*/
8179 
8180 /*MC
8181     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8182     accessed with MatSeqAIJGetArrayF90().
8183 
8184     Synopsis:
8185     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8186 
8187     Not collective
8188 
8189     Input Parameters:
8190 +   x - matrix
8191 -   xx_v - the Fortran90 pointer to the array
8192 
8193     Output Parameter:
8194 .   ierr - error code
8195 
8196     Example of Usage:
8197 .vb
8198        PetscScalar, pointer xx_v(:)
8199        ....
8200        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8201        a = xx_v(3)
8202        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8203 .ve
8204 
8205     Level: advanced
8206 
8207 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8208 
8209 M*/
8210 
8211 /*@
8212     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8213                       as the original matrix.
8214 
8215     Collective on Mat
8216 
8217     Input Parameters:
8218 +   mat - the original matrix
8219 .   isrow - parallel IS containing the rows this processor should obtain
8220 .   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.
8221 -   cll - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
8222 
8223     Output Parameter:
8224 .   newmat - the new submatrix, of the same type as the old
8225 
8226     Level: advanced
8227 
8228     Notes:
8229     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8230 
8231     Some matrix types place restrictions on the row and column indices, such
8232     as that they be sorted or that they be equal to each other.
8233 
8234     The index sets may not have duplicate entries.
8235 
8236       The first time this is called you should use a cll of MAT_INITIAL_MATRIX,
8237    the MatCreateSubMatrix() routine will create the newmat for you. Any additional calls
8238    to this routine with a mat of the same nonzero structure and with a call of MAT_REUSE_MATRIX
8239    will reuse the matrix generated the first time.  You should call MatDestroy() on newmat when
8240    you are finished using it.
8241 
8242     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8243     the input matrix.
8244 
8245     If iscol is NULL then all columns are obtained (not supported in Fortran).
8246 
8247    Example usage:
8248    Consider the following 8x8 matrix with 34 non-zero values, that is
8249    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8250    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8251    as follows:
8252 
8253 .vb
8254             1  2  0  |  0  3  0  |  0  4
8255     Proc0   0  5  6  |  7  0  0  |  8  0
8256             9  0 10  | 11  0  0  | 12  0
8257     -------------------------------------
8258            13  0 14  | 15 16 17  |  0  0
8259     Proc1   0 18  0  | 19 20 21  |  0  0
8260             0  0  0  | 22 23  0  | 24  0
8261     -------------------------------------
8262     Proc2  25 26 27  |  0  0 28  | 29  0
8263            30  0  0  | 31 32 33  |  0 34
8264 .ve
8265 
8266     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8267 
8268 .vb
8269             2  0  |  0  3  0  |  0
8270     Proc0   5  6  |  7  0  0  |  8
8271     -------------------------------
8272     Proc1  18  0  | 19 20 21  |  0
8273     -------------------------------
8274     Proc2  26 27  |  0  0 28  | 29
8275             0  0  | 31 32 33  |  0
8276 .ve
8277 
8278 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8279 @*/
8280 PetscErrorCode MatCreateSubMatrix(Mat mat,IS isrow,IS iscol,MatReuse cll,Mat *newmat)
8281 {
8282   PetscMPIInt    size;
8283   Mat            *local;
8284   IS             iscoltmp;
8285   PetscBool      flg;
8286 
8287   PetscFunctionBegin;
8288   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8289   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
8290   if (iscol) PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
8291   PetscValidPointer(newmat,5);
8292   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat,MAT_CLASSID,5);
8293   PetscValidType(mat,1);
8294   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8295   PetscCheck(cll != MAT_IGNORE_MATRIX,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Cannot use MAT_IGNORE_MATRIX");
8296 
8297   MatCheckPreallocated(mat,1);
8298   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8299 
8300   if (!iscol || isrow == iscol) {
8301     PetscBool   stride;
8302     PetscMPIInt grabentirematrix = 0,grab;
8303     PetscCall(PetscObjectTypeCompare((PetscObject)isrow,ISSTRIDE,&stride));
8304     if (stride) {
8305       PetscInt first,step,n,rstart,rend;
8306       PetscCall(ISStrideGetInfo(isrow,&first,&step));
8307       if (step == 1) {
8308         PetscCall(MatGetOwnershipRange(mat,&rstart,&rend));
8309         if (rstart == first) {
8310           PetscCall(ISGetLocalSize(isrow,&n));
8311           if (n == rend-rstart) {
8312             grabentirematrix = 1;
8313           }
8314         }
8315       }
8316     }
8317     PetscCall(MPIU_Allreduce(&grabentirematrix,&grab,1,MPI_INT,MPI_MIN,PetscObjectComm((PetscObject)mat)));
8318     if (grab) {
8319       PetscCall(PetscInfo(mat,"Getting entire matrix as submatrix\n"));
8320       if (cll == MAT_INITIAL_MATRIX) {
8321         *newmat = mat;
8322         PetscCall(PetscObjectReference((PetscObject)mat));
8323       }
8324       PetscFunctionReturn(0);
8325     }
8326   }
8327 
8328   if (!iscol) {
8329     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat),mat->cmap->n,mat->cmap->rstart,1,&iscoltmp));
8330   } else {
8331     iscoltmp = iscol;
8332   }
8333 
8334   /* if original matrix is on just one processor then use submatrix generated */
8335   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8336     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_REUSE_MATRIX,&newmat));
8337     goto setproperties;
8338   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8339     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_INITIAL_MATRIX,&local));
8340     *newmat = *local;
8341     PetscCall(PetscFree(local));
8342     goto setproperties;
8343   } else if (!mat->ops->createsubmatrix) {
8344     /* Create a new matrix type that implements the operation using the full matrix */
8345     PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8346     switch (cll) {
8347     case MAT_INITIAL_MATRIX:
8348       PetscCall(MatCreateSubMatrixVirtual(mat,isrow,iscoltmp,newmat));
8349       break;
8350     case MAT_REUSE_MATRIX:
8351       PetscCall(MatSubMatrixVirtualUpdate(*newmat,mat,isrow,iscoltmp));
8352       break;
8353     default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8354     }
8355     PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8356     goto setproperties;
8357   }
8358 
8359   PetscCheck(mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8360   PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8361   PetscCall((*mat->ops->createsubmatrix)(mat,isrow,iscoltmp,cll,newmat));
8362   PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8363 
8364 setproperties:
8365   PetscCall(ISEqualUnsorted(isrow,iscoltmp,&flg));
8366   if (flg) {
8367     PetscCall(MatPropagateSymmetryOptions(mat,*newmat));
8368   }
8369   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8370   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8371   PetscFunctionReturn(0);
8372 }
8373 
8374 /*@
8375    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8376 
8377    Not Collective
8378 
8379    Input Parameters:
8380 +  A - the matrix we wish to propagate options from
8381 -  B - the matrix we wish to propagate options to
8382 
8383    Level: beginner
8384 
8385    Notes: Propagates the options associated to MAT_SYMMETRY_ETERNAL, MAT_STRUCTURALLY_SYMMETRIC, MAT_HERMITIAN, MAT_SPD and MAT_SYMMETRIC
8386 
8387 .seealso: `MatSetOption()`
8388 @*/
8389 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8390 {
8391   PetscFunctionBegin;
8392   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8393   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
8394   if (A->symmetric_eternal) { /* symmetric_eternal does not have a corresponding *set flag */
8395     PetscCall(MatSetOption(B,MAT_SYMMETRY_ETERNAL,A->symmetric_eternal));
8396   }
8397   if (A->structurally_symmetric_set) {
8398     PetscCall(MatSetOption(B,MAT_STRUCTURALLY_SYMMETRIC,A->structurally_symmetric));
8399   }
8400   if (A->hermitian_set) {
8401     PetscCall(MatSetOption(B,MAT_HERMITIAN,A->hermitian));
8402   }
8403   if (A->spd_set) {
8404     PetscCall(MatSetOption(B,MAT_SPD,A->spd));
8405   }
8406   if (A->symmetric_set) {
8407     PetscCall(MatSetOption(B,MAT_SYMMETRIC,A->symmetric));
8408   }
8409   PetscFunctionReturn(0);
8410 }
8411 
8412 /*@
8413    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8414    used during the assembly process to store values that belong to
8415    other processors.
8416 
8417    Not Collective
8418 
8419    Input Parameters:
8420 +  mat   - the matrix
8421 .  size  - the initial size of the stash.
8422 -  bsize - the initial size of the block-stash(if used).
8423 
8424    Options Database Keys:
8425 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8426 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8427 
8428    Level: intermediate
8429 
8430    Notes:
8431      The block-stash is used for values set with MatSetValuesBlocked() while
8432      the stash is used for values set with MatSetValues()
8433 
8434      Run with the option -info and look for output of the form
8435      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8436      to determine the appropriate value, MM, to use for size and
8437      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8438      to determine the value, BMM to use for bsize
8439 
8440 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8441 
8442 @*/
8443 PetscErrorCode MatStashSetInitialSize(Mat mat,PetscInt size, PetscInt bsize)
8444 {
8445   PetscFunctionBegin;
8446   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8447   PetscValidType(mat,1);
8448   PetscCall(MatStashSetInitialSize_Private(&mat->stash,size));
8449   PetscCall(MatStashSetInitialSize_Private(&mat->bstash,bsize));
8450   PetscFunctionReturn(0);
8451 }
8452 
8453 /*@
8454    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8455      the matrix
8456 
8457    Neighbor-wise Collective on Mat
8458 
8459    Input Parameters:
8460 +  mat   - the matrix
8461 .  x,y - the vectors
8462 -  w - where the result is stored
8463 
8464    Level: intermediate
8465 
8466    Notes:
8467     w may be the same vector as y.
8468 
8469     This allows one to use either the restriction or interpolation (its transpose)
8470     matrix to do the interpolation
8471 
8472 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8473 
8474 @*/
8475 PetscErrorCode MatInterpolateAdd(Mat A,Vec x,Vec y,Vec w)
8476 {
8477   PetscInt       M,N,Ny;
8478 
8479   PetscFunctionBegin;
8480   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8481   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8482   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8483   PetscValidHeaderSpecific(w,VEC_CLASSID,4);
8484   PetscCall(MatGetSize(A,&M,&N));
8485   PetscCall(VecGetSize(y,&Ny));
8486   if (M == Ny) {
8487     PetscCall(MatMultAdd(A,x,y,w));
8488   } else {
8489     PetscCall(MatMultTransposeAdd(A,x,y,w));
8490   }
8491   PetscFunctionReturn(0);
8492 }
8493 
8494 /*@
8495    MatInterpolate - y = A*x or A'*x depending on the shape of
8496      the matrix
8497 
8498    Neighbor-wise Collective on Mat
8499 
8500    Input Parameters:
8501 +  mat   - the matrix
8502 -  x,y - the vectors
8503 
8504    Level: intermediate
8505 
8506    Notes:
8507     This allows one to use either the restriction or interpolation (its transpose)
8508     matrix to do the interpolation
8509 
8510 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8511 
8512 @*/
8513 PetscErrorCode MatInterpolate(Mat A,Vec x,Vec y)
8514 {
8515   PetscInt       M,N,Ny;
8516 
8517   PetscFunctionBegin;
8518   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8519   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8520   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8521   PetscCall(MatGetSize(A,&M,&N));
8522   PetscCall(VecGetSize(y,&Ny));
8523   if (M == Ny) {
8524     PetscCall(MatMult(A,x,y));
8525   } else {
8526     PetscCall(MatMultTranspose(A,x,y));
8527   }
8528   PetscFunctionReturn(0);
8529 }
8530 
8531 /*@
8532    MatRestrict - y = A*x or A'*x
8533 
8534    Neighbor-wise Collective on Mat
8535 
8536    Input Parameters:
8537 +  mat   - the matrix
8538 -  x,y - the vectors
8539 
8540    Level: intermediate
8541 
8542    Notes:
8543     This allows one to use either the restriction or interpolation (its transpose)
8544     matrix to do the restriction
8545 
8546 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`
8547 
8548 @*/
8549 PetscErrorCode MatRestrict(Mat A,Vec x,Vec y)
8550 {
8551   PetscInt       M,N,Ny;
8552 
8553   PetscFunctionBegin;
8554   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8555   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8556   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8557   PetscCall(MatGetSize(A,&M,&N));
8558   PetscCall(VecGetSize(y,&Ny));
8559   if (M == Ny) {
8560     PetscCall(MatMult(A,x,y));
8561   } else {
8562     PetscCall(MatMultTranspose(A,x,y));
8563   }
8564   PetscFunctionReturn(0);
8565 }
8566 
8567 /*@
8568    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8569 
8570    Neighbor-wise Collective on Mat
8571 
8572    Input Parameters:
8573 +  mat   - the matrix
8574 -  w, x - the input dense matrices
8575 
8576    Output Parameters:
8577 .  y - the output dense matrix
8578 
8579    Level: intermediate
8580 
8581    Notes:
8582     This allows one to use either the restriction or interpolation (its transpose)
8583     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8584     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8585 
8586 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`
8587 
8588 @*/
8589 PetscErrorCode MatMatInterpolateAdd(Mat A,Mat x,Mat w,Mat *y)
8590 {
8591   PetscInt       M,N,Mx,Nx,Mo,My = 0,Ny = 0;
8592   PetscBool      trans = PETSC_TRUE;
8593   MatReuse       reuse = MAT_INITIAL_MATRIX;
8594 
8595   PetscFunctionBegin;
8596   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8597   PetscValidHeaderSpecific(x,MAT_CLASSID,2);
8598   PetscValidType(x,2);
8599   if (w) PetscValidHeaderSpecific(w,MAT_CLASSID,3);
8600   if (*y) PetscValidHeaderSpecific(*y,MAT_CLASSID,4);
8601   PetscCall(MatGetSize(A,&M,&N));
8602   PetscCall(MatGetSize(x,&Mx,&Nx));
8603   if (N == Mx) trans = PETSC_FALSE;
8604   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);
8605   Mo = trans ? N : M;
8606   if (*y) {
8607     PetscCall(MatGetSize(*y,&My,&Ny));
8608     if (Mo == My && Nx == Ny) { reuse = MAT_REUSE_MATRIX; }
8609     else {
8610       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);
8611       PetscCall(MatDestroy(y));
8612     }
8613   }
8614 
8615   if (w && *y == w) { /* this is to minimize changes in PCMG */
8616     PetscBool flg;
8617 
8618     PetscCall(PetscObjectQuery((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject*)&w));
8619     if (w) {
8620       PetscInt My,Ny,Mw,Nw;
8621 
8622       PetscCall(PetscObjectTypeCompare((PetscObject)*y,((PetscObject)w)->type_name,&flg));
8623       PetscCall(MatGetSize(*y,&My,&Ny));
8624       PetscCall(MatGetSize(w,&Mw,&Nw));
8625       if (!flg || My != Mw || Ny != Nw) w = NULL;
8626     }
8627     if (!w) {
8628       PetscCall(MatDuplicate(*y,MAT_COPY_VALUES,&w));
8629       PetscCall(PetscObjectCompose((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject)w));
8630       PetscCall(PetscLogObjectParent((PetscObject)*y,(PetscObject)w));
8631       PetscCall(PetscObjectDereference((PetscObject)w));
8632     } else {
8633       PetscCall(MatCopy(*y,w,UNKNOWN_NONZERO_PATTERN));
8634     }
8635   }
8636   if (!trans) {
8637     PetscCall(MatMatMult(A,x,reuse,PETSC_DEFAULT,y));
8638   } else {
8639     PetscCall(MatTransposeMatMult(A,x,reuse,PETSC_DEFAULT,y));
8640   }
8641   if (w) {
8642     PetscCall(MatAXPY(*y,1.0,w,UNKNOWN_NONZERO_PATTERN));
8643   }
8644   PetscFunctionReturn(0);
8645 }
8646 
8647 /*@
8648    MatMatInterpolate - Y = A*X or A'*X
8649 
8650    Neighbor-wise Collective on Mat
8651 
8652    Input Parameters:
8653 +  mat   - the matrix
8654 -  x - the input dense matrix
8655 
8656    Output Parameters:
8657 .  y - the output dense matrix
8658 
8659    Level: intermediate
8660 
8661    Notes:
8662     This allows one to use either the restriction or interpolation (its transpose)
8663     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8664     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8665 
8666 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`
8667 
8668 @*/
8669 PetscErrorCode MatMatInterpolate(Mat A,Mat x,Mat *y)
8670 {
8671   PetscFunctionBegin;
8672   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8673   PetscFunctionReturn(0);
8674 }
8675 
8676 /*@
8677    MatMatRestrict - Y = A*X or A'*X
8678 
8679    Neighbor-wise Collective on Mat
8680 
8681    Input Parameters:
8682 +  mat   - the matrix
8683 -  x - the input dense matrix
8684 
8685    Output Parameters:
8686 .  y - the output dense matrix
8687 
8688    Level: intermediate
8689 
8690    Notes:
8691     This allows one to use either the restriction or interpolation (its transpose)
8692     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8693     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8694 
8695 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`
8696 @*/
8697 PetscErrorCode MatMatRestrict(Mat A,Mat x,Mat *y)
8698 {
8699   PetscFunctionBegin;
8700   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8701   PetscFunctionReturn(0);
8702 }
8703 
8704 /*@
8705    MatGetNullSpace - retrieves the null space of a matrix.
8706 
8707    Logically Collective on Mat
8708 
8709    Input Parameters:
8710 +  mat - the matrix
8711 -  nullsp - the null space object
8712 
8713    Level: developer
8714 
8715 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`
8716 @*/
8717 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8718 {
8719   PetscFunctionBegin;
8720   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8721   PetscValidPointer(nullsp,2);
8722   *nullsp = (mat->symmetric_set && mat->symmetric && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8723   PetscFunctionReturn(0);
8724 }
8725 
8726 /*@
8727    MatSetNullSpace - attaches a null space to a matrix.
8728 
8729    Logically Collective on Mat
8730 
8731    Input Parameters:
8732 +  mat - the matrix
8733 -  nullsp - the null space object
8734 
8735    Level: advanced
8736 
8737    Notes:
8738       This null space is used by the KSP linear solvers to solve singular systems.
8739 
8740       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
8741 
8742       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
8743       to zero but the linear system will still be solved in a least squares sense.
8744 
8745       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8746    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).
8747    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
8748    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
8749    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).
8750    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8751 
8752     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
8753     routine also automatically calls MatSetTransposeNullSpace().
8754 
8755     The user should call `MatNullSpaceDestroy()`.
8756 
8757 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8758           `KSPSetPCSide()`
8759 @*/
8760 PetscErrorCode MatSetNullSpace(Mat mat,MatNullSpace nullsp)
8761 {
8762   PetscFunctionBegin;
8763   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8764   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8765   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8766   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8767   mat->nullsp = nullsp;
8768   if (mat->symmetric_set && mat->symmetric) {
8769     PetscCall(MatSetTransposeNullSpace(mat,nullsp));
8770   }
8771   PetscFunctionReturn(0);
8772 }
8773 
8774 /*@
8775    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8776 
8777    Logically Collective on Mat
8778 
8779    Input Parameters:
8780 +  mat - the matrix
8781 -  nullsp - the null space object
8782 
8783    Level: developer
8784 
8785 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8786 @*/
8787 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8788 {
8789   PetscFunctionBegin;
8790   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8791   PetscValidType(mat,1);
8792   PetscValidPointer(nullsp,2);
8793   *nullsp = (mat->symmetric_set && mat->symmetric && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8794   PetscFunctionReturn(0);
8795 }
8796 
8797 /*@
8798    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8799 
8800    Logically Collective on Mat
8801 
8802    Input Parameters:
8803 +  mat - the matrix
8804 -  nullsp - the null space object
8805 
8806    Level: advanced
8807 
8808    Notes:
8809       This allows solving singular linear systems defined by the transpose of the matrix using KSP solvers with left preconditioning.
8810 
8811       See MatSetNullSpace()
8812 
8813 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8814 @*/
8815 PetscErrorCode MatSetTransposeNullSpace(Mat mat,MatNullSpace nullsp)
8816 {
8817   PetscFunctionBegin;
8818   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8819   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8820   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8821   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8822   mat->transnullsp = nullsp;
8823   PetscFunctionReturn(0);
8824 }
8825 
8826 /*@
8827    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8828         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8829 
8830    Logically Collective on Mat
8831 
8832    Input Parameters:
8833 +  mat - the matrix
8834 -  nullsp - the null space object
8835 
8836    Level: advanced
8837 
8838    Notes:
8839       Overwrites any previous near null space that may have been attached
8840 
8841       You can remove the null space by calling this routine with an nullsp of NULL
8842 
8843 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8844 @*/
8845 PetscErrorCode MatSetNearNullSpace(Mat mat,MatNullSpace nullsp)
8846 {
8847   PetscFunctionBegin;
8848   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8849   PetscValidType(mat,1);
8850   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8851   MatCheckPreallocated(mat,1);
8852   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8853   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8854   mat->nearnullsp = nullsp;
8855   PetscFunctionReturn(0);
8856 }
8857 
8858 /*@
8859    MatGetNearNullSpace - Get null space attached with MatSetNearNullSpace()
8860 
8861    Not Collective
8862 
8863    Input Parameter:
8864 .  mat - the matrix
8865 
8866    Output Parameter:
8867 .  nullsp - the null space object, NULL if not set
8868 
8869    Level: developer
8870 
8871 .seealso: `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8872 @*/
8873 PetscErrorCode MatGetNearNullSpace(Mat mat,MatNullSpace *nullsp)
8874 {
8875   PetscFunctionBegin;
8876   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8877   PetscValidType(mat,1);
8878   PetscValidPointer(nullsp,2);
8879   MatCheckPreallocated(mat,1);
8880   *nullsp = mat->nearnullsp;
8881   PetscFunctionReturn(0);
8882 }
8883 
8884 /*@C
8885    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8886 
8887    Collective on Mat
8888 
8889    Input Parameters:
8890 +  mat - the matrix
8891 .  row - row/column permutation
8892 .  fill - expected fill factor >= 1.0
8893 -  level - level of fill, for ICC(k)
8894 
8895    Notes:
8896    Probably really in-place only when level of fill is zero, otherwise allocates
8897    new space to store factored matrix and deletes previous memory.
8898 
8899    Most users should employ the simplified KSP interface for linear solvers
8900    instead of working directly with matrix algebra routines such as this.
8901    See, e.g., KSPCreate().
8902 
8903    Level: developer
8904 
8905 .seealso: `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8906 
8907     Developer Note: fortran interface is not autogenerated as the f90
8908     interface definition cannot be generated correctly [due to MatFactorInfo]
8909 
8910 @*/
8911 PetscErrorCode MatICCFactor(Mat mat,IS row,const MatFactorInfo *info)
8912 {
8913   PetscFunctionBegin;
8914   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8915   PetscValidType(mat,1);
8916   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
8917   PetscValidPointer(info,3);
8918   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
8919   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
8920   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8921   PetscCheck(mat->ops->iccfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8922   MatCheckPreallocated(mat,1);
8923   PetscCall((*mat->ops->iccfactor)(mat,row,info));
8924   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8925   PetscFunctionReturn(0);
8926 }
8927 
8928 /*@
8929    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8930          ghosted ones.
8931 
8932    Not Collective
8933 
8934    Input Parameters:
8935 +  mat - the matrix
8936 -  diag - the diagonal values, including ghost ones
8937 
8938    Level: developer
8939 
8940    Notes:
8941     Works only for MPIAIJ and MPIBAIJ matrices
8942 
8943 .seealso: `MatDiagonalScale()`
8944 @*/
8945 PetscErrorCode MatDiagonalScaleLocal(Mat mat,Vec diag)
8946 {
8947   PetscMPIInt    size;
8948 
8949   PetscFunctionBegin;
8950   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8951   PetscValidHeaderSpecific(diag,VEC_CLASSID,2);
8952   PetscValidType(mat,1);
8953 
8954   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be already assembled");
8955   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
8956   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8957   if (size == 1) {
8958     PetscInt n,m;
8959     PetscCall(VecGetSize(diag,&n));
8960     PetscCall(MatGetSize(mat,NULL,&m));
8961     if (m == n) {
8962       PetscCall(MatDiagonalScale(mat,NULL,diag));
8963     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only supported for sequential matrices when no ghost points/periodic conditions");
8964   } else {
8965     PetscUseMethod(mat,"MatDiagonalScaleLocal_C",(Mat,Vec),(mat,diag));
8966   }
8967   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
8968   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8969   PetscFunctionReturn(0);
8970 }
8971 
8972 /*@
8973    MatGetInertia - Gets the inertia from a factored matrix
8974 
8975    Collective on Mat
8976 
8977    Input Parameter:
8978 .  mat - the matrix
8979 
8980    Output Parameters:
8981 +   nneg - number of negative eigenvalues
8982 .   nzero - number of zero eigenvalues
8983 -   npos - number of positive eigenvalues
8984 
8985    Level: advanced
8986 
8987    Notes:
8988     Matrix must have been factored by MatCholeskyFactor()
8989 
8990 @*/
8991 PetscErrorCode MatGetInertia(Mat mat,PetscInt *nneg,PetscInt *nzero,PetscInt *npos)
8992 {
8993   PetscFunctionBegin;
8994   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8995   PetscValidType(mat,1);
8996   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
8997   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Numeric factor mat is not assembled");
8998   PetscCheck(mat->ops->getinertia,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8999   PetscCall((*mat->ops->getinertia)(mat,nneg,nzero,npos));
9000   PetscFunctionReturn(0);
9001 }
9002 
9003 /* ----------------------------------------------------------------*/
9004 /*@C
9005    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9006 
9007    Neighbor-wise Collective on Mats
9008 
9009    Input Parameters:
9010 +  mat - the factored matrix
9011 -  b - the right-hand-side vectors
9012 
9013    Output Parameter:
9014 .  x - the result vectors
9015 
9016    Notes:
9017    The vectors b and x cannot be the same.  I.e., one cannot
9018    call MatSolves(A,x,x).
9019 
9020    Notes:
9021    Most users should employ the simplified KSP interface for linear solvers
9022    instead of working directly with matrix algebra routines such as this.
9023    See, e.g., KSPCreate().
9024 
9025    Level: developer
9026 
9027 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9028 @*/
9029 PetscErrorCode MatSolves(Mat mat,Vecs b,Vecs x)
9030 {
9031   PetscFunctionBegin;
9032   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9033   PetscValidType(mat,1);
9034   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
9035   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
9036   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
9037 
9038   PetscCheck(mat->ops->solves,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
9039   MatCheckPreallocated(mat,1);
9040   PetscCall(PetscLogEventBegin(MAT_Solves,mat,0,0,0));
9041   PetscCall((*mat->ops->solves)(mat,b,x));
9042   PetscCall(PetscLogEventEnd(MAT_Solves,mat,0,0,0));
9043   PetscFunctionReturn(0);
9044 }
9045 
9046 /*@
9047    MatIsSymmetric - Test whether a matrix is symmetric
9048 
9049    Collective on Mat
9050 
9051    Input Parameters:
9052 +  A - the matrix to test
9053 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9054 
9055    Output Parameters:
9056 .  flg - the result
9057 
9058    Notes:
9059     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
9060 
9061    Level: intermediate
9062 
9063 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`
9064 @*/
9065 PetscErrorCode MatIsSymmetric(Mat A,PetscReal tol,PetscBool *flg)
9066 {
9067   PetscFunctionBegin;
9068   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9069   PetscValidBoolPointer(flg,3);
9070 
9071   if (!A->symmetric_set) {
9072     if (!A->ops->issymmetric) {
9073       MatType mattype;
9074       PetscCall(MatGetType(A,&mattype));
9075       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for symmetric",mattype);
9076     }
9077     PetscCall((*A->ops->issymmetric)(A,tol,flg));
9078     if (!tol) {
9079       PetscCall(MatSetOption(A,MAT_SYMMETRIC,*flg));
9080     }
9081   } else if (A->symmetric) {
9082     *flg = PETSC_TRUE;
9083   } else if (!tol) {
9084     *flg = PETSC_FALSE;
9085   } else {
9086     if (!A->ops->issymmetric) {
9087       MatType mattype;
9088       PetscCall(MatGetType(A,&mattype));
9089       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for symmetric",mattype);
9090     }
9091     PetscCall((*A->ops->issymmetric)(A,tol,flg));
9092   }
9093   PetscFunctionReturn(0);
9094 }
9095 
9096 /*@
9097    MatIsHermitian - Test whether a matrix is Hermitian
9098 
9099    Collective on Mat
9100 
9101    Input Parameters:
9102 +  A - the matrix to test
9103 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9104 
9105    Output Parameters:
9106 .  flg - the result
9107 
9108    Level: intermediate
9109 
9110 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9111           `MatIsSymmetricKnown()`, `MatIsSymmetric()`
9112 @*/
9113 PetscErrorCode MatIsHermitian(Mat A,PetscReal tol,PetscBool *flg)
9114 {
9115   PetscFunctionBegin;
9116   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9117   PetscValidBoolPointer(flg,3);
9118 
9119   if (!A->hermitian_set) {
9120     if (!A->ops->ishermitian) {
9121       MatType mattype;
9122       PetscCall(MatGetType(A,&mattype));
9123       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for hermitian",mattype);
9124     }
9125     PetscCall((*A->ops->ishermitian)(A,tol,flg));
9126     if (!tol) {
9127       PetscCall(MatSetOption(A,MAT_HERMITIAN,*flg));
9128     }
9129   } else if (A->hermitian) {
9130     *flg = PETSC_TRUE;
9131   } else if (!tol) {
9132     *flg = PETSC_FALSE;
9133   } else {
9134     if (!A->ops->ishermitian) {
9135       MatType mattype;
9136       PetscCall(MatGetType(A,&mattype));
9137       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for hermitian",mattype);
9138     }
9139     PetscCall((*A->ops->ishermitian)(A,tol,flg));
9140   }
9141   PetscFunctionReturn(0);
9142 }
9143 
9144 /*@
9145    MatIsSymmetricKnown - Checks the flag on the matrix to see if it is symmetric.
9146 
9147    Not Collective
9148 
9149    Input Parameter:
9150 .  A - the matrix to check
9151 
9152    Output Parameters:
9153 +  set - if the symmetric flag is set (this tells you if the next flag is valid)
9154 -  flg - the result
9155 
9156    Level: advanced
9157 
9158    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsSymmetric()
9159          if you want it explicitly checked
9160 
9161 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9162 @*/
9163 PetscErrorCode MatIsSymmetricKnown(Mat A,PetscBool *set,PetscBool *flg)
9164 {
9165   PetscFunctionBegin;
9166   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9167   PetscValidBoolPointer(set,2);
9168   PetscValidBoolPointer(flg,3);
9169   if (A->symmetric_set) {
9170     *set = PETSC_TRUE;
9171     *flg = A->symmetric;
9172   } else {
9173     *set = PETSC_FALSE;
9174   }
9175   PetscFunctionReturn(0);
9176 }
9177 
9178 /*@
9179    MatIsHermitianKnown - Checks the flag on the matrix to see if it is hermitian.
9180 
9181    Not Collective
9182 
9183    Input Parameter:
9184 .  A - the matrix to check
9185 
9186    Output Parameters:
9187 +  set - if the hermitian flag is set (this tells you if the next flag is valid)
9188 -  flg - the result
9189 
9190    Level: advanced
9191 
9192    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsHermitian()
9193          if you want it explicitly checked
9194 
9195 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9196 @*/
9197 PetscErrorCode MatIsHermitianKnown(Mat A,PetscBool *set,PetscBool *flg)
9198 {
9199   PetscFunctionBegin;
9200   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9201   PetscValidBoolPointer(set,2);
9202   PetscValidBoolPointer(flg,3);
9203   if (A->hermitian_set) {
9204     *set = PETSC_TRUE;
9205     *flg = A->hermitian;
9206   } else {
9207     *set = PETSC_FALSE;
9208   }
9209   PetscFunctionReturn(0);
9210 }
9211 
9212 /*@
9213    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9214 
9215    Collective on Mat
9216 
9217    Input Parameter:
9218 .  A - the matrix to test
9219 
9220    Output Parameters:
9221 .  flg - the result
9222 
9223    Level: intermediate
9224 
9225 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`
9226 @*/
9227 PetscErrorCode MatIsStructurallySymmetric(Mat A,PetscBool *flg)
9228 {
9229   PetscFunctionBegin;
9230   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9231   PetscValidBoolPointer(flg,2);
9232   if (!A->structurally_symmetric_set) {
9233     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);
9234     PetscCall((*A->ops->isstructurallysymmetric)(A,flg));
9235     PetscCall(MatSetOption(A,MAT_STRUCTURALLY_SYMMETRIC,*flg));
9236   } else *flg = A->structurally_symmetric;
9237   PetscFunctionReturn(0);
9238 }
9239 
9240 /*@
9241    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9242        to be communicated to other processors during the MatAssemblyBegin/End() process
9243 
9244     Not collective
9245 
9246    Input Parameter:
9247 .   vec - the vector
9248 
9249    Output Parameters:
9250 +   nstash   - the size of the stash
9251 .   reallocs - the number of additional mallocs incurred.
9252 .   bnstash   - the size of the block stash
9253 -   breallocs - the number of additional mallocs incurred.in the block stash
9254 
9255    Level: advanced
9256 
9257 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9258 
9259 @*/
9260 PetscErrorCode MatStashGetInfo(Mat mat,PetscInt *nstash,PetscInt *reallocs,PetscInt *bnstash,PetscInt *breallocs)
9261 {
9262   PetscFunctionBegin;
9263   PetscCall(MatStashGetInfo_Private(&mat->stash,nstash,reallocs));
9264   PetscCall(MatStashGetInfo_Private(&mat->bstash,bnstash,breallocs));
9265   PetscFunctionReturn(0);
9266 }
9267 
9268 /*@C
9269    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9270      parallel layout
9271 
9272    Collective on Mat
9273 
9274    Input Parameter:
9275 .  mat - the matrix
9276 
9277    Output Parameters:
9278 +   right - (optional) vector that the matrix can be multiplied against
9279 -   left - (optional) vector that the matrix vector product can be stored in
9280 
9281    Notes:
9282     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().
9283 
9284   Notes:
9285     These are new vectors which are not owned by the Mat, they should be destroyed in VecDestroy() when no longer needed
9286 
9287   Level: advanced
9288 
9289 .seealso: `MatCreate()`, `VecDestroy()`
9290 @*/
9291 PetscErrorCode MatCreateVecs(Mat mat,Vec *right,Vec *left)
9292 {
9293   PetscFunctionBegin;
9294   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9295   PetscValidType(mat,1);
9296   if (mat->ops->getvecs) {
9297     PetscCall((*mat->ops->getvecs)(mat,right,left));
9298   } else {
9299     PetscInt rbs,cbs;
9300     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
9301     if (right) {
9302       PetscCheck(mat->cmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for columns not yet setup");
9303       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),right));
9304       PetscCall(VecSetSizes(*right,mat->cmap->n,PETSC_DETERMINE));
9305       PetscCall(VecSetBlockSize(*right,cbs));
9306       PetscCall(VecSetType(*right,mat->defaultvectype));
9307 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9308       if (mat->boundtocpu && mat->bindingpropagates) {
9309         PetscCall(VecSetBindingPropagates(*right,PETSC_TRUE));
9310         PetscCall(VecBindToCPU(*right,PETSC_TRUE));
9311       }
9312 #endif
9313       PetscCall(PetscLayoutReference(mat->cmap,&(*right)->map));
9314     }
9315     if (left) {
9316       PetscCheck(mat->rmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for rows not yet setup");
9317       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),left));
9318       PetscCall(VecSetSizes(*left,mat->rmap->n,PETSC_DETERMINE));
9319       PetscCall(VecSetBlockSize(*left,rbs));
9320       PetscCall(VecSetType(*left,mat->defaultvectype));
9321 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9322       if (mat->boundtocpu && mat->bindingpropagates) {
9323         PetscCall(VecSetBindingPropagates(*left,PETSC_TRUE));
9324         PetscCall(VecBindToCPU(*left,PETSC_TRUE));
9325       }
9326 #endif
9327       PetscCall(PetscLayoutReference(mat->rmap,&(*left)->map));
9328     }
9329   }
9330   PetscFunctionReturn(0);
9331 }
9332 
9333 /*@C
9334    MatFactorInfoInitialize - Initializes a MatFactorInfo data structure
9335      with default values.
9336 
9337    Not Collective
9338 
9339    Input Parameters:
9340 .    info - the MatFactorInfo data structure
9341 
9342    Notes:
9343     The solvers are generally used through the KSP and PC objects, for example
9344           PCLU, PCILU, PCCHOLESKY, PCICC
9345 
9346    Level: developer
9347 
9348 .seealso: `MatFactorInfo`
9349 
9350     Developer Note: fortran interface is not autogenerated as the f90
9351     interface definition cannot be generated correctly [due to MatFactorInfo]
9352 
9353 @*/
9354 
9355 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9356 {
9357   PetscFunctionBegin;
9358   PetscCall(PetscMemzero(info,sizeof(MatFactorInfo)));
9359   PetscFunctionReturn(0);
9360 }
9361 
9362 /*@
9363    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9364 
9365    Collective on Mat
9366 
9367    Input Parameters:
9368 +  mat - the factored matrix
9369 -  is - the index set defining the Schur indices (0-based)
9370 
9371    Notes:
9372     Call MatFactorSolveSchurComplement() or MatFactorSolveSchurComplementTranspose() after this call to solve a Schur complement system.
9373 
9374    You can call MatFactorGetSchurComplement() or MatFactorCreateSchurComplement() after this call.
9375 
9376    Level: developer
9377 
9378 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9379           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`
9380 
9381 @*/
9382 PetscErrorCode MatFactorSetSchurIS(Mat mat,IS is)
9383 {
9384   PetscErrorCode (*f)(Mat,IS);
9385 
9386   PetscFunctionBegin;
9387   PetscValidType(mat,1);
9388   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9389   PetscValidType(is,2);
9390   PetscValidHeaderSpecific(is,IS_CLASSID,2);
9391   PetscCheckSameComm(mat,1,is,2);
9392   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
9393   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorSetSchurIS_C",&f));
9394   PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9395   PetscCall(MatDestroy(&mat->schur));
9396   PetscCall((*f)(mat,is));
9397   PetscCheck(mat->schur,PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Schur complement has not been created");
9398   PetscFunctionReturn(0);
9399 }
9400 
9401 /*@
9402   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9403 
9404    Logically Collective on Mat
9405 
9406    Input Parameters:
9407 +  F - the factored matrix obtained by calling MatGetFactor() from PETSc-MUMPS interface
9408 .  S - location where to return the Schur complement, can be NULL
9409 -  status - the status of the Schur complement matrix, can be NULL
9410 
9411    Notes:
9412    You must call MatFactorSetSchurIS() before calling this routine.
9413 
9414    The routine provides a copy of the Schur matrix stored within the solver data structures.
9415    The caller must destroy the object when it is no longer needed.
9416    If MatFactorInvertSchurComplement() has been called, the routine gets back the inverse.
9417 
9418    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)
9419 
9420    Developer Notes:
9421     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9422    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9423 
9424    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9425 
9426    Level: advanced
9427 
9428    References:
9429 
9430 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`
9431 @*/
9432 PetscErrorCode MatFactorCreateSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9433 {
9434   PetscFunctionBegin;
9435   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9436   if (S) PetscValidPointer(S,2);
9437   if (status) PetscValidPointer(status,3);
9438   if (S) {
9439     PetscErrorCode (*f)(Mat,Mat*);
9440 
9441     PetscCall(PetscObjectQueryFunction((PetscObject)F,"MatFactorCreateSchurComplement_C",&f));
9442     if (f) {
9443       PetscCall((*f)(F,S));
9444     } else {
9445       PetscCall(MatDuplicate(F->schur,MAT_COPY_VALUES,S));
9446     }
9447   }
9448   if (status) *status = F->schur_status;
9449   PetscFunctionReturn(0);
9450 }
9451 
9452 /*@
9453   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9454 
9455    Logically Collective on Mat
9456 
9457    Input Parameters:
9458 +  F - the factored matrix obtained by calling MatGetFactor()
9459 .  *S - location where to return the Schur complement, can be NULL
9460 -  status - the status of the Schur complement matrix, can be NULL
9461 
9462    Notes:
9463    You must call MatFactorSetSchurIS() before calling this routine.
9464 
9465    Schur complement mode is currently implemented for sequential matrices.
9466    The routine returns a the Schur Complement stored within the data strutures of the solver.
9467    If MatFactorInvertSchurComplement() has previously been called, the returned matrix is actually the inverse of the Schur complement.
9468    The returned matrix should not be destroyed; the caller should call MatFactorRestoreSchurComplement() when the object is no longer needed.
9469 
9470    Use MatFactorCreateSchurComplement() to create a copy of the Schur complement matrix that is within a factored matrix
9471 
9472    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9473 
9474    Level: advanced
9475 
9476    References:
9477 
9478 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9479 @*/
9480 PetscErrorCode MatFactorGetSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9481 {
9482   PetscFunctionBegin;
9483   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9484   if (S) PetscValidPointer(S,2);
9485   if (status) PetscValidPointer(status,3);
9486   if (S) *S = F->schur;
9487   if (status) *status = F->schur_status;
9488   PetscFunctionReturn(0);
9489 }
9490 
9491 /*@
9492   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to MatFactorGetSchurComplement
9493 
9494    Logically Collective on Mat
9495 
9496    Input Parameters:
9497 +  F - the factored matrix obtained by calling MatGetFactor()
9498 .  *S - location where the Schur complement is stored
9499 -  status - the status of the Schur complement matrix (see MatFactorSchurStatus)
9500 
9501    Notes:
9502 
9503    Level: advanced
9504 
9505    References:
9506 
9507 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9508 @*/
9509 PetscErrorCode MatFactorRestoreSchurComplement(Mat F,Mat* S,MatFactorSchurStatus status)
9510 {
9511   PetscFunctionBegin;
9512   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9513   if (S) {
9514     PetscValidHeaderSpecific(*S,MAT_CLASSID,2);
9515     *S = NULL;
9516   }
9517   F->schur_status = status;
9518   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9519   PetscFunctionReturn(0);
9520 }
9521 
9522 /*@
9523   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9524 
9525    Logically Collective on Mat
9526 
9527    Input Parameters:
9528 +  F - the factored matrix obtained by calling MatGetFactor()
9529 .  rhs - location where the right hand side of the Schur complement system is stored
9530 -  sol - location where the solution of the Schur complement system has to be returned
9531 
9532    Notes:
9533    The sizes of the vectors should match the size of the Schur complement
9534 
9535    Must be called after MatFactorSetSchurIS()
9536 
9537    Level: advanced
9538 
9539    References:
9540 
9541 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9542 @*/
9543 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9544 {
9545   PetscFunctionBegin;
9546   PetscValidType(F,1);
9547   PetscValidType(rhs,2);
9548   PetscValidType(sol,3);
9549   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9550   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9551   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9552   PetscCheckSameComm(F,1,rhs,2);
9553   PetscCheckSameComm(F,1,sol,3);
9554   PetscCall(MatFactorFactorizeSchurComplement(F));
9555   switch (F->schur_status) {
9556   case MAT_FACTOR_SCHUR_FACTORED:
9557     PetscCall(MatSolveTranspose(F->schur,rhs,sol));
9558     break;
9559   case MAT_FACTOR_SCHUR_INVERTED:
9560     PetscCall(MatMultTranspose(F->schur,rhs,sol));
9561     break;
9562   default:
9563     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9564   }
9565   PetscFunctionReturn(0);
9566 }
9567 
9568 /*@
9569   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9570 
9571    Logically Collective on Mat
9572 
9573    Input Parameters:
9574 +  F - the factored matrix obtained by calling MatGetFactor()
9575 .  rhs - location where the right hand side of the Schur complement system is stored
9576 -  sol - location where the solution of the Schur complement system has to be returned
9577 
9578    Notes:
9579    The sizes of the vectors should match the size of the Schur complement
9580 
9581    Must be called after MatFactorSetSchurIS()
9582 
9583    Level: advanced
9584 
9585    References:
9586 
9587 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9588 @*/
9589 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9590 {
9591   PetscFunctionBegin;
9592   PetscValidType(F,1);
9593   PetscValidType(rhs,2);
9594   PetscValidType(sol,3);
9595   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9596   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9597   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9598   PetscCheckSameComm(F,1,rhs,2);
9599   PetscCheckSameComm(F,1,sol,3);
9600   PetscCall(MatFactorFactorizeSchurComplement(F));
9601   switch (F->schur_status) {
9602   case MAT_FACTOR_SCHUR_FACTORED:
9603     PetscCall(MatSolve(F->schur,rhs,sol));
9604     break;
9605   case MAT_FACTOR_SCHUR_INVERTED:
9606     PetscCall(MatMult(F->schur,rhs,sol));
9607     break;
9608   default:
9609     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9610   }
9611   PetscFunctionReturn(0);
9612 }
9613 
9614 /*@
9615   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9616 
9617    Logically Collective on Mat
9618 
9619    Input Parameters:
9620 .  F - the factored matrix obtained by calling MatGetFactor()
9621 
9622    Notes:
9623     Must be called after MatFactorSetSchurIS().
9624 
9625    Call MatFactorGetSchurComplement() or  MatFactorCreateSchurComplement() AFTER this call to actually compute the inverse and get access to it.
9626 
9627    Level: advanced
9628 
9629    References:
9630 
9631 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9632 @*/
9633 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9634 {
9635   PetscFunctionBegin;
9636   PetscValidType(F,1);
9637   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9638   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9639   PetscCall(MatFactorFactorizeSchurComplement(F));
9640   PetscCall(MatFactorInvertSchurComplement_Private(F));
9641   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9642   PetscFunctionReturn(0);
9643 }
9644 
9645 /*@
9646   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9647 
9648    Logically Collective on Mat
9649 
9650    Input Parameters:
9651 .  F - the factored matrix obtained by calling MatGetFactor()
9652 
9653    Notes:
9654     Must be called after MatFactorSetSchurIS().
9655 
9656    Level: advanced
9657 
9658    References:
9659 
9660 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9661 @*/
9662 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9663 {
9664   PetscFunctionBegin;
9665   PetscValidType(F,1);
9666   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9667   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9668   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9669   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9670   PetscFunctionReturn(0);
9671 }
9672 
9673 /*@
9674    MatPtAP - Creates the matrix product C = P^T * A * P
9675 
9676    Neighbor-wise Collective on Mat
9677 
9678    Input Parameters:
9679 +  A - the matrix
9680 .  P - the projection matrix
9681 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9682 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use PETSC_DEFAULT if you do not have a good estimate
9683           if the result is a dense matrix this is irrelevant
9684 
9685    Output Parameters:
9686 .  C - the product matrix
9687 
9688    Notes:
9689    C will be created and must be destroyed by the user with MatDestroy().
9690 
9691    For matrix types without special implementation the function fallbacks to MatMatMult() followed by MatTransposeMatMult().
9692 
9693    Level: intermediate
9694 
9695 .seealso: `MatMatMult()`, `MatRARt()`
9696 @*/
9697 PetscErrorCode MatPtAP(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
9698 {
9699   PetscFunctionBegin;
9700   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9701   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9702 
9703   if (scall == MAT_INITIAL_MATRIX) {
9704     PetscCall(MatProductCreate(A,P,NULL,C));
9705     PetscCall(MatProductSetType(*C,MATPRODUCT_PtAP));
9706     PetscCall(MatProductSetAlgorithm(*C,"default"));
9707     PetscCall(MatProductSetFill(*C,fill));
9708 
9709     (*C)->product->api_user = PETSC_TRUE;
9710     PetscCall(MatProductSetFromOptions(*C));
9711     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);
9712     PetscCall(MatProductSymbolic(*C));
9713   } else { /* scall == MAT_REUSE_MATRIX */
9714     PetscCall(MatProductReplaceMats(A,P,NULL,*C));
9715   }
9716 
9717   PetscCall(MatProductNumeric(*C));
9718   if (A->symmetric) {
9719     if (A->spd) {
9720       PetscCall(MatSetOption(*C,MAT_SPD,PETSC_TRUE));
9721     } else {
9722       PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9723     }
9724   }
9725   PetscFunctionReturn(0);
9726 }
9727 
9728 /*@
9729    MatRARt - Creates the matrix product C = R * A * R^T
9730 
9731    Neighbor-wise Collective on Mat
9732 
9733    Input Parameters:
9734 +  A - the matrix
9735 .  R - the projection matrix
9736 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9737 -  fill - expected fill as ratio of nnz(C)/nnz(A), use PETSC_DEFAULT if you do not have a good estimate
9738           if the result is a dense matrix this is irrelevant
9739 
9740    Output Parameters:
9741 .  C - the product matrix
9742 
9743    Notes:
9744    C will be created and must be destroyed by the user with MatDestroy().
9745 
9746    This routine is currently only implemented for pairs of AIJ matrices and classes
9747    which inherit from AIJ. Due to PETSc sparse matrix block row distribution among processes,
9748    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9749    We recommend using MatPtAP().
9750 
9751    Level: intermediate
9752 
9753 .seealso: `MatMatMult()`, `MatPtAP()`
9754 @*/
9755 PetscErrorCode MatRARt(Mat A,Mat R,MatReuse scall,PetscReal fill,Mat *C)
9756 {
9757   PetscFunctionBegin;
9758   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9759   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9760 
9761   if (scall == MAT_INITIAL_MATRIX) {
9762     PetscCall(MatProductCreate(A,R,NULL,C));
9763     PetscCall(MatProductSetType(*C,MATPRODUCT_RARt));
9764     PetscCall(MatProductSetAlgorithm(*C,"default"));
9765     PetscCall(MatProductSetFill(*C,fill));
9766 
9767     (*C)->product->api_user = PETSC_TRUE;
9768     PetscCall(MatProductSetFromOptions(*C));
9769     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);
9770     PetscCall(MatProductSymbolic(*C));
9771   } else { /* scall == MAT_REUSE_MATRIX */
9772     PetscCall(MatProductReplaceMats(A,R,NULL,*C));
9773   }
9774 
9775   PetscCall(MatProductNumeric(*C));
9776   if (A->symmetric_set && A->symmetric) {
9777     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9778   }
9779   PetscFunctionReturn(0);
9780 }
9781 
9782 static PetscErrorCode MatProduct_Private(Mat A,Mat B,MatReuse scall,PetscReal fill,MatProductType ptype, Mat *C)
9783 {
9784   PetscFunctionBegin;
9785   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9786 
9787   if (scall == MAT_INITIAL_MATRIX) {
9788     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n",MatProductTypes[ptype]));
9789     PetscCall(MatProductCreate(A,B,NULL,C));
9790     PetscCall(MatProductSetType(*C,ptype));
9791     PetscCall(MatProductSetAlgorithm(*C,MATPRODUCTALGORITHMDEFAULT));
9792     PetscCall(MatProductSetFill(*C,fill));
9793 
9794     (*C)->product->api_user = PETSC_TRUE;
9795     PetscCall(MatProductSetFromOptions(*C));
9796     PetscCall(MatProductSymbolic(*C));
9797   } else { /* scall == MAT_REUSE_MATRIX */
9798     Mat_Product *product = (*C)->product;
9799     PetscBool isdense;
9800 
9801     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C),&isdense,MATSEQDENSE,MATMPIDENSE,""));
9802     if (isdense && product && product->type != ptype) {
9803       PetscCall(MatProductClear(*C));
9804       product = NULL;
9805     }
9806     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n",product ? "with" : "without",MatProductTypes[ptype]));
9807     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9808       if (isdense) {
9809         PetscCall(MatProductCreate_Private(A,B,NULL,*C));
9810         product = (*C)->product;
9811         product->fill     = fill;
9812         product->api_user = PETSC_TRUE;
9813         product->clear    = PETSC_TRUE;
9814 
9815         PetscCall(MatProductSetType(*C,ptype));
9816         PetscCall(MatProductSetFromOptions(*C));
9817         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);
9818         PetscCall(MatProductSymbolic(*C));
9819       } else SETERRQ(PetscObjectComm((PetscObject)(*C)),PETSC_ERR_SUP,"Call MatProductCreate() first");
9820     } else { /* user may change input matrices A or B when REUSE */
9821       PetscCall(MatProductReplaceMats(A,B,NULL,*C));
9822     }
9823   }
9824   PetscCall(MatProductNumeric(*C));
9825   PetscFunctionReturn(0);
9826 }
9827 
9828 /*@
9829    MatMatMult - Performs Matrix-Matrix Multiplication C=A*B.
9830 
9831    Neighbor-wise Collective on Mat
9832 
9833    Input Parameters:
9834 +  A - the left matrix
9835 .  B - the right matrix
9836 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9837 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if you do not have a good estimate
9838           if the result is a dense matrix this is irrelevant
9839 
9840    Output Parameters:
9841 .  C - the product matrix
9842 
9843    Notes:
9844    Unless scall is MAT_REUSE_MATRIX C will be created.
9845 
9846    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
9847    call to this function with MAT_INITIAL_MATRIX.
9848 
9849    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9850 
9851    If you have many matrices with the same non-zero structure to multiply, you should use MatProductCreate()/MatProductSymbolic()/MatProductReplaceMats(), and call MatProductNumeric() repeatedly.
9852 
9853    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.
9854 
9855    Example of Usage:
9856 .vb
9857      MatProductCreate(A,B,NULL,&C);
9858      MatProductSetType(C,MATPRODUCT_AB);
9859      MatProductSymbolic(C);
9860      MatProductNumeric(C); // compute C=A * B
9861      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9862      MatProductNumeric(C);
9863      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9864      MatProductNumeric(C);
9865 .ve
9866 
9867    Level: intermediate
9868 
9869 .seealso: `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9870 @*/
9871 PetscErrorCode MatMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9872 {
9873   PetscFunctionBegin;
9874   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AB,C));
9875   PetscFunctionReturn(0);
9876 }
9877 
9878 /*@
9879    MatMatTransposeMult - Performs Matrix-Matrix Multiplication C=A*B^T.
9880 
9881    Neighbor-wise Collective on Mat
9882 
9883    Input Parameters:
9884 +  A - the left matrix
9885 .  B - the right matrix
9886 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9887 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9888 
9889    Output Parameters:
9890 .  C - the product matrix
9891 
9892    Notes:
9893    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9894 
9895    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9896 
9897   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9898    actually needed.
9899 
9900    This routine is currently only implemented for pairs of SeqAIJ matrices, for the SeqDense class,
9901    and for pairs of MPIDense matrices.
9902 
9903    Options Database Keys:
9904 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for MPIDense matrices: the
9905               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9906               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9907 
9908    Level: intermediate
9909 
9910 .seealso: `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`
9911 @*/
9912 PetscErrorCode MatMatTransposeMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9913 {
9914   PetscFunctionBegin;
9915   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_ABt,C));
9916   if (A == B) {
9917     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9918   }
9919   PetscFunctionReturn(0);
9920 }
9921 
9922 /*@
9923    MatTransposeMatMult - Performs Matrix-Matrix Multiplication C=A^T*B.
9924 
9925    Neighbor-wise Collective on Mat
9926 
9927    Input Parameters:
9928 +  A - the left matrix
9929 .  B - the right matrix
9930 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9931 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9932 
9933    Output Parameters:
9934 .  C - the product matrix
9935 
9936    Notes:
9937    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9938 
9939    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9940 
9941   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9942    actually needed.
9943 
9944    This routine is currently implemented for pairs of AIJ matrices and pairs of SeqDense matrices and classes
9945    which inherit from SeqAIJ.  C will be of the same type as the input matrices.
9946 
9947    Level: intermediate
9948 
9949 .seealso: `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9950 @*/
9951 PetscErrorCode MatTransposeMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9952 {
9953   PetscFunctionBegin;
9954   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AtB,C));
9955   PetscFunctionReturn(0);
9956 }
9957 
9958 /*@
9959    MatMatMatMult - Performs Matrix-Matrix-Matrix Multiplication D=A*B*C.
9960 
9961    Neighbor-wise Collective on Mat
9962 
9963    Input Parameters:
9964 +  A - the left matrix
9965 .  B - the middle matrix
9966 .  C - the right matrix
9967 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9968 -  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
9969           if the result is a dense matrix this is irrelevant
9970 
9971    Output Parameters:
9972 .  D - the product matrix
9973 
9974    Notes:
9975    Unless scall is MAT_REUSE_MATRIX D will be created.
9976 
9977    MAT_REUSE_MATRIX can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9978 
9979    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9980    actually needed.
9981 
9982    If you have many matrices with the same non-zero structure to multiply, you
9983    should use MAT_REUSE_MATRIX in all calls but the first
9984 
9985    Level: intermediate
9986 
9987 .seealso: `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9988 @*/
9989 PetscErrorCode MatMatMatMult(Mat A,Mat B,Mat C,MatReuse scall,PetscReal fill,Mat *D)
9990 {
9991   PetscFunctionBegin;
9992   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D,6);
9993   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9994 
9995   if (scall == MAT_INITIAL_MATRIX) {
9996     PetscCall(MatProductCreate(A,B,C,D));
9997     PetscCall(MatProductSetType(*D,MATPRODUCT_ABC));
9998     PetscCall(MatProductSetAlgorithm(*D,"default"));
9999     PetscCall(MatProductSetFill(*D,fill));
10000 
10001     (*D)->product->api_user = PETSC_TRUE;
10002     PetscCall(MatProductSetFromOptions(*D));
10003     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);
10004     PetscCall(MatProductSymbolic(*D));
10005   } else { /* user may change input matrices when REUSE */
10006     PetscCall(MatProductReplaceMats(A,B,C,*D));
10007   }
10008   PetscCall(MatProductNumeric(*D));
10009   PetscFunctionReturn(0);
10010 }
10011 
10012 /*@
10013    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10014 
10015    Collective on Mat
10016 
10017    Input Parameters:
10018 +  mat - the matrix
10019 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10020 .  subcomm - MPI communicator split from the communicator where mat resides in (or MPI_COMM_NULL if nsubcomm is used)
10021 -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10022 
10023    Output Parameter:
10024 .  matredundant - redundant matrix
10025 
10026    Notes:
10027    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
10028    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10029 
10030    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10031    calling it.
10032 
10033    Level: advanced
10034 
10035 .seealso: `MatDestroy()`
10036 @*/
10037 PetscErrorCode MatCreateRedundantMatrix(Mat mat,PetscInt nsubcomm,MPI_Comm subcomm,MatReuse reuse,Mat *matredundant)
10038 {
10039   MPI_Comm       comm;
10040   PetscMPIInt    size;
10041   PetscInt       mloc_sub,nloc_sub,rstart,rend,M=mat->rmap->N,N=mat->cmap->N,bs=mat->rmap->bs;
10042   Mat_Redundant  *redund=NULL;
10043   PetscSubcomm   psubcomm=NULL;
10044   MPI_Comm       subcomm_in=subcomm;
10045   Mat            *matseq;
10046   IS             isrow,iscol;
10047   PetscBool      newsubcomm=PETSC_FALSE;
10048 
10049   PetscFunctionBegin;
10050   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10051   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10052     PetscValidPointer(*matredundant,5);
10053     PetscValidHeaderSpecific(*matredundant,MAT_CLASSID,5);
10054   }
10055 
10056   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10057   if (size == 1 || nsubcomm == 1) {
10058     if (reuse == MAT_INITIAL_MATRIX) {
10059       PetscCall(MatDuplicate(mat,MAT_COPY_VALUES,matredundant));
10060     } else {
10061       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");
10062       PetscCall(MatCopy(mat,*matredundant,SAME_NONZERO_PATTERN));
10063     }
10064     PetscFunctionReturn(0);
10065   }
10066 
10067   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10068   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10069   MatCheckPreallocated(mat,1);
10070 
10071   PetscCall(PetscLogEventBegin(MAT_RedundantMat,mat,0,0,0));
10072   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10073     /* create psubcomm, then get subcomm */
10074     PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10075     PetscCallMPI(MPI_Comm_size(comm,&size));
10076     PetscCheck(nsubcomm >= 1 && nsubcomm <= size,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"nsubcomm must between 1 and %d",size);
10077 
10078     PetscCall(PetscSubcommCreate(comm,&psubcomm));
10079     PetscCall(PetscSubcommSetNumber(psubcomm,nsubcomm));
10080     PetscCall(PetscSubcommSetType(psubcomm,PETSC_SUBCOMM_CONTIGUOUS));
10081     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10082     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm),&subcomm,NULL));
10083     newsubcomm = PETSC_TRUE;
10084     PetscCall(PetscSubcommDestroy(&psubcomm));
10085   }
10086 
10087   /* get isrow, iscol and a local sequential matrix matseq[0] */
10088   if (reuse == MAT_INITIAL_MATRIX) {
10089     mloc_sub = PETSC_DECIDE;
10090     nloc_sub = PETSC_DECIDE;
10091     if (bs < 1) {
10092       PetscCall(PetscSplitOwnership(subcomm,&mloc_sub,&M));
10093       PetscCall(PetscSplitOwnership(subcomm,&nloc_sub,&N));
10094     } else {
10095       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&mloc_sub,&M));
10096       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&nloc_sub,&N));
10097     }
10098     PetscCallMPI(MPI_Scan(&mloc_sub,&rend,1,MPIU_INT,MPI_SUM,subcomm));
10099     rstart = rend - mloc_sub;
10100     PetscCall(ISCreateStride(PETSC_COMM_SELF,mloc_sub,rstart,1,&isrow));
10101     PetscCall(ISCreateStride(PETSC_COMM_SELF,N,0,1,&iscol));
10102   } else { /* reuse == MAT_REUSE_MATRIX */
10103     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");
10104     /* retrieve subcomm */
10105     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant),&subcomm));
10106     redund = (*matredundant)->redundant;
10107     isrow  = redund->isrow;
10108     iscol  = redund->iscol;
10109     matseq = redund->matseq;
10110   }
10111   PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscol,reuse,&matseq));
10112 
10113   /* get matredundant over subcomm */
10114   if (reuse == MAT_INITIAL_MATRIX) {
10115     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],nloc_sub,reuse,matredundant));
10116 
10117     /* create a supporting struct and attach it to C for reuse */
10118     PetscCall(PetscNewLog(*matredundant,&redund));
10119     (*matredundant)->redundant = redund;
10120     redund->isrow              = isrow;
10121     redund->iscol              = iscol;
10122     redund->matseq             = matseq;
10123     if (newsubcomm) {
10124       redund->subcomm          = subcomm;
10125     } else {
10126       redund->subcomm          = MPI_COMM_NULL;
10127     }
10128   } else {
10129     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],PETSC_DECIDE,reuse,matredundant));
10130   }
10131 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
10132   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10133     PetscCall(MatBindToCPU(*matredundant,PETSC_TRUE));
10134     PetscCall(MatSetBindingPropagates(*matredundant,PETSC_TRUE));
10135   }
10136 #endif
10137   PetscCall(PetscLogEventEnd(MAT_RedundantMat,mat,0,0,0));
10138   PetscFunctionReturn(0);
10139 }
10140 
10141 /*@C
10142    MatGetMultiProcBlock - Create multiple [bjacobi] 'parallel submatrices' from
10143    a given 'mat' object. Each submatrix can span multiple procs.
10144 
10145    Collective on Mat
10146 
10147    Input Parameters:
10148 +  mat - the matrix
10149 .  subcomm - the subcommunicator obtained by com_split(comm)
10150 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10151 
10152    Output Parameter:
10153 .  subMat - 'parallel submatrices each spans a given subcomm
10154 
10155   Notes:
10156   The submatrix partition across processors is dictated by 'subComm' a
10157   communicator obtained by MPI_comm_split(). The subComm
10158   is not restriced to be grouped with consecutive original ranks.
10159 
10160   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10161   map directly to the layout of the original matrix [wrt the local
10162   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10163   into the 'DiagonalMat' of the subMat, hence it is used directly from
10164   the subMat. However the offDiagMat looses some columns - and this is
10165   reconstructed with MatSetValues()
10166 
10167   Level: advanced
10168 
10169 .seealso: `MatCreateSubMatrices()`
10170 @*/
10171 PetscErrorCode   MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall,Mat *subMat)
10172 {
10173   PetscMPIInt    commsize,subCommSize;
10174 
10175   PetscFunctionBegin;
10176   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&commsize));
10177   PetscCallMPI(MPI_Comm_size(subComm,&subCommSize));
10178   PetscCheck(subCommSize <= commsize,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"CommSize %d < SubCommZize %d",commsize,subCommSize);
10179 
10180   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");
10181   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock,mat,0,0,0));
10182   PetscCall((*mat->ops->getmultiprocblock)(mat,subComm,scall,subMat));
10183   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock,mat,0,0,0));
10184   PetscFunctionReturn(0);
10185 }
10186 
10187 /*@
10188    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10189 
10190    Not Collective
10191 
10192    Input Parameters:
10193 +  mat - matrix to extract local submatrix from
10194 .  isrow - local row indices for submatrix
10195 -  iscol - local column indices for submatrix
10196 
10197    Output Parameter:
10198 .  submat - the submatrix
10199 
10200    Level: intermediate
10201 
10202    Notes:
10203    The submat should be returned with MatRestoreLocalSubMatrix().
10204 
10205    Depending on the format of mat, the returned submat may not implement MatMult().  Its communicator may be
10206    the same as mat, it may be PETSC_COMM_SELF, or some other subcomm of mat's.
10207 
10208    The submat always implements MatSetValuesLocal().  If isrow and iscol have the same block size, then
10209    MatSetValuesBlockedLocal() will also be implemented.
10210 
10211    The mat must have had a ISLocalToGlobalMapping provided to it with MatSetLocalToGlobalMapping(). Note that
10212    matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10213 
10214 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10215 @*/
10216 PetscErrorCode MatGetLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10217 {
10218   PetscFunctionBegin;
10219   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10220   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10221   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10222   PetscCheckSameComm(isrow,2,iscol,3);
10223   PetscValidPointer(submat,4);
10224   PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must have local to global mapping provided before this call");
10225 
10226   if (mat->ops->getlocalsubmatrix) {
10227     PetscCall((*mat->ops->getlocalsubmatrix)(mat,isrow,iscol,submat));
10228   } else {
10229     PetscCall(MatCreateLocalRef(mat,isrow,iscol,submat));
10230   }
10231   PetscFunctionReturn(0);
10232 }
10233 
10234 /*@
10235    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering
10236 
10237    Not Collective
10238 
10239    Input Parameters:
10240 +  mat - matrix to extract local submatrix from
10241 .  isrow - local row indices for submatrix
10242 .  iscol - local column indices for submatrix
10243 -  submat - the submatrix
10244 
10245    Level: intermediate
10246 
10247 .seealso: `MatGetLocalSubMatrix()`
10248 @*/
10249 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10250 {
10251   PetscFunctionBegin;
10252   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10253   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10254   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10255   PetscCheckSameComm(isrow,2,iscol,3);
10256   PetscValidPointer(submat,4);
10257   if (*submat) {
10258     PetscValidHeaderSpecific(*submat,MAT_CLASSID,4);
10259   }
10260 
10261   if (mat->ops->restorelocalsubmatrix) {
10262     PetscCall((*mat->ops->restorelocalsubmatrix)(mat,isrow,iscol,submat));
10263   } else {
10264     PetscCall(MatDestroy(submat));
10265   }
10266   *submat = NULL;
10267   PetscFunctionReturn(0);
10268 }
10269 
10270 /* --------------------------------------------------------*/
10271 /*@
10272    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10273 
10274    Collective on Mat
10275 
10276    Input Parameter:
10277 .  mat - the matrix
10278 
10279    Output Parameter:
10280 .  is - if any rows have zero diagonals this contains the list of them
10281 
10282    Level: developer
10283 
10284 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10285 @*/
10286 PetscErrorCode MatFindZeroDiagonals(Mat mat,IS *is)
10287 {
10288   PetscFunctionBegin;
10289   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10290   PetscValidType(mat,1);
10291   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10292   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10293 
10294   if (!mat->ops->findzerodiagonals) {
10295     Vec                diag;
10296     const PetscScalar *a;
10297     PetscInt          *rows;
10298     PetscInt           rStart, rEnd, r, nrow = 0;
10299 
10300     PetscCall(MatCreateVecs(mat, &diag, NULL));
10301     PetscCall(MatGetDiagonal(mat, diag));
10302     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10303     PetscCall(VecGetArrayRead(diag, &a));
10304     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) ++nrow;
10305     PetscCall(PetscMalloc1(nrow, &rows));
10306     nrow = 0;
10307     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) rows[nrow++] = r+rStart;
10308     PetscCall(VecRestoreArrayRead(diag, &a));
10309     PetscCall(VecDestroy(&diag));
10310     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) mat), nrow, rows, PETSC_OWN_POINTER, is));
10311   } else {
10312     PetscCall((*mat->ops->findzerodiagonals)(mat, is));
10313   }
10314   PetscFunctionReturn(0);
10315 }
10316 
10317 /*@
10318    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10319 
10320    Collective on Mat
10321 
10322    Input Parameter:
10323 .  mat - the matrix
10324 
10325    Output Parameter:
10326 .  is - contains the list of rows with off block diagonal entries
10327 
10328    Level: developer
10329 
10330 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10331 @*/
10332 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat,IS *is)
10333 {
10334   PetscFunctionBegin;
10335   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10336   PetscValidType(mat,1);
10337   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10338   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10339 
10340   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);
10341   PetscCall((*mat->ops->findoffblockdiagonalentries)(mat,is));
10342   PetscFunctionReturn(0);
10343 }
10344 
10345 /*@C
10346   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10347 
10348   Collective on Mat
10349 
10350   Input Parameters:
10351 . mat - the matrix
10352 
10353   Output Parameters:
10354 . values - the block inverses in column major order (FORTRAN-like)
10355 
10356    Note:
10357      The size of the blocks is determined by the block size of the matrix.
10358 
10359    Fortran Note:
10360      This routine is not available from Fortran.
10361 
10362   Level: advanced
10363 
10364 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10365 @*/
10366 PetscErrorCode MatInvertBlockDiagonal(Mat mat,const PetscScalar **values)
10367 {
10368   PetscFunctionBegin;
10369   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10370   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10371   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10372   PetscCheck(mat->ops->invertblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10373   PetscCall((*mat->ops->invertblockdiagonal)(mat,values));
10374   PetscFunctionReturn(0);
10375 }
10376 
10377 /*@C
10378   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10379 
10380   Collective on Mat
10381 
10382   Input Parameters:
10383 + mat - the matrix
10384 . nblocks - the number of blocks on the process, set with MatSetVariableBlockSizes()
10385 - bsizes - the size of each block on the process, set with MatSetVariableBlockSizes()
10386 
10387   Output Parameters:
10388 . values - the block inverses in column major order (FORTRAN-like)
10389 
10390    Note:
10391    This routine is not available from Fortran.
10392 
10393   Level: advanced
10394 
10395 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10396 @*/
10397 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *values)
10398 {
10399   PetscFunctionBegin;
10400   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10401   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10402   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10403   PetscCheck(mat->ops->invertvariableblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10404   PetscCall((*mat->ops->invertvariableblockdiagonal)(mat,nblocks,bsizes,values));
10405   PetscFunctionReturn(0);
10406 }
10407 
10408 /*@
10409   MatInvertBlockDiagonalMat - set matrix C to be the inverted block diagonal of matrix A
10410 
10411   Collective on Mat
10412 
10413   Input Parameters:
10414 . A - the matrix
10415 
10416   Output Parameters:
10417 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10418 
10419   Notes: the blocksize of the matrix is used to determine the blocks on the diagonal of C
10420 
10421   Level: advanced
10422 
10423 .seealso: `MatInvertBlockDiagonal()`
10424 @*/
10425 PetscErrorCode MatInvertBlockDiagonalMat(Mat A,Mat C)
10426 {
10427   const PetscScalar *vals;
10428   PetscInt          *dnnz;
10429   PetscInt           m,rstart,rend,bs,i,j;
10430 
10431   PetscFunctionBegin;
10432   PetscCall(MatInvertBlockDiagonal(A,&vals));
10433   PetscCall(MatGetBlockSize(A,&bs));
10434   PetscCall(MatGetLocalSize(A,&m,NULL));
10435   PetscCall(MatSetLayouts(C,A->rmap,A->cmap));
10436   PetscCall(PetscMalloc1(m/bs,&dnnz));
10437   for (j = 0; j < m/bs; j++) dnnz[j] = 1;
10438   PetscCall(MatXAIJSetPreallocation(C,bs,dnnz,NULL,NULL,NULL));
10439   PetscCall(PetscFree(dnnz));
10440   PetscCall(MatGetOwnershipRange(C,&rstart,&rend));
10441   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_FALSE));
10442   for (i = rstart/bs; i < rend/bs; i++) {
10443     PetscCall(MatSetValuesBlocked(C,1,&i,1,&i,&vals[(i-rstart/bs)*bs*bs],INSERT_VALUES));
10444   }
10445   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
10446   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
10447   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_TRUE));
10448   PetscFunctionReturn(0);
10449 }
10450 
10451 /*@C
10452     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10453     via MatTransposeColoringCreate().
10454 
10455     Collective on MatTransposeColoring
10456 
10457     Input Parameter:
10458 .   c - coloring context
10459 
10460     Level: intermediate
10461 
10462 .seealso: `MatTransposeColoringCreate()`
10463 @*/
10464 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10465 {
10466   MatTransposeColoring matcolor=*c;
10467 
10468   PetscFunctionBegin;
10469   if (!matcolor) PetscFunctionReturn(0);
10470   if (--((PetscObject)matcolor)->refct > 0) {matcolor = NULL; PetscFunctionReturn(0);}
10471 
10472   PetscCall(PetscFree3(matcolor->ncolumns,matcolor->nrows,matcolor->colorforrow));
10473   PetscCall(PetscFree(matcolor->rows));
10474   PetscCall(PetscFree(matcolor->den2sp));
10475   PetscCall(PetscFree(matcolor->colorforcol));
10476   PetscCall(PetscFree(matcolor->columns));
10477   if (matcolor->brows>0) {
10478     PetscCall(PetscFree(matcolor->lstart));
10479   }
10480   PetscCall(PetscHeaderDestroy(c));
10481   PetscFunctionReturn(0);
10482 }
10483 
10484 /*@C
10485     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10486     a MatTransposeColoring context has been created, computes a dense B^T by Apply
10487     MatTransposeColoring to sparse B.
10488 
10489     Collective on MatTransposeColoring
10490 
10491     Input Parameters:
10492 +   B - sparse matrix B
10493 .   Btdense - symbolic dense matrix B^T
10494 -   coloring - coloring context created with MatTransposeColoringCreate()
10495 
10496     Output Parameter:
10497 .   Btdense - dense matrix B^T
10498 
10499     Level: advanced
10500 
10501      Notes:
10502     These are used internally for some implementations of MatRARt()
10503 
10504 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10505 
10506 @*/
10507 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring,Mat B,Mat Btdense)
10508 {
10509   PetscFunctionBegin;
10510   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10511   PetscValidHeaderSpecific(Btdense,MAT_CLASSID,3);
10512   PetscValidHeaderSpecific(coloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10513 
10514   PetscCheck(B->ops->transcoloringapplysptoden,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)B)->type_name);
10515   PetscCall((B->ops->transcoloringapplysptoden)(coloring,B,Btdense));
10516   PetscFunctionReturn(0);
10517 }
10518 
10519 /*@C
10520     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10521     a MatTransposeColoring context has been created and a dense matrix Cden=A*Btdense
10522     in which Btdens is obtained from MatTransColoringApplySpToDen(), recover sparse matrix
10523     Csp from Cden.
10524 
10525     Collective on MatTransposeColoring
10526 
10527     Input Parameters:
10528 +   coloring - coloring context created with MatTransposeColoringCreate()
10529 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10530 
10531     Output Parameter:
10532 .   Csp - sparse matrix
10533 
10534     Level: advanced
10535 
10536      Notes:
10537     These are used internally for some implementations of MatRARt()
10538 
10539 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10540 
10541 @*/
10542 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring,Mat Cden,Mat Csp)
10543 {
10544   PetscFunctionBegin;
10545   PetscValidHeaderSpecific(matcoloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10546   PetscValidHeaderSpecific(Cden,MAT_CLASSID,2);
10547   PetscValidHeaderSpecific(Csp,MAT_CLASSID,3);
10548 
10549   PetscCheck(Csp->ops->transcoloringapplydentosp,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)Csp)->type_name);
10550   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring,Cden,Csp));
10551   PetscCall(MatAssemblyBegin(Csp,MAT_FINAL_ASSEMBLY));
10552   PetscCall(MatAssemblyEnd(Csp,MAT_FINAL_ASSEMBLY));
10553   PetscFunctionReturn(0);
10554 }
10555 
10556 /*@C
10557    MatTransposeColoringCreate - Creates a matrix coloring context for matrix product C=A*B^T.
10558 
10559    Collective on Mat
10560 
10561    Input Parameters:
10562 +  mat - the matrix product C
10563 -  iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring()
10564 
10565     Output Parameter:
10566 .   color - the new coloring context
10567 
10568     Level: intermediate
10569 
10570 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10571           `MatTransColoringApplyDenToSp()`
10572 @*/
10573 PetscErrorCode MatTransposeColoringCreate(Mat mat,ISColoring iscoloring,MatTransposeColoring *color)
10574 {
10575   MatTransposeColoring c;
10576   MPI_Comm             comm;
10577 
10578   PetscFunctionBegin;
10579   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate,mat,0,0,0));
10580   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10581   PetscCall(PetscHeaderCreate(c,MAT_TRANSPOSECOLORING_CLASSID,"MatTransposeColoring","Matrix product C=A*B^T via coloring","Mat",comm,MatTransposeColoringDestroy,NULL));
10582 
10583   c->ctype = iscoloring->ctype;
10584   if (mat->ops->transposecoloringcreate) {
10585     PetscCall((*mat->ops->transposecoloringcreate)(mat,iscoloring,c));
10586   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);
10587 
10588   *color = c;
10589   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate,mat,0,0,0));
10590   PetscFunctionReturn(0);
10591 }
10592 
10593 /*@
10594       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10595         matrix has had no new nonzero locations added to the matrix since the previous call then the value will be the
10596         same, otherwise it will be larger
10597 
10598      Not Collective
10599 
10600   Input Parameter:
10601 .    A  - the matrix
10602 
10603   Output Parameter:
10604 .    state - the current state
10605 
10606   Notes:
10607     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10608          different matrices
10609 
10610   Level: intermediate
10611 
10612 @*/
10613 PetscErrorCode MatGetNonzeroState(Mat mat,PetscObjectState *state)
10614 {
10615   PetscFunctionBegin;
10616   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10617   *state = mat->nonzerostate;
10618   PetscFunctionReturn(0);
10619 }
10620 
10621 /*@
10622       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10623                  matrices from each processor
10624 
10625     Collective
10626 
10627    Input Parameters:
10628 +    comm - the communicators the parallel matrix will live on
10629 .    seqmat - the input sequential matrices
10630 .    n - number of local columns (or PETSC_DECIDE)
10631 -    reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10632 
10633    Output Parameter:
10634 .    mpimat - the parallel matrix generated
10635 
10636     Level: advanced
10637 
10638    Notes:
10639     The number of columns of the matrix in EACH processor MUST be the same.
10640 
10641 @*/
10642 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm,Mat seqmat,PetscInt n,MatReuse reuse,Mat *mpimat)
10643 {
10644   PetscFunctionBegin;
10645   PetscCheck(seqmat->ops->creatempimatconcatenateseqmat,PetscObjectComm((PetscObject)seqmat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)seqmat)->type_name);
10646   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");
10647 
10648   PetscCall(PetscLogEventBegin(MAT_Merge,seqmat,0,0,0));
10649   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm,seqmat,n,reuse,mpimat));
10650   PetscCall(PetscLogEventEnd(MAT_Merge,seqmat,0,0,0));
10651   PetscFunctionReturn(0);
10652 }
10653 
10654 /*@
10655      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent
10656                  ranks' ownership ranges.
10657 
10658     Collective on A
10659 
10660    Input Parameters:
10661 +    A   - the matrix to create subdomains from
10662 -    N   - requested number of subdomains
10663 
10664    Output Parameters:
10665 +    n   - number of subdomains resulting on this rank
10666 -    iss - IS list with indices of subdomains on this rank
10667 
10668     Level: advanced
10669 
10670     Notes:
10671     number of subdomains must be smaller than the communicator size
10672 @*/
10673 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A,PetscInt N,PetscInt *n,IS *iss[])
10674 {
10675   MPI_Comm        comm,subcomm;
10676   PetscMPIInt     size,rank,color;
10677   PetscInt        rstart,rend,k;
10678 
10679   PetscFunctionBegin;
10680   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
10681   PetscCallMPI(MPI_Comm_size(comm,&size));
10682   PetscCallMPI(MPI_Comm_rank(comm,&rank));
10683   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);
10684   *n = 1;
10685   k = ((PetscInt)size)/N + ((PetscInt)size%N>0); /* There are up to k ranks to a color */
10686   color = rank/k;
10687   PetscCallMPI(MPI_Comm_split(comm,color,rank,&subcomm));
10688   PetscCall(PetscMalloc1(1,iss));
10689   PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
10690   PetscCall(ISCreateStride(subcomm,rend-rstart,rstart,1,iss[0]));
10691   PetscCallMPI(MPI_Comm_free(&subcomm));
10692   PetscFunctionReturn(0);
10693 }
10694 
10695 /*@
10696    MatGalerkin - Constructs the coarse grid problem via Galerkin projection.
10697 
10698    If the interpolation and restriction operators are the same, uses MatPtAP.
10699    If they are not the same, use MatMatMatMult.
10700 
10701    Once the coarse grid problem is constructed, correct for interpolation operators
10702    that are not of full rank, which can legitimately happen in the case of non-nested
10703    geometric multigrid.
10704 
10705    Input Parameters:
10706 +  restrct - restriction operator
10707 .  dA - fine grid matrix
10708 .  interpolate - interpolation operator
10709 .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10710 -  fill - expected fill, use PETSC_DEFAULT if you do not have a good estimate
10711 
10712    Output Parameters:
10713 .  A - the Galerkin coarse matrix
10714 
10715    Options Database Key:
10716 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10717 
10718    Level: developer
10719 
10720 .seealso: `MatPtAP()`, `MatMatMatMult()`
10721 @*/
10722 PetscErrorCode  MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10723 {
10724   IS             zerorows;
10725   Vec            diag;
10726 
10727   PetscFunctionBegin;
10728   PetscCheck(reuse != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
10729   /* Construct the coarse grid matrix */
10730   if (interpolate == restrct) {
10731     PetscCall(MatPtAP(dA,interpolate,reuse,fill,A));
10732   } else {
10733     PetscCall(MatMatMatMult(restrct,dA,interpolate,reuse,fill,A));
10734   }
10735 
10736   /* If the interpolation matrix is not of full rank, A will have zero rows.
10737      This can legitimately happen in the case of non-nested geometric multigrid.
10738      In that event, we set the rows of the matrix to the rows of the identity,
10739      ignoring the equations (as the RHS will also be zero). */
10740 
10741   PetscCall(MatFindZeroRows(*A, &zerorows));
10742 
10743   if (zerorows != NULL) { /* if there are any zero rows */
10744     PetscCall(MatCreateVecs(*A, &diag, NULL));
10745     PetscCall(MatGetDiagonal(*A, diag));
10746     PetscCall(VecISSet(diag, zerorows, 1.0));
10747     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10748     PetscCall(VecDestroy(&diag));
10749     PetscCall(ISDestroy(&zerorows));
10750   }
10751   PetscFunctionReturn(0);
10752 }
10753 
10754 /*@C
10755     MatSetOperation - Allows user to set a matrix operation for any matrix type
10756 
10757    Logically Collective on Mat
10758 
10759     Input Parameters:
10760 +   mat - the matrix
10761 .   op - the name of the operation
10762 -   f - the function that provides the operation
10763 
10764    Level: developer
10765 
10766     Usage:
10767 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10768 $      PetscCall(MatCreateXXX(comm,...&A);
10769 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10770 
10771     Notes:
10772     See the file include/petscmat.h for a complete list of matrix
10773     operations, which all have the form MATOP_<OPERATION>, where
10774     <OPERATION> is the name (in all capital letters) of the
10775     user interface routine (e.g., MatMult() -> MATOP_MULT).
10776 
10777     All user-provided functions (except for MATOP_DESTROY) should have the same calling
10778     sequence as the usual matrix interface routines, since they
10779     are intended to be accessed via the usual matrix interface
10780     routines, e.g.,
10781 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10782 
10783     In particular each function MUST return an error code of 0 on success and
10784     nonzero on failure.
10785 
10786     This routine is distinct from MatShellSetOperation() in that it can be called on any matrix type.
10787 
10788 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10789 @*/
10790 PetscErrorCode MatSetOperation(Mat mat,MatOperation op,void (*f)(void))
10791 {
10792   PetscFunctionBegin;
10793   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10794   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) {
10795     mat->ops->viewnative = mat->ops->view;
10796   }
10797   (((void(**)(void))mat->ops)[op]) = f;
10798   PetscFunctionReturn(0);
10799 }
10800 
10801 /*@C
10802     MatGetOperation - Gets a matrix operation for any matrix type.
10803 
10804     Not Collective
10805 
10806     Input Parameters:
10807 +   mat - the matrix
10808 -   op - the name of the operation
10809 
10810     Output Parameter:
10811 .   f - the function that provides the operation
10812 
10813     Level: developer
10814 
10815     Usage:
10816 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10817 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10818 
10819     Notes:
10820     See the file include/petscmat.h for a complete list of matrix
10821     operations, which all have the form MATOP_<OPERATION>, where
10822     <OPERATION> is the name (in all capital letters) of the
10823     user interface routine (e.g., MatMult() -> MATOP_MULT).
10824 
10825     This routine is distinct from MatShellGetOperation() in that it can be called on any matrix type.
10826 
10827 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10828 @*/
10829 PetscErrorCode MatGetOperation(Mat mat,MatOperation op,void(**f)(void))
10830 {
10831   PetscFunctionBegin;
10832   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10833   *f = (((void (**)(void))mat->ops)[op]);
10834   PetscFunctionReturn(0);
10835 }
10836 
10837 /*@
10838     MatHasOperation - Determines whether the given matrix supports the particular
10839     operation.
10840 
10841    Not Collective
10842 
10843    Input Parameters:
10844 +  mat - the matrix
10845 -  op - the operation, for example, MATOP_GET_DIAGONAL
10846 
10847    Output Parameter:
10848 .  has - either PETSC_TRUE or PETSC_FALSE
10849 
10850    Level: advanced
10851 
10852    Notes:
10853    See the file include/petscmat.h for a complete list of matrix
10854    operations, which all have the form MATOP_<OPERATION>, where
10855    <OPERATION> is the name (in all capital letters) of the
10856    user-level routine.  E.g., MatNorm() -> MATOP_NORM.
10857 
10858 .seealso: `MatCreateShell()`
10859 @*/
10860 PetscErrorCode MatHasOperation(Mat mat,MatOperation op,PetscBool *has)
10861 {
10862   PetscFunctionBegin;
10863   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10864   PetscValidBoolPointer(has,3);
10865   if (mat->ops->hasoperation) {
10866     PetscCall((*mat->ops->hasoperation)(mat,op,has));
10867   } else {
10868     if (((void**)mat->ops)[op]) *has = PETSC_TRUE;
10869     else {
10870       *has = PETSC_FALSE;
10871       if (op == MATOP_CREATE_SUBMATRIX) {
10872         PetscMPIInt size;
10873 
10874         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10875         if (size == 1) {
10876           PetscCall(MatHasOperation(mat,MATOP_CREATE_SUBMATRICES,has));
10877         }
10878       }
10879     }
10880   }
10881   PetscFunctionReturn(0);
10882 }
10883 
10884 /*@
10885     MatHasCongruentLayouts - Determines whether the rows and columns layouts
10886     of the matrix are congruent
10887 
10888    Collective on mat
10889 
10890    Input Parameters:
10891 .  mat - the matrix
10892 
10893    Output Parameter:
10894 .  cong - either PETSC_TRUE or PETSC_FALSE
10895 
10896    Level: beginner
10897 
10898    Notes:
10899 
10900 .seealso: `MatCreate()`, `MatSetSizes()`
10901 @*/
10902 PetscErrorCode MatHasCongruentLayouts(Mat mat,PetscBool *cong)
10903 {
10904   PetscFunctionBegin;
10905   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10906   PetscValidType(mat,1);
10907   PetscValidBoolPointer(cong,2);
10908   if (!mat->rmap || !mat->cmap) {
10909     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10910     PetscFunctionReturn(0);
10911   }
10912   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10913     PetscCall(PetscLayoutSetUp(mat->rmap));
10914     PetscCall(PetscLayoutSetUp(mat->cmap));
10915     PetscCall(PetscLayoutCompare(mat->rmap,mat->cmap,cong));
10916     if (*cong) mat->congruentlayouts = 1;
10917     else       mat->congruentlayouts = 0;
10918   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10919   PetscFunctionReturn(0);
10920 }
10921 
10922 PetscErrorCode MatSetInf(Mat A)
10923 {
10924   PetscFunctionBegin;
10925   PetscCheck(A->ops->setinf,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10926   PetscCall((*A->ops->setinf)(A));
10927   PetscFunctionReturn(0);
10928 }
10929