xref: /petsc/src/mat/interface/matrix.c (revision 1179163e0bf5c4dd309079707fd3c0dfe8d44eee)
1 /*
2    This is where the abstract matrix operations are defined
3 */
4 
5 #include <petsc/private/matimpl.h>        /*I "petscmat.h" I*/
6 #include <petsc/private/isimpl.h>
7 #include <petsc/private/vecimpl.h>
8 
9 /* Logging support */
10 PetscClassId MAT_CLASSID;
11 PetscClassId MAT_COLORING_CLASSID;
12 PetscClassId MAT_FDCOLORING_CLASSID;
13 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
14 
15 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
16 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve,MAT_MatTrSolve;
17 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
18 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
19 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
20 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
21 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
22 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
23 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply,MAT_Transpose,MAT_FDColoringFunction, MAT_CreateSubMat;
24 PetscLogEvent MAT_TransposeColoringCreate;
25 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
26 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric,MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
27 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
28 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
29 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
30 PetscLogEvent MAT_MultHermitianTranspose,MAT_MultHermitianTransposeAdd;
31 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
32 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
33 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
34 PetscLogEvent MAT_GetMultiProcBlock;
35 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
36 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
37 PetscLogEvent MAT_SetValuesBatch;
38 PetscLogEvent MAT_ViennaCLCopyToGPU;
39 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
40 PetscLogEvent MAT_Merge,MAT_Residual,MAT_SetRandom;
41 PetscLogEvent MAT_FactorFactS,MAT_FactorInvS;
42 PetscLogEvent MATCOLORING_Apply,MATCOLORING_Comm,MATCOLORING_Local,MATCOLORING_ISCreate,MATCOLORING_SetUp,MATCOLORING_Weights;
43 PetscLogEvent MAT_H2Opus_Build,MAT_H2Opus_Compress,MAT_H2Opus_Orthog,MAT_H2Opus_LR;
44 
45 const char *const MatFactorTypes[] = {"NONE","LU","CHOLESKY","ILU","ICC","ILUDT","QR","MatFactorType","MAT_FACTOR_",NULL};
46 
47 /*@
48    MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
49                   for sparse matrices that already have locations it fills the locations with random numbers
50 
51    Logically Collective on Mat
52 
53    Input Parameters:
54 +  x  - the matrix
55 -  rctx - the random number context, formed by PetscRandomCreate(), or NULL and
56           it will create one internally.
57 
58    Output Parameter:
59 .  x  - the matrix
60 
61    Example of Usage:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68    Level: intermediate
69 
70 .seealso: `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
71 @*/
72 PetscErrorCode MatSetRandom(Mat x,PetscRandom rctx)
73 {
74   PetscRandom    randObj = NULL;
75 
76   PetscFunctionBegin;
77   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
78   if (rctx) PetscValidHeaderSpecific(rctx,PETSC_RANDOM_CLASSID,2);
79   PetscValidType(x,1);
80   MatCheckPreallocated(x,1);
81 
82   PetscCheck(x->ops->setrandom,PetscObjectComm((PetscObject)x),PETSC_ERR_SUP,"Mat type %s",((PetscObject)x)->type_name);
83 
84   if (!rctx) {
85     MPI_Comm comm;
86     PetscCall(PetscObjectGetComm((PetscObject)x,&comm));
87     PetscCall(PetscRandomCreate(comm,&randObj));
88     PetscCall(PetscRandomSetFromOptions(randObj));
89     rctx = randObj;
90   }
91   PetscCall(PetscLogEventBegin(MAT_SetRandom,x,rctx,0,0));
92   PetscCall((*x->ops->setrandom)(x,rctx));
93   PetscCall(PetscLogEventEnd(MAT_SetRandom,x,rctx,0,0));
94 
95   PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY));
96   PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY));
97   PetscCall(PetscRandomDestroy(&randObj));
98   PetscFunctionReturn(0);
99 }
100 
101 /*@
102    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
103 
104    Logically Collective on Mat
105 
106    Input Parameter:
107 .  mat - the factored matrix
108 
109    Output Parameters:
110 +  pivot - the pivot value computed
111 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
112          the share the matrix
113 
114    Level: advanced
115 
116    Notes:
117     This routine does not work for factorizations done with external packages.
118 
119     This routine should only be called if MatGetFactorError() returns a value of MAT_FACTOR_NUMERIC_ZEROPIVOT
120 
121     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
122 
123 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`
124 @*/
125 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat,PetscReal *pivot,PetscInt *row)
126 {
127   PetscFunctionBegin;
128   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
129   PetscValidRealPointer(pivot,2);
130   PetscValidIntPointer(row,3);
131   *pivot = mat->factorerror_zeropivot_value;
132   *row   = mat->factorerror_zeropivot_row;
133   PetscFunctionReturn(0);
134 }
135 
136 /*@
137    MatFactorGetError - gets the error code from a factorization
138 
139    Logically Collective on Mat
140 
141    Input Parameters:
142 .  mat - the factored matrix
143 
144    Output Parameter:
145 .  err  - the error code
146 
147    Level: advanced
148 
149    Notes:
150     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
151 
152 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`
153 @*/
154 PetscErrorCode MatFactorGetError(Mat mat,MatFactorError *err)
155 {
156   PetscFunctionBegin;
157   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
158   PetscValidPointer(err,2);
159   *err = mat->factorerrortype;
160   PetscFunctionReturn(0);
161 }
162 
163 /*@
164    MatFactorClearError - clears the error code in a factorization
165 
166    Logically Collective on Mat
167 
168    Input Parameter:
169 .  mat - the factored matrix
170 
171    Level: developer
172 
173    Notes:
174     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
175 
176 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`
177 @*/
178 PetscErrorCode MatFactorClearError(Mat mat)
179 {
180   PetscFunctionBegin;
181   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
182   mat->factorerrortype             = MAT_FACTOR_NOERROR;
183   mat->factorerror_zeropivot_value = 0.0;
184   mat->factorerror_zeropivot_row   = 0;
185   PetscFunctionReturn(0);
186 }
187 
188 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat,PetscBool cols,PetscReal tol,IS *nonzero)
189 {
190   Vec               r,l;
191   const PetscScalar *al;
192   PetscInt          i,nz,gnz,N,n;
193 
194   PetscFunctionBegin;
195   PetscCall(MatCreateVecs(mat,&r,&l));
196   if (!cols) { /* nonzero rows */
197     PetscCall(MatGetSize(mat,&N,NULL));
198     PetscCall(MatGetLocalSize(mat,&n,NULL));
199     PetscCall(VecSet(l,0.0));
200     PetscCall(VecSetRandom(r,NULL));
201     PetscCall(MatMult(mat,r,l));
202     PetscCall(VecGetArrayRead(l,&al));
203   } else { /* nonzero columns */
204     PetscCall(MatGetSize(mat,NULL,&N));
205     PetscCall(MatGetLocalSize(mat,NULL,&n));
206     PetscCall(VecSet(r,0.0));
207     PetscCall(VecSetRandom(l,NULL));
208     PetscCall(MatMultTranspose(mat,l,r));
209     PetscCall(VecGetArrayRead(r,&al));
210   }
211   if (tol <= 0.0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nz++; }
212   else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nz++; }
213   PetscCall(MPIU_Allreduce(&nz,&gnz,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
214   if (gnz != N) {
215     PetscInt *nzr;
216     PetscCall(PetscMalloc1(nz,&nzr));
217     if (nz) {
218       if (tol < 0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nzr[nz++] = i; }
219       else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; }
220     }
221     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat),nz,nzr,PETSC_OWN_POINTER,nonzero));
222   } else *nonzero = NULL;
223   if (!cols) { /* nonzero rows */
224     PetscCall(VecRestoreArrayRead(l,&al));
225   } else {
226     PetscCall(VecRestoreArrayRead(r,&al));
227   }
228   PetscCall(VecDestroy(&l));
229   PetscCall(VecDestroy(&r));
230   PetscFunctionReturn(0);
231 }
232 
233 /*@
234       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
235 
236   Input Parameter:
237 .    A  - the matrix
238 
239   Output Parameter:
240 .    keptrows - the rows that are not completely zero
241 
242   Notes:
243     keptrows is set to NULL if all rows are nonzero.
244 
245   Level: intermediate
246 
247  @*/
248 PetscErrorCode MatFindNonzeroRows(Mat mat,IS *keptrows)
249 {
250   PetscFunctionBegin;
251   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
252   PetscValidType(mat,1);
253   PetscValidPointer(keptrows,2);
254   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
255   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
256   if (mat->ops->findnonzerorows) {
257     PetscCall((*mat->ops->findnonzerorows)(mat,keptrows));
258   } else {
259     PetscCall(MatFindNonzeroRowsOrCols_Basic(mat,PETSC_FALSE,0.0,keptrows));
260   }
261   PetscFunctionReturn(0);
262 }
263 
264 /*@
265       MatFindZeroRows - Locate all rows that are completely zero in the matrix
266 
267   Input Parameter:
268 .    A  - the matrix
269 
270   Output Parameter:
271 .    zerorows - the rows that are completely zero
272 
273   Notes:
274     zerorows is set to NULL if no rows are zero.
275 
276   Level: intermediate
277 
278  @*/
279 PetscErrorCode MatFindZeroRows(Mat mat,IS *zerorows)
280 {
281   IS       keptrows;
282   PetscInt m, n;
283 
284   PetscFunctionBegin;
285   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
286   PetscValidType(mat,1);
287   PetscValidPointer(zerorows,2);
288   PetscCall(MatFindNonzeroRows(mat, &keptrows));
289   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
290      In keeping with this convention, we set zerorows to NULL if there are no zero
291      rows. */
292   if (keptrows == NULL) {
293     *zerorows = NULL;
294   } else {
295     PetscCall(MatGetOwnershipRange(mat,&m,&n));
296     PetscCall(ISComplement(keptrows,m,n,zerorows));
297     PetscCall(ISDestroy(&keptrows));
298   }
299   PetscFunctionReturn(0);
300 }
301 
302 /*@
303    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
304 
305    Not Collective
306 
307    Input Parameters:
308 .   A - the matrix
309 
310    Output Parameters:
311 .   a - the diagonal part (which is a SEQUENTIAL matrix)
312 
313    Notes:
314     see the manual page for MatCreateAIJ() for more information on the "diagonal part" of the matrix.
315           Use caution, as the reference count on the returned matrix is not incremented and it is used as
316           part of the containing MPI Mat's normal operation.
317 
318    Level: advanced
319 
320 @*/
321 PetscErrorCode MatGetDiagonalBlock(Mat A,Mat *a)
322 {
323   PetscFunctionBegin;
324   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
325   PetscValidType(A,1);
326   PetscValidPointer(a,2);
327   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
328   if (A->ops->getdiagonalblock) {
329     PetscCall((*A->ops->getdiagonalblock)(A,a));
330   } else {
331     PetscMPIInt size;
332 
333     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
334     PetscCheck(size == 1,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not for parallel matrix type %s",((PetscObject)A)->type_name);
335     *a = A;
336   }
337   PetscFunctionReturn(0);
338 }
339 
340 /*@
341    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
342 
343    Collective on Mat
344 
345    Input Parameters:
346 .  mat - the matrix
347 
348    Output Parameter:
349 .   trace - the sum of the diagonal entries
350 
351    Level: advanced
352 
353 @*/
354 PetscErrorCode MatGetTrace(Mat mat,PetscScalar *trace)
355 {
356   Vec diag;
357 
358   PetscFunctionBegin;
359   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
360   PetscValidScalarPointer(trace,2);
361   PetscCall(MatCreateVecs(mat,&diag,NULL));
362   PetscCall(MatGetDiagonal(mat,diag));
363   PetscCall(VecSum(diag,trace));
364   PetscCall(VecDestroy(&diag));
365   PetscFunctionReturn(0);
366 }
367 
368 /*@
369    MatRealPart - Zeros out the imaginary part of the matrix
370 
371    Logically Collective on Mat
372 
373    Input Parameters:
374 .  mat - the matrix
375 
376    Level: advanced
377 
378 .seealso: `MatImaginaryPart()`
379 @*/
380 PetscErrorCode MatRealPart(Mat mat)
381 {
382   PetscFunctionBegin;
383   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
384   PetscValidType(mat,1);
385   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
386   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
387   PetscCheck(mat->ops->realpart,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
388   MatCheckPreallocated(mat,1);
389   PetscCall((*mat->ops->realpart)(mat));
390   PetscFunctionReturn(0);
391 }
392 
393 /*@C
394    MatGetGhosts - Get the global index of all ghost nodes defined by the sparse matrix
395 
396    Collective on Mat
397 
398    Input Parameter:
399 .  mat - the matrix
400 
401    Output Parameters:
402 +   nghosts - number of ghosts (note for BAIJ matrices there is one ghost for each block)
403 -   ghosts - the global indices of the ghost points
404 
405    Notes:
406     the nghosts and ghosts are suitable to pass into VecCreateGhost()
407 
408    Level: advanced
409 
410 @*/
411 PetscErrorCode MatGetGhosts(Mat mat,PetscInt *nghosts,const PetscInt *ghosts[])
412 {
413   PetscFunctionBegin;
414   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
415   PetscValidType(mat,1);
416   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
417   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
418   if (mat->ops->getghosts) {
419     PetscCall((*mat->ops->getghosts)(mat,nghosts,ghosts));
420   } else {
421     if (nghosts) *nghosts = 0;
422     if (ghosts)  *ghosts  = NULL;
423   }
424   PetscFunctionReturn(0);
425 }
426 
427 /*@
428    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
429 
430    Logically Collective on Mat
431 
432    Input Parameters:
433 .  mat - the matrix
434 
435    Level: advanced
436 
437 .seealso: `MatRealPart()`
438 @*/
439 PetscErrorCode MatImaginaryPart(Mat mat)
440 {
441   PetscFunctionBegin;
442   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
443   PetscValidType(mat,1);
444   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
445   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
446   PetscCheck(mat->ops->imaginarypart,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
447   MatCheckPreallocated(mat,1);
448   PetscCall((*mat->ops->imaginarypart)(mat));
449   PetscFunctionReturn(0);
450 }
451 
452 /*@
453    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for BAIJ matrices)
454 
455    Not Collective
456 
457    Input Parameter:
458 .  mat - the matrix
459 
460    Output Parameters:
461 +  missing - is any diagonal missing
462 -  dd - first diagonal entry that is missing (optional) on this process
463 
464    Level: advanced
465 
466 .seealso: `MatRealPart()`
467 @*/
468 PetscErrorCode MatMissingDiagonal(Mat mat,PetscBool *missing,PetscInt *dd)
469 {
470   PetscFunctionBegin;
471   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
472   PetscValidType(mat,1);
473   PetscValidBoolPointer(missing,2);
474   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix %s",((PetscObject)mat)->type_name);
475   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
476   PetscCheck(mat->ops->missingdiagonal,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
477   PetscCall((*mat->ops->missingdiagonal)(mat,missing,dd));
478   PetscFunctionReturn(0);
479 }
480 
481 /*@C
482    MatGetRow - Gets a row of a matrix.  You MUST call MatRestoreRow()
483    for each row that you get to ensure that your application does
484    not bleed memory.
485 
486    Not Collective
487 
488    Input Parameters:
489 +  mat - the matrix
490 -  row - the row to get
491 
492    Output Parameters:
493 +  ncols -  if not NULL, the number of nonzeros in the row
494 .  cols - if not NULL, the column numbers
495 -  vals - if not NULL, the values
496 
497    Notes:
498    This routine is provided for people who need to have direct access
499    to the structure of a matrix.  We hope that we provide enough
500    high-level matrix routines that few users will need it.
501 
502    MatGetRow() always returns 0-based column indices, regardless of
503    whether the internal representation is 0-based (default) or 1-based.
504 
505    For better efficiency, set cols and/or vals to NULL if you do
506    not wish to extract these quantities.
507 
508    The user can only examine the values extracted with MatGetRow();
509    the values cannot be altered.  To change the matrix entries, one
510    must use MatSetValues().
511 
512    You can only have one call to MatGetRow() outstanding for a particular
513    matrix at a time, per processor. MatGetRow() can only obtain rows
514    associated with the given processor, it cannot get rows from the
515    other processors; for that we suggest using MatCreateSubMatrices(), then
516    MatGetRow() on the submatrix. The row index passed to MatGetRow()
517    is in the global number of rows.
518 
519    Fortran Notes:
520    The calling sequence from Fortran is
521 .vb
522    MatGetRow(matrix,row,ncols,cols,values,ierr)
523          Mat     matrix (input)
524          integer row    (input)
525          integer ncols  (output)
526          integer cols(maxcols) (output)
527          double precision (or double complex) values(maxcols) output
528 .ve
529    where maxcols >= maximum nonzeros in any row of the matrix.
530 
531    Caution:
532    Do not try to change the contents of the output arrays (cols and vals).
533    In some cases, this may corrupt the matrix.
534 
535    Level: advanced
536 
537 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`
538 @*/
539 PetscErrorCode MatGetRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
540 {
541   PetscInt incols;
542 
543   PetscFunctionBegin;
544   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
545   PetscValidType(mat,1);
546   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
547   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
548   PetscCheck(mat->ops->getrow,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
549   MatCheckPreallocated(mat,1);
550   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")",row,mat->rmap->rstart,mat->rmap->rend);
551   PetscCall(PetscLogEventBegin(MAT_GetRow,mat,0,0,0));
552   PetscCall((*mat->ops->getrow)(mat,row,&incols,(PetscInt**)cols,(PetscScalar**)vals));
553   if (ncols) *ncols = incols;
554   PetscCall(PetscLogEventEnd(MAT_GetRow,mat,0,0,0));
555   PetscFunctionReturn(0);
556 }
557 
558 /*@
559    MatConjugate - replaces the matrix values with their complex conjugates
560 
561    Logically Collective on Mat
562 
563    Input Parameters:
564 .  mat - the matrix
565 
566    Level: advanced
567 
568 .seealso: `VecConjugate()`
569 @*/
570 PetscErrorCode MatConjugate(Mat mat)
571 {
572   PetscFunctionBegin;
573   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
574   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
575   if (PetscDefined(USE_COMPLEX)) {
576     PetscCheck(mat->ops->conjugate,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not provided for matrix type %s, send email to petsc-maint@mcs.anl.gov",((PetscObject)mat)->type_name);
577     PetscCall((*mat->ops->conjugate)(mat));
578   }
579   PetscFunctionReturn(0);
580 }
581 
582 /*@C
583    MatRestoreRow - Frees any temporary space allocated by MatGetRow().
584 
585    Not Collective
586 
587    Input Parameters:
588 +  mat - the matrix
589 .  row - the row to get
590 .  ncols, cols - the number of nonzeros and their columns
591 -  vals - if nonzero the column values
592 
593    Notes:
594    This routine should be called after you have finished examining the entries.
595 
596    This routine zeros out ncols, cols, and vals. This is to prevent accidental
597    us of the array after it has been restored. If you pass NULL, it will
598    not zero the pointers.  Use of cols or vals after MatRestoreRow is invalid.
599 
600    Fortran Notes:
601    The calling sequence from Fortran is
602 .vb
603    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
604       Mat     matrix (input)
605       integer row    (input)
606       integer ncols  (output)
607       integer cols(maxcols) (output)
608       double precision (or double complex) values(maxcols) output
609 .ve
610    Where maxcols >= maximum nonzeros in any row of the matrix.
611 
612    In Fortran MatRestoreRow() MUST be called after MatGetRow()
613    before another call to MatGetRow() can be made.
614 
615    Level: advanced
616 
617 .seealso: `MatGetRow()`
618 @*/
619 PetscErrorCode MatRestoreRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
620 {
621   PetscFunctionBegin;
622   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
623   if (ncols) PetscValidIntPointer(ncols,3);
624   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
625   if (!mat->ops->restorerow) PetscFunctionReturn(0);
626   PetscCall((*mat->ops->restorerow)(mat,row,ncols,(PetscInt **)cols,(PetscScalar **)vals));
627   if (ncols) *ncols = 0;
628   if (cols)  *cols = NULL;
629   if (vals)  *vals = NULL;
630   PetscFunctionReturn(0);
631 }
632 
633 /*@
634    MatGetRowUpperTriangular - Sets a flag to enable calls to MatGetRow() for matrix in MATSBAIJ format.
635    You should call MatRestoreRowUpperTriangular() after calling MatGetRow/MatRestoreRow() to disable the flag.
636 
637    Not Collective
638 
639    Input Parameters:
640 .  mat - the matrix
641 
642    Notes:
643    The flag is to ensure that users are aware of MatGetRow() only provides the upper triangular part of the row for the matrices in MATSBAIJ format.
644 
645    Level: advanced
646 
647 .seealso: `MatRestoreRowUpperTriangular()`
648 @*/
649 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
650 {
651   PetscFunctionBegin;
652   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
653   PetscValidType(mat,1);
654   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
655   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
656   MatCheckPreallocated(mat,1);
657   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
658   PetscCall((*mat->ops->getrowuppertriangular)(mat));
659   PetscFunctionReturn(0);
660 }
661 
662 /*@
663    MatRestoreRowUpperTriangular - Disable calls to MatGetRow() for matrix in MATSBAIJ format.
664 
665    Not Collective
666 
667    Input Parameters:
668 .  mat - the matrix
669 
670    Notes:
671    This routine should be called after you have finished MatGetRow/MatRestoreRow().
672 
673    Level: advanced
674 
675 .seealso: `MatGetRowUpperTriangular()`
676 @*/
677 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
678 {
679   PetscFunctionBegin;
680   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
681   PetscValidType(mat,1);
682   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
683   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
684   MatCheckPreallocated(mat,1);
685   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
686   PetscCall((*mat->ops->restorerowuppertriangular)(mat));
687   PetscFunctionReturn(0);
688 }
689 
690 /*@C
691    MatSetOptionsPrefix - Sets the prefix used for searching for all
692    Mat options in the database.
693 
694    Logically Collective on Mat
695 
696    Input Parameters:
697 +  A - the Mat context
698 -  prefix - the prefix to prepend to all option names
699 
700    Notes:
701    A hyphen (-) must NOT be given at the beginning of the prefix name.
702    The first character of all runtime options is AUTOMATICALLY the hyphen.
703 
704    This is NOT used for options for the factorization of the matrix. Normally the
705    prefix is automatically passed in from the PC calling the factorization. To set
706    it directly use  `MatSetOptionsPrefixFactor()`
707 
708    Level: advanced
709 
710 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
711 @*/
712 PetscErrorCode MatSetOptionsPrefix(Mat A,const char prefix[])
713 {
714   PetscFunctionBegin;
715   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
716   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A,prefix));
717   PetscFunctionReturn(0);
718 }
719 
720 /*@C
721    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all Mat factor options in the database for
722    for matrices created with `MatGetFactor()`
723 
724    Logically Collective on Mat
725 
726    Input Parameters:
727 +  A - the Mat context
728 -  prefix - the prefix to prepend to all option names for the factored matrix
729 
730    Notes:
731    A hyphen (-) must NOT be given at the beginning of the prefix name.
732    The first character of all runtime options is AUTOMATICALLY the hyphen.
733 
734    Normally the prefix is automatically passed in from the PC calling the factorization. To set
735    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
736 
737    Level: developer
738 
739 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
740 @*/
741 PetscErrorCode MatSetOptionsPrefixFactor(Mat A,const char prefix[])
742 {
743   PetscFunctionBegin;
744   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
745   if (prefix) {
746     PetscValidCharPointer(prefix,2);
747     PetscCheck(prefix[0] != '-',PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
748     if (prefix != A->factorprefix) {
749       PetscCall(PetscFree(A->factorprefix));
750       PetscCall(PetscStrallocpy(prefix,&A->factorprefix));
751     }
752   } else PetscCall(PetscFree(A->factorprefix));
753   PetscFunctionReturn(0);
754 }
755 
756 /*@C
757    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all Mat factor options in the database for
758    for matrices created with `MatGetFactor()`
759 
760    Logically Collective on Mat
761 
762    Input Parameters:
763 +  A - the Mat context
764 -  prefix - the prefix to prepend to all option names for the factored matrix
765 
766    Notes:
767    A hyphen (-) must NOT be given at the beginning of the prefix name.
768    The first character of all runtime options is AUTOMATICALLY the hyphen.
769 
770    Normally the prefix is automatically passed in from the PC calling the factorization. To set
771    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
772 
773    Level: developer
774    .seealso: `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
775              `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
776              `MatSetOptionsPrefix()`
777 @*/
778 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A,const char prefix[])
779 {
780   char           *buf = A->factorprefix;
781   size_t         len1,len2;
782 
783   PetscFunctionBegin;
784   PetscValidHeader(A,1);
785   if (!prefix) PetscFunctionReturn(0);
786   if (!buf) {
787     PetscCall(MatSetOptionsPrefixFactor(A,prefix));
788     PetscFunctionReturn(0);
789   }
790   PetscCheck(prefix[0] != '-',PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
791 
792   PetscCall(PetscStrlen(prefix,&len1));
793   PetscCall(PetscStrlen(buf,&len2));
794   PetscCall(PetscMalloc1(1+len1+len2,&A->factorprefix));
795   PetscCall(PetscStrcpy(A->factorprefix,buf));
796   PetscCall(PetscStrcat(A->factorprefix,prefix));
797   PetscCall(PetscFree(buf));
798   PetscFunctionReturn(0);
799 }
800 
801 /*@C
802    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
803    Mat options in the database.
804 
805    Logically Collective on Mat
806 
807    Input Parameters:
808 +  A - the Mat context
809 -  prefix - the prefix to prepend to all option names
810 
811    Notes:
812    A hyphen (-) must NOT be given at the beginning of the prefix name.
813    The first character of all runtime options is AUTOMATICALLY the hyphen.
814 
815    Level: advanced
816 
817 .seealso: `MatGetOptionsPrefix()`
818 @*/
819 PetscErrorCode MatAppendOptionsPrefix(Mat A,const char prefix[])
820 {
821   PetscFunctionBegin;
822   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
823   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A,prefix));
824   PetscFunctionReturn(0);
825 }
826 
827 /*@C
828    MatGetOptionsPrefix - Gets the prefix used for searching for all
829    Mat options in the database.
830 
831    Not Collective
832 
833    Input Parameter:
834 .  A - the Mat context
835 
836    Output Parameter:
837 .  prefix - pointer to the prefix string used
838 
839    Notes:
840     On the fortran side, the user should pass in a string 'prefix' of
841    sufficient length to hold the prefix.
842 
843    Level: advanced
844 
845 .seealso: `MatAppendOptionsPrefix()`
846 @*/
847 PetscErrorCode MatGetOptionsPrefix(Mat A,const char *prefix[])
848 {
849   PetscFunctionBegin;
850   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
851   PetscValidPointer(prefix,2);
852   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A,prefix));
853   PetscFunctionReturn(0);
854 }
855 
856 /*@
857    MatResetPreallocation - Reset mat to use the original nonzero pattern provided by users.
858 
859    Collective on Mat
860 
861    Input Parameters:
862 .  A - the Mat context
863 
864    Notes:
865    The allocated memory will be shrunk after calling MatAssembly with MAT_FINAL_ASSEMBLY. Users can reset the preallocation to access the original memory.
866    Currently support MPIAIJ and SEQAIJ.
867 
868    Level: beginner
869 
870 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
871 @*/
872 PetscErrorCode MatResetPreallocation(Mat A)
873 {
874   PetscFunctionBegin;
875   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
876   PetscValidType(A,1);
877   PetscUseMethod(A,"MatResetPreallocation_C",(Mat),(A));
878   PetscFunctionReturn(0);
879 }
880 
881 /*@
882    MatSetUp - Sets up the internal matrix data structures for later use.
883 
884    Collective on Mat
885 
886    Input Parameters:
887 .  A - the Mat context
888 
889    Notes:
890    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
891 
892    If a suitable preallocation routine is used, this function does not need to be called.
893 
894    See the Performance chapter of the PETSc users manual for how to preallocate matrices
895 
896    Level: beginner
897 
898 .seealso: `MatCreate()`, `MatDestroy()`
899 @*/
900 PetscErrorCode MatSetUp(Mat A)
901 {
902   PetscFunctionBegin;
903   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
904   if (!((PetscObject)A)->type_name) {
905     PetscMPIInt size;
906 
907     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
908     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
909   }
910   if (!A->preallocated && A->ops->setup) {
911     PetscCall(PetscInfo(A,"Warning not preallocating matrix storage\n"));
912     PetscCall((*A->ops->setup)(A));
913   }
914   PetscCall(PetscLayoutSetUp(A->rmap));
915   PetscCall(PetscLayoutSetUp(A->cmap));
916   A->preallocated = PETSC_TRUE;
917   PetscFunctionReturn(0);
918 }
919 
920 #if defined(PETSC_HAVE_SAWS)
921 #include <petscviewersaws.h>
922 #endif
923 
924 /*@C
925    MatViewFromOptions - View from Options
926 
927    Collective on Mat
928 
929    Input Parameters:
930 +  A - the Mat context
931 .  obj - Optional object
932 -  name - command line option
933 
934    Level: intermediate
935 .seealso: `Mat`, `MatView`, `PetscObjectViewFromOptions()`, `MatCreate()`
936 @*/
937 PetscErrorCode  MatViewFromOptions(Mat A,PetscObject obj,const char name[])
938 {
939   PetscFunctionBegin;
940   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
941   PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name));
942   PetscFunctionReturn(0);
943 }
944 
945 /*@C
946    MatView - Visualizes a matrix object.
947 
948    Collective on Mat
949 
950    Input Parameters:
951 +  mat - the matrix
952 -  viewer - visualization context
953 
954   Notes:
955   The available visualization contexts include
956 +    PETSC_VIEWER_STDOUT_SELF - for sequential matrices
957 .    PETSC_VIEWER_STDOUT_WORLD - for parallel matrices created on PETSC_COMM_WORLD
958 .    PETSC_VIEWER_STDOUT_(comm) - for matrices created on MPI communicator comm
959 -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
960 
961    The user can open alternative visualization contexts with
962 +    PetscViewerASCIIOpen() - Outputs matrix to a specified file
963 .    PetscViewerBinaryOpen() - Outputs matrix in binary to a
964          specified file; corresponding input uses MatLoad()
965 .    PetscViewerDrawOpen() - Outputs nonzero matrix structure to
966          an X window display
967 -    PetscViewerSocketOpen() - Outputs matrix to Socket viewer.
968          Currently only the sequential dense and AIJ
969          matrix types support the Socket viewer.
970 
971    The user can call PetscViewerPushFormat() to specify the output
972    format of ASCII printed objects (when using PETSC_VIEWER_STDOUT_SELF,
973    PETSC_VIEWER_STDOUT_WORLD and PetscViewerASCIIOpen).  Available formats include
974 +    PETSC_VIEWER_DEFAULT - default, prints matrix contents
975 .    PETSC_VIEWER_ASCII_MATLAB - prints matrix contents in Matlab format
976 .    PETSC_VIEWER_ASCII_DENSE - prints entire matrix including zeros
977 .    PETSC_VIEWER_ASCII_COMMON - prints matrix contents, using a sparse
978          format common among all matrix types
979 .    PETSC_VIEWER_ASCII_IMPL - prints matrix contents, using an implementation-specific
980          format (which is in many cases the same as the default)
981 .    PETSC_VIEWER_ASCII_INFO - prints basic information about the matrix
982          size and structure (not the matrix entries)
983 -    PETSC_VIEWER_ASCII_INFO_DETAIL - prints more detailed information about
984          the matrix structure
985 
986    Options Database Keys:
987 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatAssemblyEnd()
988 .  -mat_view ::ascii_info_detail - Prints more detailed info
989 .  -mat_view - Prints matrix in ASCII format
990 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
991 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
992 .  -display <name> - Sets display name (default is host)
993 .  -draw_pause <sec> - Sets number of seconds to pause after display
994 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
995 .  -viewer_socket_machine <machine> -
996 .  -viewer_socket_port <port> -
997 .  -mat_view binary - save matrix to file in binary format
998 -  -viewer_binary_filename <name> -
999 
1000    Level: beginner
1001 
1002    Notes:
1003     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1004     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1005 
1006     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1007 
1008     See the manual page for MatLoad() for the exact format of the binary file when the binary
1009       viewer is used.
1010 
1011       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1012       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1013 
1014       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1015       and then use the following mouse functions.
1016 .vb
1017   left mouse: zoom in
1018   middle mouse: zoom out
1019   right mouse: continue with the simulation
1020 .ve
1021 
1022 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`,
1023           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`
1024 @*/
1025 PetscErrorCode MatView(Mat mat,PetscViewer viewer)
1026 {
1027   PetscInt          rows,cols,rbs,cbs;
1028   PetscBool         isascii,isstring,issaws;
1029   PetscViewerFormat format;
1030   PetscMPIInt       size;
1031 
1032   PetscFunctionBegin;
1033   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1034   PetscValidType(mat,1);
1035   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat),&viewer));
1036   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1037   PetscCheckSameComm(mat,1,viewer,2);
1038   MatCheckPreallocated(mat,1);
1039 
1040   PetscCall(PetscViewerGetFormat(viewer,&format));
1041   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
1042   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1043 
1044   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring));
1045   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
1046   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws));
1047   if ((!isascii || (format != PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) && mat->factortype) {
1048     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"No viewers for factored matrix except ASCII info or info_detail");
1049   }
1050 
1051   PetscCall(PetscLogEventBegin(MAT_View,mat,viewer,0,0));
1052   if (isascii) {
1053     PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Must call MatAssemblyBegin/End() before viewing matrix");
1054     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat,viewer));
1055     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1056       MatNullSpace nullsp,transnullsp;
1057 
1058       PetscCall(PetscViewerASCIIPushTab(viewer));
1059       PetscCall(MatGetSize(mat,&rows,&cols));
1060       PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
1061       if (rbs != 1 || cbs != 1) {
1062         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n",rows,cols,rbs,cbs));
1063         else            PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n",rows,cols,rbs));
1064       } else PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n",rows,cols));
1065       if (mat->factortype) {
1066         MatSolverType solver;
1067         PetscCall(MatFactorGetSolverType(mat,&solver));
1068         PetscCall(PetscViewerASCIIPrintf(viewer,"package used to perform factorization: %s\n",solver));
1069       }
1070       if (mat->ops->getinfo) {
1071         MatInfo info;
1072         PetscCall(MatGetInfo(mat,MAT_GLOBAL_SUM,&info));
1073         PetscCall(PetscViewerASCIIPrintf(viewer,"total: nonzeros=%.f, allocated nonzeros=%.f\n",info.nz_used,info.nz_allocated));
1074         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer,"total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n",(PetscInt)info.mallocs));
1075       }
1076       PetscCall(MatGetNullSpace(mat,&nullsp));
1077       PetscCall(MatGetTransposeNullSpace(mat,&transnullsp));
1078       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached null space\n"));
1079       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached transposed null space\n"));
1080       PetscCall(MatGetNearNullSpace(mat,&nullsp));
1081       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached near null space\n"));
1082       PetscCall(PetscViewerASCIIPushTab(viewer));
1083       PetscCall(MatProductView(mat,viewer));
1084       PetscCall(PetscViewerASCIIPopTab(viewer));
1085     }
1086   } else if (issaws) {
1087 #if defined(PETSC_HAVE_SAWS)
1088     PetscMPIInt rank;
1089 
1090     PetscCall(PetscObjectName((PetscObject)mat));
1091     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
1092     if (!((PetscObject)mat)->amsmem && rank == 0) {
1093       PetscCall(PetscObjectViewSAWs((PetscObject)mat,viewer));
1094     }
1095 #endif
1096   } else if (isstring) {
1097     const char *type;
1098     PetscCall(MatGetType(mat,&type));
1099     PetscCall(PetscViewerStringSPrintf(viewer," MatType: %-7.7s",type));
1100     if (mat->ops->view) PetscCall((*mat->ops->view)(mat,viewer));
1101   }
1102   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1103     PetscCall(PetscViewerASCIIPushTab(viewer));
1104     PetscCall((*mat->ops->viewnative)(mat,viewer));
1105     PetscCall(PetscViewerASCIIPopTab(viewer));
1106   } else if (mat->ops->view) {
1107     PetscCall(PetscViewerASCIIPushTab(viewer));
1108     PetscCall((*mat->ops->view)(mat,viewer));
1109     PetscCall(PetscViewerASCIIPopTab(viewer));
1110   }
1111   if (isascii) {
1112     PetscCall(PetscViewerGetFormat(viewer,&format));
1113     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1114       PetscCall(PetscViewerASCIIPopTab(viewer));
1115     }
1116   }
1117   PetscCall(PetscLogEventEnd(MAT_View,mat,viewer,0,0));
1118   PetscFunctionReturn(0);
1119 }
1120 
1121 #if defined(PETSC_USE_DEBUG)
1122 #include <../src/sys/totalview/tv_data_display.h>
1123 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1124 {
1125   TV_add_row("Local rows", "int", &mat->rmap->n);
1126   TV_add_row("Local columns", "int", &mat->cmap->n);
1127   TV_add_row("Global rows", "int", &mat->rmap->N);
1128   TV_add_row("Global columns", "int", &mat->cmap->N);
1129   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1130   return TV_format_OK;
1131 }
1132 #endif
1133 
1134 /*@C
1135    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1136    with MatView().  The matrix format is determined from the options database.
1137    Generates a parallel MPI matrix if the communicator has more than one
1138    processor.  The default matrix type is AIJ.
1139 
1140    Collective on PetscViewer
1141 
1142    Input Parameters:
1143 +  mat - the newly loaded matrix, this needs to have been created with MatCreate()
1144             or some related function before a call to MatLoad()
1145 -  viewer - binary/HDF5 file viewer
1146 
1147    Options Database Keys:
1148    Used with block matrix formats (MATSEQBAIJ,  ...) to specify
1149    block size
1150 .    -matload_block_size <bs> - set block size
1151 
1152    Level: beginner
1153 
1154    Notes:
1155    If the Mat type has not yet been given then MATAIJ is used, call MatSetFromOptions() on the
1156    Mat before calling this routine if you wish to set it from the options database.
1157 
1158    MatLoad() automatically loads into the options database any options
1159    given in the file filename.info where filename is the name of the file
1160    that was passed to the PetscViewerBinaryOpen(). The options in the info
1161    file will be ignored if you use the -viewer_binary_skip_info option.
1162 
1163    If the type or size of mat is not set before a call to MatLoad, PETSc
1164    sets the default matrix type AIJ and sets the local and global sizes.
1165    If type and/or size is already set, then the same are used.
1166 
1167    In parallel, each processor can load a subset of rows (or the
1168    entire matrix).  This routine is especially useful when a large
1169    matrix is stored on disk and only part of it is desired on each
1170    processor.  For example, a parallel solver may access only some of
1171    the rows from each processor.  The algorithm used here reads
1172    relatively small blocks of data rather than reading the entire
1173    matrix and then subsetting it.
1174 
1175    Viewer's PetscViewerType must be either PETSCVIEWERBINARY or PETSCVIEWERHDF5.
1176    Such viewer can be created using PetscViewerBinaryOpen()/PetscViewerHDF5Open(),
1177    or the sequence like
1178 $    PetscViewer v;
1179 $    PetscViewerCreate(PETSC_COMM_WORLD,&v);
1180 $    PetscViewerSetType(v,PETSCVIEWERBINARY);
1181 $    PetscViewerSetFromOptions(v);
1182 $    PetscViewerFileSetMode(v,FILE_MODE_READ);
1183 $    PetscViewerFileSetName(v,"datafile");
1184    The optional PetscViewerSetFromOptions() call allows to override PetscViewerSetType() using option
1185 $ -viewer_type {binary,hdf5}
1186 
1187    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1188    and src/mat/tutorials/ex10.c with the second approach.
1189 
1190    Notes about the PETSc binary format:
1191    In case of PETSCVIEWERBINARY, a native PETSc binary format is used. Each of the blocks
1192    is read onto rank 0 and then shipped to its destination rank, one after another.
1193    Multiple objects, both matrices and vectors, can be stored within the same file.
1194    Their PetscObject name is ignored; they are loaded in the order of their storage.
1195 
1196    Most users should not need to know the details of the binary storage
1197    format, since MatLoad() and MatView() completely hide these details.
1198    But for anyone who's interested, the standard binary matrix storage
1199    format is
1200 
1201 $    PetscInt    MAT_FILE_CLASSID
1202 $    PetscInt    number of rows
1203 $    PetscInt    number of columns
1204 $    PetscInt    total number of nonzeros
1205 $    PetscInt    *number nonzeros in each row
1206 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1207 $    PetscScalar *values of all nonzeros
1208 
1209    PETSc automatically does the byte swapping for
1210 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1211 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1212 read/write routines you have to swap the bytes; see PetscBinaryRead()
1213 and PetscBinaryWrite() to see how this may be done.
1214 
1215    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1216    In case of PETSCVIEWERHDF5, a parallel HDF5 reader is used.
1217    Each processor's chunk is loaded independently by its owning rank.
1218    Multiple objects, both matrices and vectors, can be stored within the same file.
1219    They are looked up by their PetscObject name.
1220 
1221    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1222    by default the same structure and naming of the AIJ arrays and column count
1223    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1224 $    save example.mat A b -v7.3
1225    can be directly read by this routine (see Reference 1 for details).
1226    Note that depending on your MATLAB version, this format might be a default,
1227    otherwise you can set it as default in Preferences.
1228 
1229    Unless -nocompression flag is used to save the file in MATLAB,
1230    PETSc must be configured with ZLIB package.
1231 
1232    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1233 
1234    Current HDF5 (MAT-File) limitations:
1235    This reader currently supports only real MATSEQAIJ, MATMPIAIJ, MATSEQDENSE and MATMPIDENSE matrices.
1236 
1237    Corresponding MatView() is not yet implemented.
1238 
1239    The loaded matrix is actually a transpose of the original one in MATLAB,
1240    unless you push PETSC_VIEWER_HDF5_MAT format (see examples above).
1241    With this format, matrix is automatically transposed by PETSc,
1242    unless the matrix is marked as SPD or symmetric
1243    (see MatSetOption(), MAT_SPD, MAT_SYMMETRIC).
1244 
1245    References:
1246 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1247 
1248 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1249 
1250  @*/
1251 PetscErrorCode MatLoad(Mat mat,PetscViewer viewer)
1252 {
1253   PetscBool flg;
1254 
1255   PetscFunctionBegin;
1256   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1257   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1258 
1259   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat,MATAIJ));
1260 
1261   flg  = PETSC_FALSE;
1262   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matload_symmetric",&flg,NULL));
1263   if (flg) {
1264     PetscCall(MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE));
1265     PetscCall(MatSetOption(mat,MAT_SYMMETRY_ETERNAL,PETSC_TRUE));
1266   }
1267   flg  = PETSC_FALSE;
1268   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matload_spd",&flg,NULL));
1269   if (flg) PetscCall(MatSetOption(mat,MAT_SPD,PETSC_TRUE));
1270 
1271   PetscCheck(mat->ops->load,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatLoad is not supported for type %s",((PetscObject)mat)->type_name);
1272   PetscCall(PetscLogEventBegin(MAT_Load,mat,viewer,0,0));
1273   PetscCall((*mat->ops->load)(mat,viewer));
1274   PetscCall(PetscLogEventEnd(MAT_Load,mat,viewer,0,0));
1275   PetscFunctionReturn(0);
1276 }
1277 
1278 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1279 {
1280   Mat_Redundant *redund = *redundant;
1281 
1282   PetscFunctionBegin;
1283   if (redund) {
1284     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1285       PetscCall(ISDestroy(&redund->isrow));
1286       PetscCall(ISDestroy(&redund->iscol));
1287       PetscCall(MatDestroySubMatrices(1,&redund->matseq));
1288     } else {
1289       PetscCall(PetscFree2(redund->send_rank,redund->recv_rank));
1290       PetscCall(PetscFree(redund->sbuf_j));
1291       PetscCall(PetscFree(redund->sbuf_a));
1292       for (PetscInt i=0; i<redund->nrecvs; i++) {
1293         PetscCall(PetscFree(redund->rbuf_j[i]));
1294         PetscCall(PetscFree(redund->rbuf_a[i]));
1295       }
1296       PetscCall(PetscFree4(redund->sbuf_nz,redund->rbuf_nz,redund->rbuf_j,redund->rbuf_a));
1297     }
1298 
1299     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1300     PetscCall(PetscFree(redund));
1301   }
1302   PetscFunctionReturn(0);
1303 }
1304 
1305 /*@C
1306    MatDestroy - Frees space taken by a matrix.
1307 
1308    Collective on Mat
1309 
1310    Input Parameter:
1311 .  A - the matrix
1312 
1313    Level: beginner
1314 
1315    Developer Notes:
1316    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1317    MatDestroySubMatrices(). Thus one must be sure that any changes here must also be made in those routines.
1318    MatHeaderMerge() and MatHeaderReplace() also manipulate the data in the Mat object and likely need changes
1319    if changes are needed here.
1320 @*/
1321 PetscErrorCode MatDestroy(Mat *A)
1322 {
1323   PetscFunctionBegin;
1324   if (!*A) PetscFunctionReturn(0);
1325   PetscValidHeaderSpecific(*A,MAT_CLASSID,1);
1326   if (--((PetscObject)(*A))->refct > 0) {*A = NULL; PetscFunctionReturn(0);}
1327 
1328   /* if memory was published with SAWs then destroy it */
1329   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1330   if ((*A)->ops->destroy) PetscCall((*(*A)->ops->destroy)(*A));
1331 
1332   PetscCall(PetscFree((*A)->factorprefix));
1333   PetscCall(PetscFree((*A)->defaultvectype));
1334   PetscCall(PetscFree((*A)->bsizes));
1335   PetscCall(PetscFree((*A)->solvertype));
1336   for (PetscInt i=0; i<MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1337   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1338   PetscCall(MatProductClear(*A));
1339   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1340   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1341   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1342   PetscCall(MatDestroy(&(*A)->schur));
1343   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1344   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1345   PetscCall(PetscHeaderDestroy(A));
1346   PetscFunctionReturn(0);
1347 }
1348 
1349 /*@C
1350    MatSetValues - Inserts or adds a block of values into a matrix.
1351    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
1352    MUST be called after all calls to MatSetValues() have been completed.
1353 
1354    Not Collective
1355 
1356    Input Parameters:
1357 +  mat - the matrix
1358 .  v - a logically two-dimensional array of values
1359 .  m, idxm - the number of rows and their global indices
1360 .  n, idxn - the number of columns and their global indices
1361 -  addv - either ADD_VALUES or INSERT_VALUES, where
1362    ADD_VALUES adds values to any existing entries, and
1363    INSERT_VALUES replaces existing entries with new values
1364 
1365    Notes:
1366    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
1367       MatSetUp() before using this routine
1368 
1369    By default the values, v, are row-oriented. See MatSetOption() for other options.
1370 
1371    Calls to MatSetValues() with the INSERT_VALUES and ADD_VALUES
1372    options cannot be mixed without intervening calls to the assembly
1373    routines.
1374 
1375    MatSetValues() uses 0-based row and column numbers in Fortran
1376    as well as in C.
1377 
1378    Negative indices may be passed in idxm and idxn, these rows and columns are
1379    simply ignored. This allows easily inserting element stiffness matrices
1380    with homogeneous Dirchlet boundary conditions that you don't want represented
1381    in the matrix.
1382 
1383    Efficiency Alert:
1384    The routine MatSetValuesBlocked() may offer much better efficiency
1385    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1386 
1387    Level: beginner
1388 
1389    Developer Notes:
1390     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1391                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1392 
1393 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1394           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1395 @*/
1396 PetscErrorCode MatSetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1397 {
1398   PetscFunctionBeginHot;
1399   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1400   PetscValidType(mat,1);
1401   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1402   PetscValidIntPointer(idxm,3);
1403   PetscValidIntPointer(idxn,5);
1404   MatCheckPreallocated(mat,1);
1405 
1406   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1407   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1408 
1409   if (PetscDefined(USE_DEBUG)) {
1410     PetscInt       i,j;
1411 
1412     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1413     PetscCheck(mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1414 
1415     for (i=0; i<m; i++) {
1416       for (j=0; j<n; j++) {
1417         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i*n+j]))
1418 #if defined(PETSC_USE_COMPLEX)
1419           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")",(double)PetscRealPart(v[i*n+j]),(double)PetscImaginaryPart(v[i*n+j]),idxm[i],idxn[j]);
1420 #else
1421           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")",(double)v[i*n+j],idxm[i],idxn[j]);
1422 #endif
1423       }
1424     }
1425     for (i=0; i<m; i++) PetscCheck(idxm[i] < mat->rmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT,idxm[i],mat->rmap->N-1);
1426     for (i=0; i<n; i++) PetscCheck(idxn[i] < mat->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT,idxn[i],mat->cmap->N-1);
1427   }
1428 
1429   if (mat->assembled) {
1430     mat->was_assembled = PETSC_TRUE;
1431     mat->assembled     = PETSC_FALSE;
1432   }
1433   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1434   PetscCall((*mat->ops->setvalues)(mat,m,idxm,n,idxn,v,addv));
1435   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1436   PetscFunctionReturn(0);
1437 }
1438 
1439 /*@C
1440    MatSetValuesIS - Inserts or adds a block of values into a matrix using IS to indicate the rows and columns
1441    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
1442    MUST be called after all calls to MatSetValues() have been completed.
1443 
1444    Not Collective
1445 
1446    Input Parameters:
1447 +  mat - the matrix
1448 .  v - a logically two-dimensional array of values
1449 .  ism - the rows to provide
1450 .  isn - the columns to provide
1451 -  addv - either ADD_VALUES or INSERT_VALUES, where
1452    ADD_VALUES adds values to any existing entries, and
1453    INSERT_VALUES replaces existing entries with new values
1454 
1455    Notes:
1456    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
1457       MatSetUp() before using this routine
1458 
1459    By default the values, v, are row-oriented. See MatSetOption() for other options.
1460 
1461    Calls to MatSetValues() with the INSERT_VALUES and ADD_VALUES
1462    options cannot be mixed without intervening calls to the assembly
1463    routines.
1464 
1465    MatSetValues() uses 0-based row and column numbers in Fortran
1466    as well as in C.
1467 
1468    Negative indices may be passed in ism and isn, these rows and columns are
1469    simply ignored. This allows easily inserting element stiffness matrices
1470    with homogeneous Dirchlet boundary conditions that you don't want represented
1471    in the matrix.
1472 
1473    Efficiency Alert:
1474    The routine MatSetValuesBlocked() may offer much better efficiency
1475    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1476 
1477    Level: beginner
1478 
1479    Developer Notes:
1480     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1481                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1482 
1483     This is currently not optimized for any particular IS type
1484 
1485 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal(),
1486           InsertMode, INSERT_VALUES, ADD_VALUES, MatSetValues()
1487 @*/
1488 PetscErrorCode MatSetValuesIS(Mat mat,IS ism,IS isn,const PetscScalar v[],InsertMode addv)
1489 {
1490   PetscInt       m,n;
1491   const PetscInt *rows,*cols;
1492 
1493   PetscFunctionBeginHot;
1494   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1495   PetscCall(ISGetIndices(ism,&rows));
1496   PetscCall(ISGetIndices(isn,&cols));
1497   PetscCall(ISGetLocalSize(ism,&m));
1498   PetscCall(ISGetLocalSize(isn,&n));
1499   PetscCall(MatSetValues(mat,m,rows,n,cols,v,addv));
1500   PetscCall(ISRestoreIndices(ism,&rows));
1501   PetscCall(ISRestoreIndices(isn,&cols));
1502   PetscFunctionReturn(0);
1503 }
1504 
1505 /*@
1506    MatSetValuesRowLocal - Inserts a row (block row for BAIJ matrices) of nonzero
1507         values into a matrix
1508 
1509    Not Collective
1510 
1511    Input Parameters:
1512 +  mat - the matrix
1513 .  row - the (block) row to set
1514 -  v - a logically two-dimensional array of values
1515 
1516    Notes:
1517    By the values, v, are column-oriented (for the block version) and sorted
1518 
1519    All the nonzeros in the row must be provided
1520 
1521    The matrix must have previously had its column indices set
1522 
1523    The row must belong to this process
1524 
1525    Level: intermediate
1526 
1527 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1528           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1529 @*/
1530 PetscErrorCode MatSetValuesRowLocal(Mat mat,PetscInt row,const PetscScalar v[])
1531 {
1532   PetscInt globalrow;
1533 
1534   PetscFunctionBegin;
1535   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1536   PetscValidType(mat,1);
1537   PetscValidScalarPointer(v,3);
1538   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,1,&row,&globalrow));
1539   PetscCall(MatSetValuesRow(mat,globalrow,v));
1540   PetscFunctionReturn(0);
1541 }
1542 
1543 /*@
1544    MatSetValuesRow - Inserts a row (block row for BAIJ matrices) of nonzero
1545         values into a matrix
1546 
1547    Not Collective
1548 
1549    Input Parameters:
1550 +  mat - the matrix
1551 .  row - the (block) row to set
1552 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1553 
1554    Notes:
1555    The values, v, are column-oriented for the block version.
1556 
1557    All the nonzeros in the row must be provided
1558 
1559    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually MatSetValues() is used.
1560 
1561    The row must belong to this process
1562 
1563    Level: advanced
1564 
1565 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1566           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1567 @*/
1568 PetscErrorCode MatSetValuesRow(Mat mat,PetscInt row,const PetscScalar v[])
1569 {
1570   PetscFunctionBeginHot;
1571   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1572   PetscValidType(mat,1);
1573   MatCheckPreallocated(mat,1);
1574   PetscValidScalarPointer(v,3);
1575   PetscCheck(mat->insertmode != ADD_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add and insert values");
1576   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1577   mat->insertmode = INSERT_VALUES;
1578 
1579   if (mat->assembled) {
1580     mat->was_assembled = PETSC_TRUE;
1581     mat->assembled     = PETSC_FALSE;
1582   }
1583   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1584   PetscCheck(mat->ops->setvaluesrow,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1585   PetscCall((*mat->ops->setvaluesrow)(mat,row,v));
1586   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1587   PetscFunctionReturn(0);
1588 }
1589 
1590 /*@
1591    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1592      Using structured grid indexing
1593 
1594    Not Collective
1595 
1596    Input Parameters:
1597 +  mat - the matrix
1598 .  m - number of rows being entered
1599 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1600 .  n - number of columns being entered
1601 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1602 .  v - a logically two-dimensional array of values
1603 -  addv - either ADD_VALUES or INSERT_VALUES, where
1604    ADD_VALUES adds values to any existing entries, and
1605    INSERT_VALUES replaces existing entries with new values
1606 
1607    Notes:
1608    By default the values, v, are row-oriented.  See MatSetOption() for other options.
1609 
1610    Calls to MatSetValuesStencil() with the INSERT_VALUES and ADD_VALUES
1611    options cannot be mixed without intervening calls to the assembly
1612    routines.
1613 
1614    The grid coordinates are across the entire grid, not just the local portion
1615 
1616    MatSetValuesStencil() uses 0-based row and column numbers in Fortran
1617    as well as in C.
1618 
1619    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1620 
1621    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1622    or call MatSetLocalToGlobalMapping() and MatSetStencil() first.
1623 
1624    The columns and rows in the stencil passed in MUST be contained within the
1625    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1626    if you create a DMDA with an overlap of one grid level and on a particular process its first
1627    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1628    first i index you can use in your column and row indices in MatSetStencil() is 5.
1629 
1630    In Fortran idxm and idxn should be declared as
1631 $     MatStencil idxm(4,m),idxn(4,n)
1632    and the values inserted using
1633 $    idxm(MatStencil_i,1) = i
1634 $    idxm(MatStencil_j,1) = j
1635 $    idxm(MatStencil_k,1) = k
1636 $    idxm(MatStencil_c,1) = c
1637    etc
1638 
1639    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1640    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1641    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1642    DM_BOUNDARY_PERIODIC boundary type.
1643 
1644    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1645    a single value per point) you can skip filling those indices.
1646 
1647    Inspired by the structured grid interface to the HYPRE package
1648    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1649 
1650    Efficiency Alert:
1651    The routine MatSetValuesBlockedStencil() may offer much better efficiency
1652    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1653 
1654    Level: beginner
1655 
1656 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1657           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1658 @*/
1659 PetscErrorCode MatSetValuesStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1660 {
1661   PetscInt       buf[8192],*bufm=NULL,*bufn=NULL,*jdxm,*jdxn;
1662   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1663   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1664 
1665   PetscFunctionBegin;
1666   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1667   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1668   PetscValidType(mat,1);
1669   PetscValidPointer(idxm,3);
1670   PetscValidPointer(idxn,5);
1671 
1672   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1673     jdxm = buf; jdxn = buf+m;
1674   } else {
1675     PetscCall(PetscMalloc2(m,&bufm,n,&bufn));
1676     jdxm = bufm; jdxn = bufn;
1677   }
1678   for (i=0; i<m; i++) {
1679     for (j=0; j<3-sdim; j++) dxm++;
1680     tmp = *dxm++ - starts[0];
1681     for (j=0; j<dim-1; j++) {
1682       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1683       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1684     }
1685     if (mat->stencil.noc) dxm++;
1686     jdxm[i] = tmp;
1687   }
1688   for (i=0; i<n; i++) {
1689     for (j=0; j<3-sdim; j++) dxn++;
1690     tmp = *dxn++ - starts[0];
1691     for (j=0; j<dim-1; j++) {
1692       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1693       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1694     }
1695     if (mat->stencil.noc) dxn++;
1696     jdxn[i] = tmp;
1697   }
1698   PetscCall(MatSetValuesLocal(mat,m,jdxm,n,jdxn,v,addv));
1699   PetscCall(PetscFree2(bufm,bufn));
1700   PetscFunctionReturn(0);
1701 }
1702 
1703 /*@
1704    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1705      Using structured grid indexing
1706 
1707    Not Collective
1708 
1709    Input Parameters:
1710 +  mat - the matrix
1711 .  m - number of rows being entered
1712 .  idxm - grid coordinates for matrix rows being entered
1713 .  n - number of columns being entered
1714 .  idxn - grid coordinates for matrix columns being entered
1715 .  v - a logically two-dimensional array of values
1716 -  addv - either ADD_VALUES or INSERT_VALUES, where
1717    ADD_VALUES adds values to any existing entries, and
1718    INSERT_VALUES replaces existing entries with new values
1719 
1720    Notes:
1721    By default the values, v, are row-oriented and unsorted.
1722    See MatSetOption() for other options.
1723 
1724    Calls to MatSetValuesBlockedStencil() with the INSERT_VALUES and ADD_VALUES
1725    options cannot be mixed without intervening calls to the assembly
1726    routines.
1727 
1728    The grid coordinates are across the entire grid, not just the local portion
1729 
1730    MatSetValuesBlockedStencil() uses 0-based row and column numbers in Fortran
1731    as well as in C.
1732 
1733    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1734 
1735    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1736    or call MatSetBlockSize(), MatSetLocalToGlobalMapping() and MatSetStencil() first.
1737 
1738    The columns and rows in the stencil passed in MUST be contained within the
1739    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1740    if you create a DMDA with an overlap of one grid level and on a particular process its first
1741    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1742    first i index you can use in your column and row indices in MatSetStencil() is 5.
1743 
1744    In Fortran idxm and idxn should be declared as
1745 $     MatStencil idxm(4,m),idxn(4,n)
1746    and the values inserted using
1747 $    idxm(MatStencil_i,1) = i
1748 $    idxm(MatStencil_j,1) = j
1749 $    idxm(MatStencil_k,1) = k
1750    etc
1751 
1752    Negative indices may be passed in idxm and idxn, these rows and columns are
1753    simply ignored. This allows easily inserting element stiffness matrices
1754    with homogeneous Dirchlet boundary conditions that you don't want represented
1755    in the matrix.
1756 
1757    Inspired by the structured grid interface to the HYPRE package
1758    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1759 
1760    Level: beginner
1761 
1762 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1763           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1764           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1765 @*/
1766 PetscErrorCode MatSetValuesBlockedStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1767 {
1768   PetscInt       buf[8192],*bufm=NULL,*bufn=NULL,*jdxm,*jdxn;
1769   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1770   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1771 
1772   PetscFunctionBegin;
1773   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1774   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1775   PetscValidType(mat,1);
1776   PetscValidPointer(idxm,3);
1777   PetscValidPointer(idxn,5);
1778   PetscValidScalarPointer(v,6);
1779 
1780   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1781     jdxm = buf; jdxn = buf+m;
1782   } else {
1783     PetscCall(PetscMalloc2(m,&bufm,n,&bufn));
1784     jdxm = bufm; jdxn = bufn;
1785   }
1786   for (i=0; i<m; i++) {
1787     for (j=0; j<3-sdim; j++) dxm++;
1788     tmp = *dxm++ - starts[0];
1789     for (j=0; j<sdim-1; j++) {
1790       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1791       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1792     }
1793     dxm++;
1794     jdxm[i] = tmp;
1795   }
1796   for (i=0; i<n; i++) {
1797     for (j=0; j<3-sdim; j++) dxn++;
1798     tmp = *dxn++ - starts[0];
1799     for (j=0; j<sdim-1; j++) {
1800       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1801       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1802     }
1803     dxn++;
1804     jdxn[i] = tmp;
1805   }
1806   PetscCall(MatSetValuesBlockedLocal(mat,m,jdxm,n,jdxn,v,addv));
1807   PetscCall(PetscFree2(bufm,bufn));
1808   PetscFunctionReturn(0);
1809 }
1810 
1811 /*@
1812    MatSetStencil - Sets the grid information for setting values into a matrix via
1813         MatSetValuesStencil()
1814 
1815    Not Collective
1816 
1817    Input Parameters:
1818 +  mat - the matrix
1819 .  dim - dimension of the grid 1, 2, or 3
1820 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1821 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1822 -  dof - number of degrees of freedom per node
1823 
1824    Inspired by the structured grid interface to the HYPRE package
1825    (www.llnl.gov/CASC/hyper)
1826 
1827    For matrices generated with DMCreateMatrix() this routine is automatically called and so not needed by the
1828    user.
1829 
1830    Level: beginner
1831 
1832 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1833           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1834 @*/
1835 PetscErrorCode MatSetStencil(Mat mat,PetscInt dim,const PetscInt dims[],const PetscInt starts[],PetscInt dof)
1836 {
1837   PetscFunctionBegin;
1838   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1839   PetscValidIntPointer(dims,3);
1840   PetscValidIntPointer(starts,4);
1841 
1842   mat->stencil.dim = dim + (dof > 1);
1843   for (PetscInt i=0; i<dim; i++) {
1844     mat->stencil.dims[i]   = dims[dim-i-1];      /* copy the values in backwards */
1845     mat->stencil.starts[i] = starts[dim-i-1];
1846   }
1847   mat->stencil.dims[dim]   = dof;
1848   mat->stencil.starts[dim] = 0;
1849   mat->stencil.noc         = (PetscBool)(dof == 1);
1850   PetscFunctionReturn(0);
1851 }
1852 
1853 /*@C
1854    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1855 
1856    Not Collective
1857 
1858    Input Parameters:
1859 +  mat - the matrix
1860 .  v - a logically two-dimensional array of values
1861 .  m, idxm - the number of block rows and their global block indices
1862 .  n, idxn - the number of block columns and their global block indices
1863 -  addv - either ADD_VALUES or INSERT_VALUES, where
1864    ADD_VALUES adds values to any existing entries, and
1865    INSERT_VALUES replaces existing entries with new values
1866 
1867    Notes:
1868    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call
1869    MatXXXXSetPreallocation() or MatSetUp() before using this routine.
1870 
1871    The m and n count the NUMBER of blocks in the row direction and column direction,
1872    NOT the total number of rows/columns; for example, if the block size is 2 and
1873    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1874    The values in idxm would be 1 2; that is the first index for each block divided by
1875    the block size.
1876 
1877    Note that you must call MatSetBlockSize() when constructing this matrix (before
1878    preallocating it).
1879 
1880    By default the values, v, are row-oriented, so the layout of
1881    v is the same as for MatSetValues(). See MatSetOption() for other options.
1882 
1883    Calls to MatSetValuesBlocked() with the INSERT_VALUES and ADD_VALUES
1884    options cannot be mixed without intervening calls to the assembly
1885    routines.
1886 
1887    MatSetValuesBlocked() uses 0-based row and column numbers in Fortran
1888    as well as in C.
1889 
1890    Negative indices may be passed in idxm and idxn, these rows and columns are
1891    simply ignored. This allows easily inserting element stiffness matrices
1892    with homogeneous Dirchlet boundary conditions that you don't want represented
1893    in the matrix.
1894 
1895    Each time an entry is set within a sparse matrix via MatSetValues(),
1896    internal searching must be done to determine where to place the
1897    data in the matrix storage space.  By instead inserting blocks of
1898    entries via MatSetValuesBlocked(), the overhead of matrix assembly is
1899    reduced.
1900 
1901    Example:
1902 $   Suppose m=n=2 and block size(bs) = 2 The array is
1903 $
1904 $   1  2  | 3  4
1905 $   5  6  | 7  8
1906 $   - - - | - - -
1907 $   9  10 | 11 12
1908 $   13 14 | 15 16
1909 $
1910 $   v[] should be passed in like
1911 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1912 $
1913 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1914 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1915 
1916    Level: intermediate
1917 
1918 .seealso: `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1919 @*/
1920 PetscErrorCode MatSetValuesBlocked(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1921 {
1922   PetscFunctionBeginHot;
1923   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1924   PetscValidType(mat,1);
1925   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1926   PetscValidIntPointer(idxm,3);
1927   PetscValidIntPointer(idxn,5);
1928   MatCheckPreallocated(mat,1);
1929   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1930   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1931   if (PetscDefined(USE_DEBUG)) {
1932     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1933     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1934   }
1935   if (PetscDefined(USE_DEBUG)) {
1936     PetscInt rbs,cbs,M,N,i;
1937     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
1938     PetscCall(MatGetSize(mat,&M,&N));
1939     for (i=0; i<m; i++) PetscCheck(idxm[i]*rbs < M,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT,i,idxm[i],M);
1940     for (i=0; i<n; i++) PetscCheck(idxn[i]*cbs < N,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT,i,idxn[i],N);
1941   }
1942   if (mat->assembled) {
1943     mat->was_assembled = PETSC_TRUE;
1944     mat->assembled     = PETSC_FALSE;
1945   }
1946   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1947   if (mat->ops->setvaluesblocked) {
1948     PetscCall((*mat->ops->setvaluesblocked)(mat,m,idxm,n,idxn,v,addv));
1949   } else {
1950     PetscInt buf[8192],*bufr=NULL,*bufc=NULL,*iidxm,*iidxn;
1951     PetscInt i,j,bs,cbs;
1952 
1953     PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
1954     if (m*bs+n*cbs <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1955       iidxm = buf;
1956       iidxn = buf + m*bs;
1957     } else {
1958       PetscCall(PetscMalloc2(m*bs,&bufr,n*cbs,&bufc));
1959       iidxm = bufr;
1960       iidxn = bufc;
1961     }
1962     for (i=0; i<m; i++) {
1963       for (j=0; j<bs; j++) {
1964         iidxm[i*bs+j] = bs*idxm[i] + j;
1965       }
1966     }
1967     if (m != n || bs != cbs || idxm != idxn) {
1968       for (i=0; i<n; i++) {
1969         for (j=0; j<cbs; j++) {
1970           iidxn[i*cbs+j] = cbs*idxn[i] + j;
1971         }
1972       }
1973     } else iidxn = iidxm;
1974     PetscCall(MatSetValues(mat,m*bs,iidxm,n*cbs,iidxn,v,addv));
1975     PetscCall(PetscFree2(bufr,bufc));
1976   }
1977   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1978   PetscFunctionReturn(0);
1979 }
1980 
1981 /*@C
1982    MatGetValues - Gets a block of values from a matrix.
1983 
1984    Not Collective; can only return values that are owned by the give process
1985 
1986    Input Parameters:
1987 +  mat - the matrix
1988 .  v - a logically two-dimensional array for storing the values
1989 .  m, idxm - the number of rows and their global indices
1990 -  n, idxn - the number of columns and their global indices
1991 
1992    Notes:
1993      The user must allocate space (m*n PetscScalars) for the values, v.
1994      The values, v, are then returned in a row-oriented format,
1995      analogous to that used by default in MatSetValues().
1996 
1997      MatGetValues() uses 0-based row and column numbers in
1998      Fortran as well as in C.
1999 
2000      MatGetValues() requires that the matrix has been assembled
2001      with MatAssemblyBegin()/MatAssemblyEnd().  Thus, calls to
2002      MatSetValues() and MatGetValues() CANNOT be made in succession
2003      without intermediate matrix assembly.
2004 
2005      Negative row or column indices will be ignored and those locations in v[] will be
2006      left unchanged.
2007 
2008      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2009      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2010      from MatGetOwnershipRange(mat,&rstart,&rend).
2011 
2012    Level: advanced
2013 
2014 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2015 @*/
2016 PetscErrorCode MatGetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
2017 {
2018   PetscFunctionBegin;
2019   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2020   PetscValidType(mat,1);
2021   if (!m || !n) PetscFunctionReturn(0);
2022   PetscValidIntPointer(idxm,3);
2023   PetscValidIntPointer(idxn,5);
2024   PetscValidScalarPointer(v,6);
2025   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2026   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2027   PetscCheck(mat->ops->getvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2028   MatCheckPreallocated(mat,1);
2029 
2030   PetscCall(PetscLogEventBegin(MAT_GetValues,mat,0,0,0));
2031   PetscCall((*mat->ops->getvalues)(mat,m,idxm,n,idxn,v));
2032   PetscCall(PetscLogEventEnd(MAT_GetValues,mat,0,0,0));
2033   PetscFunctionReturn(0);
2034 }
2035 
2036 /*@C
2037    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2038      defined previously by MatSetLocalToGlobalMapping()
2039 
2040    Not Collective
2041 
2042    Input Parameters:
2043 +  mat - the matrix
2044 .  nrow, irow - number of rows and their local indices
2045 -  ncol, icol - number of columns and their local indices
2046 
2047    Output Parameter:
2048 .  y -  a logically two-dimensional array of values
2049 
2050    Notes:
2051      If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine.
2052 
2053      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2054      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from MatGetOwnershipRange(mat,&rstart,&rend). One can
2055      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the ISLocalToGlobalMapping set
2056      with MatSetLocalToGlobalMapping().
2057 
2058    Developer Notes:
2059       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2060       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2061 
2062    Level: advanced
2063 
2064 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2065           `MatSetValuesLocal()`, `MatGetValues()`
2066 @*/
2067 PetscErrorCode MatGetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],PetscScalar y[])
2068 {
2069   PetscFunctionBeginHot;
2070   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2071   PetscValidType(mat,1);
2072   MatCheckPreallocated(mat,1);
2073   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2074   PetscValidIntPointer(irow,3);
2075   PetscValidIntPointer(icol,5);
2076   if (PetscDefined(USE_DEBUG)) {
2077     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2078     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2079   }
2080   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2081   PetscCall(PetscLogEventBegin(MAT_GetValues,mat,0,0,0));
2082   if (mat->ops->getvalueslocal) {
2083     PetscCall((*mat->ops->getvalueslocal)(mat,nrow,irow,ncol,icol,y));
2084   } else {
2085     PetscInt buf[8192],*bufr=NULL,*bufc=NULL,*irowm,*icolm;
2086     if ((nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2087       irowm = buf; icolm = buf+nrow;
2088     } else {
2089       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2090       irowm = bufr; icolm = bufc;
2091     }
2092     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2093     PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2094     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,irowm));
2095     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,icolm));
2096     PetscCall(MatGetValues(mat,nrow,irowm,ncol,icolm,y));
2097     PetscCall(PetscFree2(bufr,bufc));
2098   }
2099   PetscCall(PetscLogEventEnd(MAT_GetValues,mat,0,0,0));
2100   PetscFunctionReturn(0);
2101 }
2102 
2103 /*@
2104   MatSetValuesBatch - Adds (ADD_VALUES) many blocks of values into a matrix at once. The blocks must all be square and
2105   the same size. Currently, this can only be called once and creates the given matrix.
2106 
2107   Not Collective
2108 
2109   Input Parameters:
2110 + mat - the matrix
2111 . nb - the number of blocks
2112 . bs - the number of rows (and columns) in each block
2113 . rows - a concatenation of the rows for each block
2114 - v - a concatenation of logically two-dimensional arrays of values
2115 
2116   Notes:
2117   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2118 
2119   Level: advanced
2120 
2121 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2122           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
2123 @*/
2124 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2125 {
2126   PetscFunctionBegin;
2127   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2128   PetscValidType(mat,1);
2129   PetscValidIntPointer(rows,4);
2130   PetscValidScalarPointer(v,5);
2131   PetscAssert(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2132 
2133   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch,mat,0,0,0));
2134   if (mat->ops->setvaluesbatch) {
2135     PetscCall((*mat->ops->setvaluesbatch)(mat,nb,bs,rows,v));
2136   } else {
2137     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b*bs], bs, &rows[b*bs], &v[b*bs*bs], ADD_VALUES));
2138   }
2139   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch,mat,0,0,0));
2140   PetscFunctionReturn(0);
2141 }
2142 
2143 /*@
2144    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2145    the routine MatSetValuesLocal() to allow users to insert matrix entries
2146    using a local (per-processor) numbering.
2147 
2148    Not Collective
2149 
2150    Input Parameters:
2151 +  x - the matrix
2152 .  rmapping - row mapping created with ISLocalToGlobalMappingCreate() or ISLocalToGlobalMappingCreateIS()
2153 -  cmapping - column mapping
2154 
2155    Level: intermediate
2156 
2157 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2158 @*/
2159 PetscErrorCode MatSetLocalToGlobalMapping(Mat x,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
2160 {
2161   PetscFunctionBegin;
2162   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
2163   PetscValidType(x,1);
2164   if (rmapping) PetscValidHeaderSpecific(rmapping,IS_LTOGM_CLASSID,2);
2165   if (cmapping) PetscValidHeaderSpecific(cmapping,IS_LTOGM_CLASSID,3);
2166   if (x->ops->setlocaltoglobalmapping) {
2167     PetscCall((*x->ops->setlocaltoglobalmapping)(x,rmapping,cmapping));
2168   } else {
2169     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap,rmapping));
2170     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap,cmapping));
2171   }
2172   PetscFunctionReturn(0);
2173 }
2174 
2175 /*@
2176    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by MatSetLocalToGlobalMapping()
2177 
2178    Not Collective
2179 
2180    Input Parameter:
2181 .  A - the matrix
2182 
2183    Output Parameters:
2184 + rmapping - row mapping
2185 - cmapping - column mapping
2186 
2187    Level: advanced
2188 
2189 .seealso: `MatSetValuesLocal()`
2190 @*/
2191 PetscErrorCode MatGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping)
2192 {
2193   PetscFunctionBegin;
2194   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2195   PetscValidType(A,1);
2196   if (rmapping) {
2197     PetscValidPointer(rmapping,2);
2198     *rmapping = A->rmap->mapping;
2199   }
2200   if (cmapping) {
2201     PetscValidPointer(cmapping,3);
2202     *cmapping = A->cmap->mapping;
2203   }
2204   PetscFunctionReturn(0);
2205 }
2206 
2207 /*@
2208    MatSetLayouts - Sets the PetscLayout objects for rows and columns of a matrix
2209 
2210    Logically Collective on A
2211 
2212    Input Parameters:
2213 +  A - the matrix
2214 . rmap - row layout
2215 - cmap - column layout
2216 
2217    Level: advanced
2218 
2219 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2220 @*/
2221 PetscErrorCode MatSetLayouts(Mat A,PetscLayout rmap,PetscLayout cmap)
2222 {
2223   PetscFunctionBegin;
2224   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2225   PetscCall(PetscLayoutReference(rmap,&A->rmap));
2226   PetscCall(PetscLayoutReference(cmap,&A->cmap));
2227   PetscFunctionReturn(0);
2228 }
2229 
2230 /*@
2231    MatGetLayouts - Gets the PetscLayout objects for rows and columns
2232 
2233    Not Collective
2234 
2235    Input Parameter:
2236 .  A - the matrix
2237 
2238    Output Parameters:
2239 + rmap - row layout
2240 - cmap - column layout
2241 
2242    Level: advanced
2243 
2244 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2245 @*/
2246 PetscErrorCode MatGetLayouts(Mat A,PetscLayout *rmap,PetscLayout *cmap)
2247 {
2248   PetscFunctionBegin;
2249   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2250   PetscValidType(A,1);
2251   if (rmap) {
2252     PetscValidPointer(rmap,2);
2253     *rmap = A->rmap;
2254   }
2255   if (cmap) {
2256     PetscValidPointer(cmap,3);
2257     *cmap = A->cmap;
2258   }
2259   PetscFunctionReturn(0);
2260 }
2261 
2262 /*@C
2263    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2264    using a local numbering of the nodes.
2265 
2266    Not Collective
2267 
2268    Input Parameters:
2269 +  mat - the matrix
2270 .  nrow, irow - number of rows and their local indices
2271 .  ncol, icol - number of columns and their local indices
2272 .  y -  a logically two-dimensional array of values
2273 -  addv - either INSERT_VALUES or ADD_VALUES, where
2274    ADD_VALUES adds values to any existing entries, and
2275    INSERT_VALUES replaces existing entries with new values
2276 
2277    Notes:
2278    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2279       MatSetUp() before using this routine
2280 
2281    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine
2282 
2283    Calls to MatSetValuesLocal() with the INSERT_VALUES and ADD_VALUES
2284    options cannot be mixed without intervening calls to the assembly
2285    routines.
2286 
2287    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2288    MUST be called after all calls to MatSetValuesLocal() have been completed.
2289 
2290    Level: intermediate
2291 
2292    Developer Notes:
2293     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2294                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2295 
2296 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2297           `MatSetValueLocal()`, `MatGetValuesLocal()`
2298 @*/
2299 PetscErrorCode MatSetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2300 {
2301   PetscFunctionBeginHot;
2302   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2303   PetscValidType(mat,1);
2304   MatCheckPreallocated(mat,1);
2305   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2306   PetscValidIntPointer(irow,3);
2307   PetscValidIntPointer(icol,5);
2308   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2309   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2310   if (PetscDefined(USE_DEBUG)) {
2311     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2312     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2313   }
2314 
2315   if (mat->assembled) {
2316     mat->was_assembled = PETSC_TRUE;
2317     mat->assembled     = PETSC_FALSE;
2318   }
2319   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
2320   if (mat->ops->setvalueslocal) {
2321     PetscCall((*mat->ops->setvalueslocal)(mat,nrow,irow,ncol,icol,y,addv));
2322   } else {
2323     PetscInt       buf[8192],*bufr=NULL,*bufc=NULL;
2324     const PetscInt *irowm,*icolm;
2325 
2326     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2327       bufr  = buf;
2328       bufc  = buf + nrow;
2329       irowm = bufr;
2330       icolm = bufc;
2331     } else {
2332       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2333       irowm = bufr;
2334       icolm = bufc;
2335     }
2336     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,bufr));
2337     else irowm = irow;
2338     if (mat->cmap->mapping) {
2339       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2340         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,bufc));
2341       } else icolm = irowm;
2342     } else icolm = icol;
2343     PetscCall(MatSetValues(mat,nrow,irowm,ncol,icolm,y,addv));
2344     if (bufr != buf) PetscCall(PetscFree2(bufr,bufc));
2345   }
2346   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
2347   PetscFunctionReturn(0);
2348 }
2349 
2350 /*@C
2351    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2352    using a local ordering of the nodes a block at a time.
2353 
2354    Not Collective
2355 
2356    Input Parameters:
2357 +  x - the matrix
2358 .  nrow, irow - number of rows and their local indices
2359 .  ncol, icol - number of columns and their local indices
2360 .  y -  a logically two-dimensional array of values
2361 -  addv - either INSERT_VALUES or ADD_VALUES, where
2362    ADD_VALUES adds values to any existing entries, and
2363    INSERT_VALUES replaces existing entries with new values
2364 
2365    Notes:
2366    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2367       MatSetUp() before using this routine
2368 
2369    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetBlockSize() and MatSetLocalToGlobalMapping()
2370       before using this routineBefore calling MatSetValuesLocal(), the user must first set the
2371 
2372    Calls to MatSetValuesBlockedLocal() with the INSERT_VALUES and ADD_VALUES
2373    options cannot be mixed without intervening calls to the assembly
2374    routines.
2375 
2376    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2377    MUST be called after all calls to MatSetValuesBlockedLocal() have been completed.
2378 
2379    Level: intermediate
2380 
2381    Developer Notes:
2382     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2383                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2384 
2385 .seealso: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2386           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2387 @*/
2388 PetscErrorCode MatSetValuesBlockedLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2389 {
2390   PetscFunctionBeginHot;
2391   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2392   PetscValidType(mat,1);
2393   MatCheckPreallocated(mat,1);
2394   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2395   PetscValidIntPointer(irow,3);
2396   PetscValidIntPointer(icol,5);
2397   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2398   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2399   if (PetscDefined(USE_DEBUG)) {
2400     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2401     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2402   }
2403 
2404   if (mat->assembled) {
2405     mat->was_assembled = PETSC_TRUE;
2406     mat->assembled     = PETSC_FALSE;
2407   }
2408   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2409     PetscInt irbs, rbs;
2410     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2411     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&irbs));
2412     PetscCheck(rbs == irbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT,rbs,irbs);
2413   }
2414   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2415     PetscInt icbs, cbs;
2416     PetscCall(MatGetBlockSizes(mat,NULL,&cbs));
2417     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&icbs));
2418     PetscCheck(cbs == icbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT,cbs,icbs);
2419   }
2420   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
2421   if (mat->ops->setvaluesblockedlocal) {
2422     PetscCall((*mat->ops->setvaluesblockedlocal)(mat,nrow,irow,ncol,icol,y,addv));
2423   } else {
2424     PetscInt       buf[8192],*bufr=NULL,*bufc=NULL;
2425     const PetscInt *irowm,*icolm;
2426 
2427     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2428       bufr  = buf;
2429       bufc  = buf + nrow;
2430       irowm = bufr;
2431       icolm = bufc;
2432     } else {
2433       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2434       irowm = bufr;
2435       icolm = bufc;
2436     }
2437     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping,nrow,irow,bufr));
2438     else irowm = irow;
2439     if (mat->cmap->mapping) {
2440       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2441         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping,ncol,icol,bufc));
2442       } else icolm = irowm;
2443     } else icolm = icol;
2444     PetscCall(MatSetValuesBlocked(mat,nrow,irowm,ncol,icolm,y,addv));
2445     if (bufr != buf) PetscCall(PetscFree2(bufr,bufc));
2446   }
2447   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
2448   PetscFunctionReturn(0);
2449 }
2450 
2451 /*@
2452    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2453 
2454    Collective on Mat
2455 
2456    Input Parameters:
2457 +  mat - the matrix
2458 -  x   - the vector to be multiplied
2459 
2460    Output Parameters:
2461 .  y - the result
2462 
2463    Notes:
2464    The vectors x and y cannot be the same.  I.e., one cannot
2465    call MatMult(A,y,y).
2466 
2467    Level: developer
2468 
2469 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2470 @*/
2471 PetscErrorCode MatMultDiagonalBlock(Mat mat,Vec x,Vec y)
2472 {
2473   PetscFunctionBegin;
2474   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2475   PetscValidType(mat,1);
2476   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2477   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2478 
2479   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2480   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2481   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2482   MatCheckPreallocated(mat,1);
2483 
2484   PetscCheck(mat->ops->multdiagonalblock,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply defined",((PetscObject)mat)->type_name);
2485   PetscCall((*mat->ops->multdiagonalblock)(mat,x,y));
2486   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2487   PetscFunctionReturn(0);
2488 }
2489 
2490 /* --------------------------------------------------------*/
2491 /*@
2492    MatMult - Computes the matrix-vector product, y = Ax.
2493 
2494    Neighbor-wise Collective on Mat
2495 
2496    Input Parameters:
2497 +  mat - the matrix
2498 -  x   - the vector to be multiplied
2499 
2500    Output Parameters:
2501 .  y - the result
2502 
2503    Notes:
2504    The vectors x and y cannot be the same.  I.e., one cannot
2505    call MatMult(A,y,y).
2506 
2507    Level: beginner
2508 
2509 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2510 @*/
2511 PetscErrorCode MatMult(Mat mat,Vec x,Vec y)
2512 {
2513   PetscFunctionBegin;
2514   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2515   PetscValidType(mat,1);
2516   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2517   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2518   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2519   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2520   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2521   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
2522   PetscCheck(mat->rmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,y->map->N);
2523   PetscCheck(mat->cmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,x->map->n);
2524   PetscCheck(mat->rmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,y->map->n);
2525   PetscCall(VecSetErrorIfLocked(y,3));
2526   if (mat->erroriffailure) PetscCall(VecValidValues(x,2,PETSC_TRUE));
2527   MatCheckPreallocated(mat,1);
2528 
2529   PetscCall(VecLockReadPush(x));
2530   PetscCheck(mat->ops->mult,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply defined",((PetscObject)mat)->type_name);
2531   PetscCall(PetscLogEventBegin(MAT_Mult,mat,x,y,0));
2532   PetscCall((*mat->ops->mult)(mat,x,y));
2533   PetscCall(PetscLogEventEnd(MAT_Mult,mat,x,y,0));
2534   if (mat->erroriffailure) PetscCall(VecValidValues(y,3,PETSC_FALSE));
2535   PetscCall(VecLockReadPop(x));
2536   PetscFunctionReturn(0);
2537 }
2538 
2539 /*@
2540    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2541 
2542    Neighbor-wise Collective on Mat
2543 
2544    Input Parameters:
2545 +  mat - the matrix
2546 -  x   - the vector to be multiplied
2547 
2548    Output Parameters:
2549 .  y - the result
2550 
2551    Notes:
2552    The vectors x and y cannot be the same.  I.e., one cannot
2553    call MatMultTranspose(A,y,y).
2554 
2555    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2556    use MatMultHermitianTranspose()
2557 
2558    Level: beginner
2559 
2560 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2561 @*/
2562 PetscErrorCode MatMultTranspose(Mat mat,Vec x,Vec y)
2563 {
2564   PetscErrorCode (*op)(Mat,Vec,Vec) = NULL;
2565 
2566   PetscFunctionBegin;
2567   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2568   PetscValidType(mat,1);
2569   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2570   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2571 
2572   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2573   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2574   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2575   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
2576   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
2577   PetscCheck(mat->cmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,y->map->n);
2578   PetscCheck(mat->rmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,x->map->n);
2579   if (mat->erroriffailure) PetscCall(VecValidValues(x,2,PETSC_TRUE));
2580   MatCheckPreallocated(mat,1);
2581 
2582   if (!mat->ops->multtranspose) {
2583     if (mat->symmetric && mat->ops->mult) op = mat->ops->mult;
2584     PetscCheck(op,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined",((PetscObject)mat)->type_name);
2585   } else op = mat->ops->multtranspose;
2586   PetscCall(PetscLogEventBegin(MAT_MultTranspose,mat,x,y,0));
2587   PetscCall(VecLockReadPush(x));
2588   PetscCall((*op)(mat,x,y));
2589   PetscCall(VecLockReadPop(x));
2590   PetscCall(PetscLogEventEnd(MAT_MultTranspose,mat,x,y,0));
2591   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2592   if (mat->erroriffailure) PetscCall(VecValidValues(y,3,PETSC_FALSE));
2593   PetscFunctionReturn(0);
2594 }
2595 
2596 /*@
2597    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2598 
2599    Neighbor-wise Collective on Mat
2600 
2601    Input Parameters:
2602 +  mat - the matrix
2603 -  x   - the vector to be multilplied
2604 
2605    Output Parameters:
2606 .  y - the result
2607 
2608    Notes:
2609    The vectors x and y cannot be the same.  I.e., one cannot
2610    call MatMultHermitianTranspose(A,y,y).
2611 
2612    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2613 
2614    For real numbers MatMultTranspose() and MatMultHermitianTranspose() are identical.
2615 
2616    Level: beginner
2617 
2618 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2619 @*/
2620 PetscErrorCode MatMultHermitianTranspose(Mat mat,Vec x,Vec y)
2621 {
2622   PetscFunctionBegin;
2623   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2624   PetscValidType(mat,1);
2625   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2626   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2627 
2628   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2629   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2630   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2631   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
2632   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
2633   PetscCheck(mat->cmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,y->map->n);
2634   PetscCheck(mat->rmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,x->map->n);
2635   MatCheckPreallocated(mat,1);
2636 
2637   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose,mat,x,y,0));
2638 #if defined(PETSC_USE_COMPLEX)
2639   if (mat->ops->multhermitiantranspose || (mat->hermitian && mat->ops->mult)) {
2640     PetscCall(VecLockReadPush(x));
2641     if (mat->ops->multhermitiantranspose) {
2642       PetscCall((*mat->ops->multhermitiantranspose)(mat,x,y));
2643     } else {
2644       PetscCall((*mat->ops->mult)(mat,x,y));
2645     }
2646     PetscCall(VecLockReadPop(x));
2647   } else {
2648     Vec w;
2649     PetscCall(VecDuplicate(x,&w));
2650     PetscCall(VecCopy(x,w));
2651     PetscCall(VecConjugate(w));
2652     PetscCall(MatMultTranspose(mat,w,y));
2653     PetscCall(VecDestroy(&w));
2654     PetscCall(VecConjugate(y));
2655   }
2656   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2657 #else
2658   PetscCall(MatMultTranspose(mat,x,y));
2659 #endif
2660   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose,mat,x,y,0));
2661   PetscFunctionReturn(0);
2662 }
2663 
2664 /*@
2665     MatMultAdd -  Computes v3 = v2 + A * v1.
2666 
2667     Neighbor-wise Collective on Mat
2668 
2669     Input Parameters:
2670 +   mat - the matrix
2671 -   v1, v2 - the vectors
2672 
2673     Output Parameters:
2674 .   v3 - the result
2675 
2676     Notes:
2677     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2678     call MatMultAdd(A,v1,v2,v1).
2679 
2680     Level: beginner
2681 
2682 .seealso: `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2683 @*/
2684 PetscErrorCode MatMultAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2685 {
2686   PetscFunctionBegin;
2687   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2688   PetscValidType(mat,1);
2689   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2690   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2691   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2692 
2693   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2694   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2695   PetscCheck(mat->cmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v1->map->N);
2696   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2697      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2698   PetscCheck(mat->rmap->n == v3->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,v3->map->n);
2699   PetscCheck(mat->rmap->n == v2->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,v2->map->n);
2700   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2701   MatCheckPreallocated(mat,1);
2702 
2703   PetscCheck(mat->ops->multadd,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No MatMultAdd() for matrix type %s",((PetscObject)mat)->type_name);
2704   PetscCall(PetscLogEventBegin(MAT_MultAdd,mat,v1,v2,v3));
2705   PetscCall(VecLockReadPush(v1));
2706   PetscCall((*mat->ops->multadd)(mat,v1,v2,v3));
2707   PetscCall(VecLockReadPop(v1));
2708   PetscCall(PetscLogEventEnd(MAT_MultAdd,mat,v1,v2,v3));
2709   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2710   PetscFunctionReturn(0);
2711 }
2712 
2713 /*@
2714    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2715 
2716    Neighbor-wise Collective on Mat
2717 
2718    Input Parameters:
2719 +  mat - the matrix
2720 -  v1, v2 - the vectors
2721 
2722    Output Parameters:
2723 .  v3 - the result
2724 
2725    Notes:
2726    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2727    call MatMultTransposeAdd(A,v1,v2,v1).
2728 
2729    Level: beginner
2730 
2731 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2732 @*/
2733 PetscErrorCode MatMultTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2734 {
2735   PetscErrorCode (*op)(Mat,Vec,Vec,Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2736 
2737   PetscFunctionBegin;
2738   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2739   PetscValidType(mat,1);
2740   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2741   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2742   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2743 
2744   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2745   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2746   PetscCheck(mat->rmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v1->map->N);
2747   PetscCheck(mat->cmap->N == v2->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v2->map->N);
2748   PetscCheck(mat->cmap->N == v3->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v3->map->N);
2749   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2750   PetscCheck(op,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2751   MatCheckPreallocated(mat,1);
2752 
2753   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd,mat,v1,v2,v3));
2754   PetscCall(VecLockReadPush(v1));
2755   PetscCall((*op)(mat,v1,v2,v3));
2756   PetscCall(VecLockReadPop(v1));
2757   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd,mat,v1,v2,v3));
2758   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2759   PetscFunctionReturn(0);
2760 }
2761 
2762 /*@
2763    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2764 
2765    Neighbor-wise Collective on Mat
2766 
2767    Input Parameters:
2768 +  mat - the matrix
2769 -  v1, v2 - the vectors
2770 
2771    Output Parameters:
2772 .  v3 - the result
2773 
2774    Notes:
2775    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2776    call MatMultHermitianTransposeAdd(A,v1,v2,v1).
2777 
2778    Level: beginner
2779 
2780 .seealso: `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2781 @*/
2782 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2783 {
2784   PetscFunctionBegin;
2785   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2786   PetscValidType(mat,1);
2787   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2788   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2789   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2790 
2791   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2792   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2793   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2794   PetscCheck(mat->rmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v1->map->N);
2795   PetscCheck(mat->cmap->N == v2->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v2->map->N);
2796   PetscCheck(mat->cmap->N == v3->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v3->map->N);
2797   MatCheckPreallocated(mat,1);
2798 
2799   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3));
2800   PetscCall(VecLockReadPush(v1));
2801   if (mat->ops->multhermitiantransposeadd) {
2802     PetscCall((*mat->ops->multhermitiantransposeadd)(mat,v1,v2,v3));
2803   } else {
2804     Vec w,z;
2805     PetscCall(VecDuplicate(v1,&w));
2806     PetscCall(VecCopy(v1,w));
2807     PetscCall(VecConjugate(w));
2808     PetscCall(VecDuplicate(v3,&z));
2809     PetscCall(MatMultTranspose(mat,w,z));
2810     PetscCall(VecDestroy(&w));
2811     PetscCall(VecConjugate(z));
2812     if (v2 != v3) {
2813       PetscCall(VecWAXPY(v3,1.0,v2,z));
2814     } else {
2815       PetscCall(VecAXPY(v3,1.0,z));
2816     }
2817     PetscCall(VecDestroy(&z));
2818   }
2819   PetscCall(VecLockReadPop(v1));
2820   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3));
2821   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2822   PetscFunctionReturn(0);
2823 }
2824 
2825 /*@C
2826    MatGetFactorType - gets the type of factorization it is
2827 
2828    Not Collective
2829 
2830    Input Parameters:
2831 .  mat - the matrix
2832 
2833    Output Parameters:
2834 .  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2835 
2836    Level: intermediate
2837 
2838 .seealso: `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`
2839 @*/
2840 PetscErrorCode MatGetFactorType(Mat mat,MatFactorType *t)
2841 {
2842   PetscFunctionBegin;
2843   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2844   PetscValidType(mat,1);
2845   PetscValidPointer(t,2);
2846   *t = mat->factortype;
2847   PetscFunctionReturn(0);
2848 }
2849 
2850 /*@C
2851    MatSetFactorType - sets the type of factorization it is
2852 
2853    Logically Collective on Mat
2854 
2855    Input Parameters:
2856 +  mat - the matrix
2857 -  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2858 
2859    Level: intermediate
2860 
2861 .seealso: `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`
2862 @*/
2863 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2864 {
2865   PetscFunctionBegin;
2866   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2867   PetscValidType(mat,1);
2868   mat->factortype = t;
2869   PetscFunctionReturn(0);
2870 }
2871 
2872 /* ------------------------------------------------------------*/
2873 /*@C
2874    MatGetInfo - Returns information about matrix storage (number of
2875    nonzeros, memory, etc.).
2876 
2877    Collective on Mat if MAT_GLOBAL_MAX or MAT_GLOBAL_SUM is used as the flag
2878 
2879    Input Parameter:
2880 .  mat - the matrix
2881 
2882    Output Parameters:
2883 +  flag - flag indicating the type of parameters to be returned
2884    (MAT_LOCAL - local matrix, MAT_GLOBAL_MAX - maximum over all processors,
2885    MAT_GLOBAL_SUM - sum over all processors)
2886 -  info - matrix information context
2887 
2888    Notes:
2889    The MatInfo context contains a variety of matrix data, including
2890    number of nonzeros allocated and used, number of mallocs during
2891    matrix assembly, etc.  Additional information for factored matrices
2892    is provided (such as the fill ratio, number of mallocs during
2893    factorization, etc.).  Much of this info is printed to PETSC_STDOUT
2894    when using the runtime options
2895 $       -info -mat_view ::ascii_info
2896 
2897    Example for C/C++ Users:
2898    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2899    data within the MatInfo context.  For example,
2900 .vb
2901       MatInfo info;
2902       Mat     A;
2903       double  mal, nz_a, nz_u;
2904 
2905       MatGetInfo(A,MAT_LOCAL,&info);
2906       mal  = info.mallocs;
2907       nz_a = info.nz_allocated;
2908 .ve
2909 
2910    Example for Fortran Users:
2911    Fortran users should declare info as a double precision
2912    array of dimension MAT_INFO_SIZE, and then extract the parameters
2913    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2914    a complete list of parameter names.
2915 .vb
2916       double  precision info(MAT_INFO_SIZE)
2917       double  precision mal, nz_a
2918       Mat     A
2919       integer ierr
2920 
2921       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2922       mal = info(MAT_INFO_MALLOCS)
2923       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2924 .ve
2925 
2926     Level: intermediate
2927 
2928     Developer Note: fortran interface is not autogenerated as the f90
2929     interface definition cannot be generated correctly [due to MatInfo]
2930 
2931 .seealso: `MatStashGetInfo()`
2932 
2933 @*/
2934 PetscErrorCode MatGetInfo(Mat mat,MatInfoType flag,MatInfo *info)
2935 {
2936   PetscFunctionBegin;
2937   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2938   PetscValidType(mat,1);
2939   PetscValidPointer(info,3);
2940   PetscCheck(mat->ops->getinfo,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2941   MatCheckPreallocated(mat,1);
2942   PetscCall((*mat->ops->getinfo)(mat,flag,info));
2943   PetscFunctionReturn(0);
2944 }
2945 
2946 /*
2947    This is used by external packages where it is not easy to get the info from the actual
2948    matrix factorization.
2949 */
2950 PetscErrorCode MatGetInfo_External(Mat A,MatInfoType flag,MatInfo *info)
2951 {
2952   PetscFunctionBegin;
2953   PetscCall(PetscMemzero(info,sizeof(MatInfo)));
2954   PetscFunctionReturn(0);
2955 }
2956 
2957 /* ----------------------------------------------------------*/
2958 
2959 /*@C
2960    MatLUFactor - Performs in-place LU factorization of matrix.
2961 
2962    Collective on Mat
2963 
2964    Input Parameters:
2965 +  mat - the matrix
2966 .  row - row permutation
2967 .  col - column permutation
2968 -  info - options for factorization, includes
2969 $          fill - expected fill as ratio of original fill.
2970 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2971 $                   Run with the option -info to determine an optimal value to use
2972 
2973    Notes:
2974    Most users should employ the simplified KSP interface for linear solvers
2975    instead of working directly with matrix algebra routines such as this.
2976    See, e.g., KSPCreate().
2977 
2978    This changes the state of the matrix to a factored matrix; it cannot be used
2979    for example with MatSetValues() unless one first calls MatSetUnfactored().
2980 
2981    Level: developer
2982 
2983 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2984           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2985 
2986     Developer Note: fortran interface is not autogenerated as the f90
2987     interface definition cannot be generated correctly [due to MatFactorInfo]
2988 
2989 @*/
2990 PetscErrorCode MatLUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
2991 {
2992   MatFactorInfo  tinfo;
2993 
2994   PetscFunctionBegin;
2995   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2996   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
2997   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
2998   if (info) PetscValidPointer(info,4);
2999   PetscValidType(mat,1);
3000   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3001   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3002   PetscCheck(mat->ops->lufactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3003   MatCheckPreallocated(mat,1);
3004   if (!info) {
3005     PetscCall(MatFactorInfoInitialize(&tinfo));
3006     info = &tinfo;
3007   }
3008 
3009   PetscCall(PetscLogEventBegin(MAT_LUFactor,mat,row,col,0));
3010   PetscCall((*mat->ops->lufactor)(mat,row,col,info));
3011   PetscCall(PetscLogEventEnd(MAT_LUFactor,mat,row,col,0));
3012   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3013   PetscFunctionReturn(0);
3014 }
3015 
3016 /*@C
3017    MatILUFactor - Performs in-place ILU factorization of matrix.
3018 
3019    Collective on Mat
3020 
3021    Input Parameters:
3022 +  mat - the matrix
3023 .  row - row permutation
3024 .  col - column permutation
3025 -  info - structure containing
3026 $      levels - number of levels of fill.
3027 $      expected fill - as ratio of original fill.
3028 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3029                 missing diagonal entries)
3030 
3031    Notes:
3032    Probably really in-place only when level of fill is zero, otherwise allocates
3033    new space to store factored matrix and deletes previous memory.
3034 
3035    Most users should employ the simplified KSP interface for linear solvers
3036    instead of working directly with matrix algebra routines such as this.
3037    See, e.g., KSPCreate().
3038 
3039    Level: developer
3040 
3041 .seealso: `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3042 
3043     Developer Note: fortran interface is not autogenerated as the f90
3044     interface definition cannot be generated correctly [due to MatFactorInfo]
3045 
3046 @*/
3047 PetscErrorCode MatILUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
3048 {
3049   PetscFunctionBegin;
3050   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3051   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
3052   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3053   PetscValidPointer(info,4);
3054   PetscValidType(mat,1);
3055   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
3056   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3057   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3058   PetscCheck(mat->ops->ilufactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3059   MatCheckPreallocated(mat,1);
3060 
3061   PetscCall(PetscLogEventBegin(MAT_ILUFactor,mat,row,col,0));
3062   PetscCall((*mat->ops->ilufactor)(mat,row,col,info));
3063   PetscCall(PetscLogEventEnd(MAT_ILUFactor,mat,row,col,0));
3064   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3065   PetscFunctionReturn(0);
3066 }
3067 
3068 /*@C
3069    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3070    Call this routine before calling MatLUFactorNumeric().
3071 
3072    Collective on Mat
3073 
3074    Input Parameters:
3075 +  fact - the factor matrix obtained with MatGetFactor()
3076 .  mat - the matrix
3077 .  row, col - row and column permutations
3078 -  info - options for factorization, includes
3079 $          fill - expected fill as ratio of original fill.
3080 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3081 $                   Run with the option -info to determine an optimal value to use
3082 
3083    Notes:
3084     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
3085 
3086    Most users should employ the simplified KSP interface for linear solvers
3087    instead of working directly with matrix algebra routines such as this.
3088    See, e.g., KSPCreate().
3089 
3090    Level: developer
3091 
3092 .seealso: `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3093 
3094     Developer Note: fortran interface is not autogenerated as the f90
3095     interface definition cannot be generated correctly [due to MatFactorInfo]
3096 
3097 @*/
3098 PetscErrorCode MatLUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
3099 {
3100   MatFactorInfo  tinfo;
3101 
3102   PetscFunctionBegin;
3103   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3104   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
3105   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
3106   if (info) PetscValidPointer(info,5);
3107   PetscValidType(mat,2);
3108   PetscValidPointer(fact,1);
3109   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3110   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3111   if (!(fact)->ops->lufactorsymbolic) {
3112     MatSolverType stype;
3113     PetscCall(MatFactorGetSolverType(fact,&stype));
3114     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic LU using solver package %s",((PetscObject)mat)->type_name,stype);
3115   }
3116   MatCheckPreallocated(mat,2);
3117   if (!info) {
3118     PetscCall(MatFactorInfoInitialize(&tinfo));
3119     info = &tinfo;
3120   }
3121 
3122   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic,mat,row,col,0));
3123   PetscCall((fact->ops->lufactorsymbolic)(fact,mat,row,col,info));
3124   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic,mat,row,col,0));
3125   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3126   PetscFunctionReturn(0);
3127 }
3128 
3129 /*@C
3130    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3131    Call this routine after first calling MatLUFactorSymbolic().
3132 
3133    Collective on Mat
3134 
3135    Input Parameters:
3136 +  fact - the factor matrix obtained with MatGetFactor()
3137 .  mat - the matrix
3138 -  info - options for factorization
3139 
3140    Notes:
3141    See MatLUFactor() for in-place factorization.  See
3142    MatCholeskyFactorNumeric() for the symmetric, positive definite case.
3143 
3144    Most users should employ the simplified KSP interface for linear solvers
3145    instead of working directly with matrix algebra routines such as this.
3146    See, e.g., KSPCreate().
3147 
3148    Level: developer
3149 
3150 .seealso: `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3151 
3152     Developer Note: fortran interface is not autogenerated as the f90
3153     interface definition cannot be generated correctly [due to MatFactorInfo]
3154 
3155 @*/
3156 PetscErrorCode MatLUFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3157 {
3158   MatFactorInfo  tinfo;
3159 
3160   PetscFunctionBegin;
3161   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3162   PetscValidType(mat,2);
3163   PetscValidPointer(fact,1);
3164   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3165   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3166   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3167 
3168   PetscCheck((fact)->ops->lufactornumeric,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric LU",((PetscObject)mat)->type_name);
3169   MatCheckPreallocated(mat,2);
3170   if (!info) {
3171     PetscCall(MatFactorInfoInitialize(&tinfo));
3172     info = &tinfo;
3173   }
3174 
3175   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric,mat,fact,0,0));
3176   else PetscCall(PetscLogEventBegin(MAT_LUFactor,mat,fact,0,0));
3177   PetscCall((fact->ops->lufactornumeric)(fact,mat,info));
3178   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric,mat,fact,0,0));
3179   else PetscCall(PetscLogEventEnd(MAT_LUFactor,mat,fact,0,0));
3180   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3181   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3182   PetscFunctionReturn(0);
3183 }
3184 
3185 /*@C
3186    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3187    symmetric matrix.
3188 
3189    Collective on Mat
3190 
3191    Input Parameters:
3192 +  mat - the matrix
3193 .  perm - row and column permutations
3194 -  f - expected fill as ratio of original fill
3195 
3196    Notes:
3197    See MatLUFactor() for the nonsymmetric case.  See also
3198    MatCholeskyFactorSymbolic(), and MatCholeskyFactorNumeric().
3199 
3200    Most users should employ the simplified KSP interface for linear solvers
3201    instead of working directly with matrix algebra routines such as this.
3202    See, e.g., KSPCreate().
3203 
3204    Level: developer
3205 
3206 .seealso: `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3207           `MatGetOrdering()`
3208 
3209     Developer Note: fortran interface is not autogenerated as the f90
3210     interface definition cannot be generated correctly [due to MatFactorInfo]
3211 
3212 @*/
3213 PetscErrorCode MatCholeskyFactor(Mat mat,IS perm,const MatFactorInfo *info)
3214 {
3215   MatFactorInfo  tinfo;
3216 
3217   PetscFunctionBegin;
3218   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3219   PetscValidType(mat,1);
3220   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,2);
3221   if (info) PetscValidPointer(info,3);
3222   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3223   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3224   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3225   PetscCheck(mat->ops->choleskyfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"In-place factorization for Mat type %s is not supported, try out-of-place factorization. See MatCholeskyFactorSymbolic/Numeric",((PetscObject)mat)->type_name);
3226   MatCheckPreallocated(mat,1);
3227   if (!info) {
3228     PetscCall(MatFactorInfoInitialize(&tinfo));
3229     info = &tinfo;
3230   }
3231 
3232   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor,mat,perm,0,0));
3233   PetscCall((*mat->ops->choleskyfactor)(mat,perm,info));
3234   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor,mat,perm,0,0));
3235   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3236   PetscFunctionReturn(0);
3237 }
3238 
3239 /*@C
3240    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3241    of a symmetric matrix.
3242 
3243    Collective on Mat
3244 
3245    Input Parameters:
3246 +  fact - the factor matrix obtained with MatGetFactor()
3247 .  mat - the matrix
3248 .  perm - row and column permutations
3249 -  info - options for factorization, includes
3250 $          fill - expected fill as ratio of original fill.
3251 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3252 $                   Run with the option -info to determine an optimal value to use
3253 
3254    Notes:
3255    See MatLUFactorSymbolic() for the nonsymmetric case.  See also
3256    MatCholeskyFactor() and MatCholeskyFactorNumeric().
3257 
3258    Most users should employ the simplified KSP interface for linear solvers
3259    instead of working directly with matrix algebra routines such as this.
3260    See, e.g., KSPCreate().
3261 
3262    Level: developer
3263 
3264 .seealso: `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3265           `MatGetOrdering()`
3266 
3267     Developer Note: fortran interface is not autogenerated as the f90
3268     interface definition cannot be generated correctly [due to MatFactorInfo]
3269 
3270 @*/
3271 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
3272 {
3273   MatFactorInfo  tinfo;
3274 
3275   PetscFunctionBegin;
3276   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3277   PetscValidType(mat,2);
3278   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
3279   if (info) PetscValidPointer(info,4);
3280   PetscValidPointer(fact,1);
3281   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3282   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3283   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3284   if (!(fact)->ops->choleskyfactorsymbolic) {
3285     MatSolverType stype;
3286     PetscCall(MatFactorGetSolverType(fact,&stype));
3287     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s symbolic factor Cholesky using solver package %s",((PetscObject)mat)->type_name,stype);
3288   }
3289   MatCheckPreallocated(mat,2);
3290   if (!info) {
3291     PetscCall(MatFactorInfoInitialize(&tinfo));
3292     info = &tinfo;
3293   }
3294 
3295   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic,mat,perm,0,0));
3296   PetscCall((fact->ops->choleskyfactorsymbolic)(fact,mat,perm,info));
3297   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic,mat,perm,0,0));
3298   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3299   PetscFunctionReturn(0);
3300 }
3301 
3302 /*@C
3303    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3304    of a symmetric matrix. Call this routine after first calling
3305    MatCholeskyFactorSymbolic().
3306 
3307    Collective on Mat
3308 
3309    Input Parameters:
3310 +  fact - the factor matrix obtained with MatGetFactor()
3311 .  mat - the initial matrix
3312 .  info - options for factorization
3313 -  fact - the symbolic factor of mat
3314 
3315    Notes:
3316    Most users should employ the simplified KSP interface for linear solvers
3317    instead of working directly with matrix algebra routines such as this.
3318    See, e.g., KSPCreate().
3319 
3320    Level: developer
3321 
3322 .seealso: `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3323 
3324     Developer Note: fortran interface is not autogenerated as the f90
3325     interface definition cannot be generated correctly [due to MatFactorInfo]
3326 
3327 @*/
3328 PetscErrorCode MatCholeskyFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3329 {
3330   MatFactorInfo  tinfo;
3331 
3332   PetscFunctionBegin;
3333   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3334   PetscValidType(mat,2);
3335   PetscValidPointer(fact,1);
3336   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3337   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3338   PetscCheck((fact)->ops->choleskyfactornumeric,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric factor Cholesky",((PetscObject)mat)->type_name);
3339   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3340   MatCheckPreallocated(mat,2);
3341   if (!info) {
3342     PetscCall(MatFactorInfoInitialize(&tinfo));
3343     info = &tinfo;
3344   }
3345 
3346   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric,mat,fact,0,0));
3347   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor,mat,fact,0,0));
3348   PetscCall((fact->ops->choleskyfactornumeric)(fact,mat,info));
3349   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric,mat,fact,0,0));
3350   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor,mat,fact,0,0));
3351   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3352   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3353   PetscFunctionReturn(0);
3354 }
3355 
3356 /*@
3357    MatQRFactor - Performs in-place QR factorization of matrix.
3358 
3359    Collective on Mat
3360 
3361    Input Parameters:
3362 +  mat - the matrix
3363 .  col - column permutation
3364 -  info - options for factorization, includes
3365 $          fill - expected fill as ratio of original fill.
3366 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3367 $                   Run with the option -info to determine an optimal value to use
3368 
3369    Notes:
3370    Most users should employ the simplified KSP interface for linear solvers
3371    instead of working directly with matrix algebra routines such as this.
3372    See, e.g., KSPCreate().
3373 
3374    This changes the state of the matrix to a factored matrix; it cannot be used
3375    for example with MatSetValues() unless one first calls MatSetUnfactored().
3376 
3377    Level: developer
3378 
3379 .seealso: `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3380           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3381 
3382     Developer Note: fortran interface is not autogenerated as the f90
3383     interface definition cannot be generated correctly [due to MatFactorInfo]
3384 
3385 @*/
3386 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3387 {
3388   PetscFunctionBegin;
3389   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3390   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,2);
3391   if (info) PetscValidPointer(info,3);
3392   PetscValidType(mat,1);
3393   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3394   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3395   MatCheckPreallocated(mat,1);
3396   PetscCall(PetscLogEventBegin(MAT_QRFactor,mat,col,0,0));
3397   PetscUseMethod(mat,"MatQRFactor_C", (Mat,IS,const MatFactorInfo*), (mat, col, info));
3398   PetscCall(PetscLogEventEnd(MAT_QRFactor,mat,col,0,0));
3399   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3400   PetscFunctionReturn(0);
3401 }
3402 
3403 /*@
3404    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3405    Call this routine before calling MatQRFactorNumeric().
3406 
3407    Collective on Mat
3408 
3409    Input Parameters:
3410 +  fact - the factor matrix obtained with MatGetFactor()
3411 .  mat - the matrix
3412 .  col - column permutation
3413 -  info - options for factorization, includes
3414 $          fill - expected fill as ratio of original fill.
3415 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3416 $                   Run with the option -info to determine an optimal value to use
3417 
3418    Most users should employ the simplified KSP interface for linear solvers
3419    instead of working directly with matrix algebra routines such as this.
3420    See, e.g., KSPCreate().
3421 
3422    Level: developer
3423 
3424 .seealso: `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3425 
3426     Developer Note: fortran interface is not autogenerated as the f90
3427     interface definition cannot be generated correctly [due to MatFactorInfo]
3428 
3429 @*/
3430 PetscErrorCode MatQRFactorSymbolic(Mat fact,Mat mat,IS col,const MatFactorInfo *info)
3431 {
3432   MatFactorInfo  tinfo;
3433 
3434   PetscFunctionBegin;
3435   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3436   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3437   if (info) PetscValidPointer(info,4);
3438   PetscValidType(mat,2);
3439   PetscValidPointer(fact,1);
3440   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3441   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3442   MatCheckPreallocated(mat,2);
3443   if (!info) {
3444     PetscCall(MatFactorInfoInitialize(&tinfo));
3445     info = &tinfo;
3446   }
3447 
3448   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic,fact,mat,col,0));
3449   PetscUseMethod(fact,"MatQRFactorSymbolic_C", (Mat,Mat,IS,const MatFactorInfo*), (fact, mat, col, info));
3450   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic,fact,mat,col,0));
3451   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3452   PetscFunctionReturn(0);
3453 }
3454 
3455 /*@
3456    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3457    Call this routine after first calling MatQRFactorSymbolic().
3458 
3459    Collective on Mat
3460 
3461    Input Parameters:
3462 +  fact - the factor matrix obtained with MatGetFactor()
3463 .  mat - the matrix
3464 -  info - options for factorization
3465 
3466    Notes:
3467    See MatQRFactor() for in-place factorization.
3468 
3469    Most users should employ the simplified KSP interface for linear solvers
3470    instead of working directly with matrix algebra routines such as this.
3471    See, e.g., KSPCreate().
3472 
3473    Level: developer
3474 
3475 .seealso: `MatQRFactorSymbolic()`, `MatLUFactor()`
3476 
3477     Developer Note: fortran interface is not autogenerated as the f90
3478     interface definition cannot be generated correctly [due to MatFactorInfo]
3479 
3480 @*/
3481 PetscErrorCode MatQRFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3482 {
3483   MatFactorInfo  tinfo;
3484 
3485   PetscFunctionBegin;
3486   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3487   PetscValidType(mat,2);
3488   PetscValidPointer(fact,1);
3489   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3490   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3491   PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3492 
3493   MatCheckPreallocated(mat,2);
3494   if (!info) {
3495     PetscCall(MatFactorInfoInitialize(&tinfo));
3496     info = &tinfo;
3497   }
3498 
3499   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric,mat,fact,0,0));
3500   else  PetscCall(PetscLogEventBegin(MAT_QRFactor,mat,fact,0,0));
3501   PetscUseMethod(fact,"MatQRFactorNumeric_C", (Mat,Mat,const MatFactorInfo*), (fact, mat, info));
3502   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric,mat,fact,0,0));
3503   else PetscCall(PetscLogEventEnd(MAT_QRFactor,mat,fact,0,0));
3504   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3505   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3506   PetscFunctionReturn(0);
3507 }
3508 
3509 /* ----------------------------------------------------------------*/
3510 /*@
3511    MatSolve - Solves A x = b, given a factored matrix.
3512 
3513    Neighbor-wise Collective on Mat
3514 
3515    Input Parameters:
3516 +  mat - the factored matrix
3517 -  b - the right-hand-side vector
3518 
3519    Output Parameter:
3520 .  x - the result vector
3521 
3522    Notes:
3523    The vectors b and x cannot be the same.  I.e., one cannot
3524    call MatSolve(A,x,x).
3525 
3526    Notes:
3527    Most users should employ the simplified KSP interface for linear solvers
3528    instead of working directly with matrix algebra routines such as this.
3529    See, e.g., KSPCreate().
3530 
3531    Level: developer
3532 
3533 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3534 @*/
3535 PetscErrorCode MatSolve(Mat mat,Vec b,Vec x)
3536 {
3537   PetscFunctionBegin;
3538   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3539   PetscValidType(mat,1);
3540   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3541   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3542   PetscCheckSameComm(mat,1,b,2);
3543   PetscCheckSameComm(mat,1,x,3);
3544   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3545   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3546   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3547   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3548   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3549   MatCheckPreallocated(mat,1);
3550 
3551   PetscCall(PetscLogEventBegin(MAT_Solve,mat,b,x,0));
3552   if (mat->factorerrortype) {
3553     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
3554     PetscCall(VecSetInf(x));
3555   } else {
3556     PetscCheck(mat->ops->solve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3557     PetscCall((*mat->ops->solve)(mat,b,x));
3558   }
3559   PetscCall(PetscLogEventEnd(MAT_Solve,mat,b,x,0));
3560   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3561   PetscFunctionReturn(0);
3562 }
3563 
3564 static PetscErrorCode MatMatSolve_Basic(Mat A,Mat B,Mat X,PetscBool trans)
3565 {
3566   Vec            b,x;
3567   PetscInt       N,i;
3568   PetscErrorCode (*f)(Mat,Vec,Vec);
3569   PetscBool      Abound,Bneedconv = PETSC_FALSE,Xneedconv = PETSC_FALSE;
3570 
3571   PetscFunctionBegin;
3572   if (A->factorerrortype) {
3573     PetscCall(PetscInfo(A,"MatFactorError %d\n",A->factorerrortype));
3574     PetscCall(MatSetInf(X));
3575     PetscFunctionReturn(0);
3576   }
3577   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3578   PetscCheck(f,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
3579   PetscCall(MatBoundToCPU(A,&Abound));
3580   if (!Abound) {
3581     PetscCall(PetscObjectTypeCompareAny((PetscObject)B,&Bneedconv,MATSEQDENSE,MATMPIDENSE,""));
3582     PetscCall(PetscObjectTypeCompareAny((PetscObject)X,&Xneedconv,MATSEQDENSE,MATMPIDENSE,""));
3583   }
3584   if (Bneedconv) {
3585     PetscCall(MatConvert(B,MATDENSECUDA,MAT_INPLACE_MATRIX,&B));
3586   }
3587   if (Xneedconv) {
3588     PetscCall(MatConvert(X,MATDENSECUDA,MAT_INPLACE_MATRIX,&X));
3589   }
3590   PetscCall(MatGetSize(B,NULL,&N));
3591   for (i=0; i<N; i++) {
3592     PetscCall(MatDenseGetColumnVecRead(B,i,&b));
3593     PetscCall(MatDenseGetColumnVecWrite(X,i,&x));
3594     PetscCall((*f)(A,b,x));
3595     PetscCall(MatDenseRestoreColumnVecWrite(X,i,&x));
3596     PetscCall(MatDenseRestoreColumnVecRead(B,i,&b));
3597   }
3598   if (Bneedconv) {
3599     PetscCall(MatConvert(B,MATDENSE,MAT_INPLACE_MATRIX,&B));
3600   }
3601   if (Xneedconv) {
3602     PetscCall(MatConvert(X,MATDENSE,MAT_INPLACE_MATRIX,&X));
3603   }
3604   PetscFunctionReturn(0);
3605 }
3606 
3607 /*@
3608    MatMatSolve - Solves A X = B, given a factored matrix.
3609 
3610    Neighbor-wise Collective on Mat
3611 
3612    Input Parameters:
3613 +  A - the factored matrix
3614 -  B - the right-hand-side matrix MATDENSE (or sparse -- when using MUMPS)
3615 
3616    Output Parameter:
3617 .  X - the result matrix (dense matrix)
3618 
3619    Notes:
3620    If B is a MATDENSE matrix then one can call MatMatSolve(A,B,B) except with MKL_CPARDISO;
3621    otherwise, B and X cannot be the same.
3622 
3623    Notes:
3624    Most users should usually employ the simplified KSP interface for linear solvers
3625    instead of working directly with matrix algebra routines such as this.
3626    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3627    at a time.
3628 
3629    Level: developer
3630 
3631 .seealso: `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3632 @*/
3633 PetscErrorCode MatMatSolve(Mat A,Mat B,Mat X)
3634 {
3635   PetscFunctionBegin;
3636   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3637   PetscValidType(A,1);
3638   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3639   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3640   PetscCheckSameComm(A,1,B,2);
3641   PetscCheckSameComm(A,1,X,3);
3642   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3643   PetscCheck(A->rmap->N == B->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N);
3644   PetscCheck(X->cmap->N == B->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as rhs matrix");
3645   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3646   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3647   MatCheckPreallocated(A,1);
3648 
3649   PetscCall(PetscLogEventBegin(MAT_MatSolve,A,B,X,0));
3650   if (!A->ops->matsolve) {
3651     PetscCall(PetscInfo(A,"Mat type %s using basic MatMatSolve\n",((PetscObject)A)->type_name));
3652     PetscCall(MatMatSolve_Basic(A,B,X,PETSC_FALSE));
3653   } else {
3654     PetscCall((*A->ops->matsolve)(A,B,X));
3655   }
3656   PetscCall(PetscLogEventEnd(MAT_MatSolve,A,B,X,0));
3657   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3658   PetscFunctionReturn(0);
3659 }
3660 
3661 /*@
3662    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3663 
3664    Neighbor-wise Collective on Mat
3665 
3666    Input Parameters:
3667 +  A - the factored matrix
3668 -  B - the right-hand-side matrix  (dense matrix)
3669 
3670    Output Parameter:
3671 .  X - the result matrix (dense matrix)
3672 
3673    Notes:
3674    The matrices B and X cannot be the same.  I.e., one cannot
3675    call MatMatSolveTranspose(A,X,X).
3676 
3677    Notes:
3678    Most users should usually employ the simplified KSP interface for linear solvers
3679    instead of working directly with matrix algebra routines such as this.
3680    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3681    at a time.
3682 
3683    When using SuperLU_Dist or MUMPS as a parallel solver, PETSc will use their functionality to solve multiple right hand sides simultaneously.
3684 
3685    Level: developer
3686 
3687 .seealso: `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3688 @*/
3689 PetscErrorCode MatMatSolveTranspose(Mat A,Mat B,Mat X)
3690 {
3691   PetscFunctionBegin;
3692   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3693   PetscValidType(A,1);
3694   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3695   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3696   PetscCheckSameComm(A,1,B,2);
3697   PetscCheckSameComm(A,1,X,3);
3698   PetscCheck(X != B,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3699   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3700   PetscCheck(A->rmap->N == B->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N);
3701   PetscCheck(A->rmap->n == B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->n,B->rmap->n);
3702   PetscCheck(X->cmap->N >= B->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as rhs matrix");
3703   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3704   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3705   MatCheckPreallocated(A,1);
3706 
3707   PetscCall(PetscLogEventBegin(MAT_MatSolve,A,B,X,0));
3708   if (!A->ops->matsolvetranspose) {
3709     PetscCall(PetscInfo(A,"Mat type %s using basic MatMatSolveTranspose\n",((PetscObject)A)->type_name));
3710     PetscCall(MatMatSolve_Basic(A,B,X,PETSC_TRUE));
3711   } else {
3712     PetscCall((*A->ops->matsolvetranspose)(A,B,X));
3713   }
3714   PetscCall(PetscLogEventEnd(MAT_MatSolve,A,B,X,0));
3715   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3716   PetscFunctionReturn(0);
3717 }
3718 
3719 /*@
3720    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3721 
3722    Neighbor-wise Collective on Mat
3723 
3724    Input Parameters:
3725 +  A - the factored matrix
3726 -  Bt - the transpose of right-hand-side matrix
3727 
3728    Output Parameter:
3729 .  X - the result matrix (dense matrix)
3730 
3731    Notes:
3732    Most users should usually employ the simplified KSP interface for linear solvers
3733    instead of working directly with matrix algebra routines such as this.
3734    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3735    at a time.
3736 
3737    For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row format on the host processor and call MatMatTransposeSolve() to implement MUMPS' MatMatSolve().
3738 
3739    Level: developer
3740 
3741 .seealso: `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3742 @*/
3743 PetscErrorCode MatMatTransposeSolve(Mat A,Mat Bt,Mat X)
3744 {
3745   PetscFunctionBegin;
3746   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3747   PetscValidType(A,1);
3748   PetscValidHeaderSpecific(Bt,MAT_CLASSID,2);
3749   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3750   PetscCheckSameComm(A,1,Bt,2);
3751   PetscCheckSameComm(A,1,X,3);
3752 
3753   PetscCheck(X != Bt,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3754   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3755   PetscCheck(A->rmap->N == Bt->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,Bt->cmap->N);
3756   PetscCheck(X->cmap->N >= Bt->rmap->N,PetscObjectComm((PetscObject)X),PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as row number of the rhs matrix");
3757   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3758   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3759   MatCheckPreallocated(A,1);
3760 
3761   PetscCheck(A->ops->mattransposesolve,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
3762   PetscCall(PetscLogEventBegin(MAT_MatTrSolve,A,Bt,X,0));
3763   PetscCall((*A->ops->mattransposesolve)(A,Bt,X));
3764   PetscCall(PetscLogEventEnd(MAT_MatTrSolve,A,Bt,X,0));
3765   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3766   PetscFunctionReturn(0);
3767 }
3768 
3769 /*@
3770    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3771                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3772 
3773    Neighbor-wise Collective on Mat
3774 
3775    Input Parameters:
3776 +  mat - the factored matrix
3777 -  b - the right-hand-side vector
3778 
3779    Output Parameter:
3780 .  x - the result vector
3781 
3782    Notes:
3783    MatSolve() should be used for most applications, as it performs
3784    a forward solve followed by a backward solve.
3785 
3786    The vectors b and x cannot be the same,  i.e., one cannot
3787    call MatForwardSolve(A,x,x).
3788 
3789    For matrix in seqsbaij format with block size larger than 1,
3790    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3791    MatForwardSolve() solves U^T*D y = b, and
3792    MatBackwardSolve() solves U x = y.
3793    Thus they do not provide a symmetric preconditioner.
3794 
3795    Most users should employ the simplified KSP interface for linear solvers
3796    instead of working directly with matrix algebra routines such as this.
3797    See, e.g., KSPCreate().
3798 
3799    Level: developer
3800 
3801 .seealso: `MatSolve()`, `MatBackwardSolve()`
3802 @*/
3803 PetscErrorCode MatForwardSolve(Mat mat,Vec b,Vec x)
3804 {
3805   PetscFunctionBegin;
3806   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3807   PetscValidType(mat,1);
3808   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3809   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3810   PetscCheckSameComm(mat,1,b,2);
3811   PetscCheckSameComm(mat,1,x,3);
3812   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3813   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3814   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3815   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3816   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3817   MatCheckPreallocated(mat,1);
3818 
3819   PetscCheck(mat->ops->forwardsolve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3820   PetscCall(PetscLogEventBegin(MAT_ForwardSolve,mat,b,x,0));
3821   PetscCall((*mat->ops->forwardsolve)(mat,b,x));
3822   PetscCall(PetscLogEventEnd(MAT_ForwardSolve,mat,b,x,0));
3823   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3824   PetscFunctionReturn(0);
3825 }
3826 
3827 /*@
3828    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3829                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3830 
3831    Neighbor-wise Collective on Mat
3832 
3833    Input Parameters:
3834 +  mat - the factored matrix
3835 -  b - the right-hand-side vector
3836 
3837    Output Parameter:
3838 .  x - the result vector
3839 
3840    Notes:
3841    MatSolve() should be used for most applications, as it performs
3842    a forward solve followed by a backward solve.
3843 
3844    The vectors b and x cannot be the same.  I.e., one cannot
3845    call MatBackwardSolve(A,x,x).
3846 
3847    For matrix in seqsbaij format with block size larger than 1,
3848    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3849    MatForwardSolve() solves U^T*D y = b, and
3850    MatBackwardSolve() solves U x = y.
3851    Thus they do not provide a symmetric preconditioner.
3852 
3853    Most users should employ the simplified KSP interface for linear solvers
3854    instead of working directly with matrix algebra routines such as this.
3855    See, e.g., KSPCreate().
3856 
3857    Level: developer
3858 
3859 .seealso: `MatSolve()`, `MatForwardSolve()`
3860 @*/
3861 PetscErrorCode MatBackwardSolve(Mat mat,Vec b,Vec x)
3862 {
3863   PetscFunctionBegin;
3864   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3865   PetscValidType(mat,1);
3866   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3867   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3868   PetscCheckSameComm(mat,1,b,2);
3869   PetscCheckSameComm(mat,1,x,3);
3870   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3871   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3872   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3873   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3874   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3875   MatCheckPreallocated(mat,1);
3876 
3877   PetscCheck(mat->ops->backwardsolve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3878   PetscCall(PetscLogEventBegin(MAT_BackwardSolve,mat,b,x,0));
3879   PetscCall((*mat->ops->backwardsolve)(mat,b,x));
3880   PetscCall(PetscLogEventEnd(MAT_BackwardSolve,mat,b,x,0));
3881   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3882   PetscFunctionReturn(0);
3883 }
3884 
3885 /*@
3886    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3887 
3888    Neighbor-wise Collective on Mat
3889 
3890    Input Parameters:
3891 +  mat - the factored matrix
3892 .  b - the right-hand-side vector
3893 -  y - the vector to be added to
3894 
3895    Output Parameter:
3896 .  x - the result vector
3897 
3898    Notes:
3899    The vectors b and x cannot be the same.  I.e., one cannot
3900    call MatSolveAdd(A,x,y,x).
3901 
3902    Most users should employ the simplified KSP interface for linear solvers
3903    instead of working directly with matrix algebra routines such as this.
3904    See, e.g., KSPCreate().
3905 
3906    Level: developer
3907 
3908 .seealso: `MatSolve()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3909 @*/
3910 PetscErrorCode MatSolveAdd(Mat mat,Vec b,Vec y,Vec x)
3911 {
3912   PetscScalar    one = 1.0;
3913   Vec            tmp;
3914 
3915   PetscFunctionBegin;
3916   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3917   PetscValidType(mat,1);
3918   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3919   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3920   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
3921   PetscCheckSameComm(mat,1,b,2);
3922   PetscCheckSameComm(mat,1,y,3);
3923   PetscCheckSameComm(mat,1,x,4);
3924   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3925   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3926   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3927   PetscCheck(mat->rmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,y->map->N);
3928   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3929   PetscCheck(x->map->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,x->map->n,y->map->n);
3930   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3931    MatCheckPreallocated(mat,1);
3932 
3933   PetscCall(PetscLogEventBegin(MAT_SolveAdd,mat,b,x,y));
3934   if (mat->factorerrortype) {
3935 
3936     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
3937     PetscCall(VecSetInf(x));
3938   } else if (mat->ops->solveadd) {
3939     PetscCall((*mat->ops->solveadd)(mat,b,y,x));
3940   } else {
3941     /* do the solve then the add manually */
3942     if (x != y) {
3943       PetscCall(MatSolve(mat,b,x));
3944       PetscCall(VecAXPY(x,one,y));
3945     } else {
3946       PetscCall(VecDuplicate(x,&tmp));
3947       PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp));
3948       PetscCall(VecCopy(x,tmp));
3949       PetscCall(MatSolve(mat,b,x));
3950       PetscCall(VecAXPY(x,one,tmp));
3951       PetscCall(VecDestroy(&tmp));
3952     }
3953   }
3954   PetscCall(PetscLogEventEnd(MAT_SolveAdd,mat,b,x,y));
3955   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3956   PetscFunctionReturn(0);
3957 }
3958 
3959 /*@
3960    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3961 
3962    Neighbor-wise Collective on Mat
3963 
3964    Input Parameters:
3965 +  mat - the factored matrix
3966 -  b - the right-hand-side vector
3967 
3968    Output Parameter:
3969 .  x - the result vector
3970 
3971    Notes:
3972    The vectors b and x cannot be the same.  I.e., one cannot
3973    call MatSolveTranspose(A,x,x).
3974 
3975    Most users should employ the simplified KSP interface for linear solvers
3976    instead of working directly with matrix algebra routines such as this.
3977    See, e.g., KSPCreate().
3978 
3979    Level: developer
3980 
3981 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3982 @*/
3983 PetscErrorCode MatSolveTranspose(Mat mat,Vec b,Vec x)
3984 {
3985   PetscErrorCode (*f)(Mat,Vec,Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3986 
3987   PetscFunctionBegin;
3988   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3989   PetscValidType(mat,1);
3990   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3991   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3992   PetscCheckSameComm(mat,1,b,2);
3993   PetscCheckSameComm(mat,1,x,3);
3994   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3995   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
3996   PetscCheck(mat->cmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,b->map->N);
3997   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3998   MatCheckPreallocated(mat,1);
3999   PetscCall(PetscLogEventBegin(MAT_SolveTranspose,mat,b,x,0));
4000   if (mat->factorerrortype) {
4001     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
4002     PetscCall(VecSetInf(x));
4003   } else {
4004     PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s",((PetscObject)mat)->type_name);
4005     PetscCall((*f)(mat,b,x));
4006   }
4007   PetscCall(PetscLogEventEnd(MAT_SolveTranspose,mat,b,x,0));
4008   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4009   PetscFunctionReturn(0);
4010 }
4011 
4012 /*@
4013    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4014                       factored matrix.
4015 
4016    Neighbor-wise Collective on Mat
4017 
4018    Input Parameters:
4019 +  mat - the factored matrix
4020 .  b - the right-hand-side vector
4021 -  y - the vector to be added to
4022 
4023    Output Parameter:
4024 .  x - the result vector
4025 
4026    Notes:
4027    The vectors b and x cannot be the same.  I.e., one cannot
4028    call MatSolveTransposeAdd(A,x,y,x).
4029 
4030    Most users should employ the simplified KSP interface for linear solvers
4031    instead of working directly with matrix algebra routines such as this.
4032    See, e.g., KSPCreate().
4033 
4034    Level: developer
4035 
4036 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4037 @*/
4038 PetscErrorCode MatSolveTransposeAdd(Mat mat,Vec b,Vec y,Vec x)
4039 {
4040   PetscScalar    one = 1.0;
4041   Vec            tmp;
4042   PetscErrorCode (*f)(Mat,Vec,Vec,Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4043 
4044   PetscFunctionBegin;
4045   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4046   PetscValidType(mat,1);
4047   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
4048   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4049   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
4050   PetscCheckSameComm(mat,1,b,2);
4051   PetscCheckSameComm(mat,1,y,3);
4052   PetscCheckSameComm(mat,1,x,4);
4053   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
4054   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
4055   PetscCheck(mat->cmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,b->map->N);
4056   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
4057   PetscCheck(x->map->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,x->map->n,y->map->n);
4058   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4059   MatCheckPreallocated(mat,1);
4060 
4061   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd,mat,b,x,y));
4062   if (mat->factorerrortype) {
4063     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
4064     PetscCall(VecSetInf(x));
4065   } else if (f) {
4066     PetscCall((*f)(mat,b,y,x));
4067   } else {
4068     /* do the solve then the add manually */
4069     if (x != y) {
4070       PetscCall(MatSolveTranspose(mat,b,x));
4071       PetscCall(VecAXPY(x,one,y));
4072     } else {
4073       PetscCall(VecDuplicate(x,&tmp));
4074       PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp));
4075       PetscCall(VecCopy(x,tmp));
4076       PetscCall(MatSolveTranspose(mat,b,x));
4077       PetscCall(VecAXPY(x,one,tmp));
4078       PetscCall(VecDestroy(&tmp));
4079     }
4080   }
4081   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd,mat,b,x,y));
4082   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4083   PetscFunctionReturn(0);
4084 }
4085 /* ----------------------------------------------------------------*/
4086 
4087 /*@
4088    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4089 
4090    Neighbor-wise Collective on Mat
4091 
4092    Input Parameters:
4093 +  mat - the matrix
4094 .  b - the right hand side
4095 .  omega - the relaxation factor
4096 .  flag - flag indicating the type of SOR (see below)
4097 .  shift -  diagonal shift
4098 .  its - the number of iterations
4099 -  lits - the number of local iterations
4100 
4101    Output Parameter:
4102 .  x - the solution (can contain an initial guess, use option SOR_ZERO_INITIAL_GUESS to indicate no guess)
4103 
4104    SOR Flags:
4105 +     SOR_FORWARD_SWEEP - forward SOR
4106 .     SOR_BACKWARD_SWEEP - backward SOR
4107 .     SOR_SYMMETRIC_SWEEP - SSOR (symmetric SOR)
4108 .     SOR_LOCAL_FORWARD_SWEEP - local forward SOR
4109 .     SOR_LOCAL_BACKWARD_SWEEP - local forward SOR
4110 .     SOR_LOCAL_SYMMETRIC_SWEEP - local SSOR
4111 .     SOR_APPLY_UPPER, SOR_APPLY_LOWER - applies
4112          upper/lower triangular part of matrix to
4113          vector (with omega)
4114 -     SOR_ZERO_INITIAL_GUESS - zero initial guess
4115 
4116    Notes:
4117    SOR_LOCAL_FORWARD_SWEEP, SOR_LOCAL_BACKWARD_SWEEP, and
4118    SOR_LOCAL_SYMMETRIC_SWEEP perform separate independent smoothings
4119    on each processor.
4120 
4121    Application programmers will not generally use MatSOR() directly,
4122    but instead will employ the KSP/PC interface.
4123 
4124    Notes:
4125     for BAIJ, SBAIJ, and AIJ matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4126 
4127    Notes for Advanced Users:
4128    The flags are implemented as bitwise inclusive or operations.
4129    For example, use (SOR_ZERO_INITIAL_GUESS | SOR_SYMMETRIC_SWEEP)
4130    to specify a zero initial guess for SSOR.
4131 
4132    Most users should employ the simplified KSP interface for linear solvers
4133    instead of working directly with matrix algebra routines such as this.
4134    See, e.g., KSPCreate().
4135 
4136    Vectors x and b CANNOT be the same
4137 
4138    Developer Note: We should add block SOR support for AIJ matrices with block size set to great than one and no inodes
4139 
4140    Level: developer
4141 
4142 @*/
4143 PetscErrorCode MatSOR(Mat mat,Vec b,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec x)
4144 {
4145   PetscFunctionBegin;
4146   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4147   PetscValidType(mat,1);
4148   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4149   PetscValidHeaderSpecific(x,VEC_CLASSID,8);
4150   PetscCheckSameComm(mat,1,b,2);
4151   PetscCheckSameComm(mat,1,x,8);
4152   PetscCheck(mat->ops->sor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4153   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4154   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4155   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
4156   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
4157   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
4158   PetscCheck(its > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %" PetscInt_FMT " positive",its);
4159   PetscCheck(lits > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires local its %" PetscInt_FMT " positive",lits);
4160   PetscCheck(b != x,PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"b and x vector cannot be the same");
4161 
4162   MatCheckPreallocated(mat,1);
4163   PetscCall(PetscLogEventBegin(MAT_SOR,mat,b,x,0));
4164   PetscCall((*mat->ops->sor)(mat,b,omega,flag,shift,its,lits,x));
4165   PetscCall(PetscLogEventEnd(MAT_SOR,mat,b,x,0));
4166   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4167   PetscFunctionReturn(0);
4168 }
4169 
4170 /*
4171       Default matrix copy routine.
4172 */
4173 PetscErrorCode MatCopy_Basic(Mat A,Mat B,MatStructure str)
4174 {
4175   PetscInt          i,rstart = 0,rend = 0,nz;
4176   const PetscInt    *cwork;
4177   const PetscScalar *vwork;
4178 
4179   PetscFunctionBegin;
4180   if (B->assembled) PetscCall(MatZeroEntries(B));
4181   if (str == SAME_NONZERO_PATTERN) {
4182     PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
4183     for (i=rstart; i<rend; i++) {
4184       PetscCall(MatGetRow(A,i,&nz,&cwork,&vwork));
4185       PetscCall(MatSetValues(B,1,&i,nz,cwork,vwork,INSERT_VALUES));
4186       PetscCall(MatRestoreRow(A,i,&nz,&cwork,&vwork));
4187     }
4188   } else {
4189     PetscCall(MatAYPX(B,0.0,A,str));
4190   }
4191   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
4192   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
4193   PetscFunctionReturn(0);
4194 }
4195 
4196 /*@
4197    MatCopy - Copies a matrix to another matrix.
4198 
4199    Collective on Mat
4200 
4201    Input Parameters:
4202 +  A - the matrix
4203 -  str - SAME_NONZERO_PATTERN or DIFFERENT_NONZERO_PATTERN
4204 
4205    Output Parameter:
4206 .  B - where the copy is put
4207 
4208    Notes:
4209    If you use SAME_NONZERO_PATTERN then the two matrices must have the same nonzero pattern or the routine will crash.
4210 
4211    MatCopy() copies the matrix entries of a matrix to another existing
4212    matrix (after first zeroing the second matrix).  A related routine is
4213    MatConvert(), which first creates a new matrix and then copies the data.
4214 
4215    Level: intermediate
4216 
4217 .seealso: `MatConvert()`, `MatDuplicate()`
4218 @*/
4219 PetscErrorCode MatCopy(Mat A,Mat B,MatStructure str)
4220 {
4221   PetscInt       i;
4222 
4223   PetscFunctionBegin;
4224   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4225   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4226   PetscValidType(A,1);
4227   PetscValidType(B,2);
4228   PetscCheckSameComm(A,1,B,2);
4229   MatCheckPreallocated(B,2);
4230   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4231   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4232   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")",A->rmap->N,B->rmap->N,A->cmap->N,B->cmap->N);
4233   MatCheckPreallocated(A,1);
4234   if (A == B) PetscFunctionReturn(0);
4235 
4236   PetscCall(PetscLogEventBegin(MAT_Copy,A,B,0,0));
4237   if (A->ops->copy) {
4238     PetscCall((*A->ops->copy)(A,B,str));
4239   } else { /* generic conversion */
4240     PetscCall(MatCopy_Basic(A,B,str));
4241   }
4242 
4243   B->stencil.dim = A->stencil.dim;
4244   B->stencil.noc = A->stencil.noc;
4245   for (i=0; i<=A->stencil.dim; i++) {
4246     B->stencil.dims[i]   = A->stencil.dims[i];
4247     B->stencil.starts[i] = A->stencil.starts[i];
4248   }
4249 
4250   PetscCall(PetscLogEventEnd(MAT_Copy,A,B,0,0));
4251   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4252   PetscFunctionReturn(0);
4253 }
4254 
4255 /*@C
4256    MatConvert - Converts a matrix to another matrix, either of the same
4257    or different type.
4258 
4259    Collective on Mat
4260 
4261    Input Parameters:
4262 +  mat - the matrix
4263 .  newtype - new matrix type.  Use MATSAME to create a new matrix of the
4264    same type as the original matrix.
4265 -  reuse - denotes if the destination matrix is to be created or reused.
4266    Use MAT_INPLACE_MATRIX for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use
4267    MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX (can only be used after the first call was made with MAT_INITIAL_MATRIX, causes the matrix space in M to be reused).
4268 
4269    Output Parameter:
4270 .  M - pointer to place new matrix
4271 
4272    Notes:
4273    MatConvert() first creates a new matrix and then copies the data from
4274    the first matrix.  A related routine is MatCopy(), which copies the matrix
4275    entries of one matrix to another already existing matrix context.
4276 
4277    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4278    the MPI communicator of the generated matrix is always the same as the communicator
4279    of the input matrix.
4280 
4281    Level: intermediate
4282 
4283 .seealso: `MatCopy()`, `MatDuplicate()`
4284 @*/
4285 PetscErrorCode MatConvert(Mat mat,MatType newtype,MatReuse reuse,Mat *M)
4286 {
4287   PetscBool      sametype,issame,flg,issymmetric,ishermitian;
4288   char           convname[256],mtype[256];
4289   Mat            B;
4290 
4291   PetscFunctionBegin;
4292   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4293   PetscValidType(mat,1);
4294   PetscValidPointer(M,4);
4295   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4296   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4297   MatCheckPreallocated(mat,1);
4298 
4299   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matconvert_type",mtype,sizeof(mtype),&flg));
4300   if (flg) newtype = mtype;
4301 
4302   PetscCall(PetscObjectTypeCompare((PetscObject)mat,newtype,&sametype));
4303   PetscCall(PetscStrcmp(newtype,"same",&issame));
4304   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M),PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires same input and output matrix");
4305   PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M),PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4306 
4307   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4308     PetscCall(PetscInfo(mat,"Early return for inplace %s %d %d\n",((PetscObject)mat)->type_name,sametype,issame));
4309     PetscFunctionReturn(0);
4310   }
4311 
4312   /* Cache Mat options because some converter use MatHeaderReplace  */
4313   issymmetric = mat->symmetric;
4314   ishermitian = mat->hermitian;
4315 
4316   if ((sametype || issame) && (reuse==MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4317     PetscCall(PetscInfo(mat,"Calling duplicate for initial matrix %s %d %d\n",((PetscObject)mat)->type_name,sametype,issame));
4318     PetscCall((*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M));
4319   } else {
4320     PetscErrorCode (*conv)(Mat, MatType,MatReuse,Mat*)=NULL;
4321     const char     *prefix[3] = {"seq","mpi",""};
4322     PetscInt       i;
4323     /*
4324        Order of precedence:
4325        0) See if newtype is a superclass of the current matrix.
4326        1) See if a specialized converter is known to the current matrix.
4327        2) See if a specialized converter is known to the desired matrix class.
4328        3) See if a good general converter is registered for the desired class
4329           (as of 6/27/03 only MATMPIADJ falls into this category).
4330        4) See if a good general converter is known for the current matrix.
4331        5) Use a really basic converter.
4332     */
4333 
4334     /* 0) See if newtype is a superclass of the current matrix.
4335           i.e mat is mpiaij and newtype is aij */
4336     for (i=0; i<2; i++) {
4337       PetscCall(PetscStrncpy(convname,prefix[i],sizeof(convname)));
4338       PetscCall(PetscStrlcat(convname,newtype,sizeof(convname)));
4339       PetscCall(PetscStrcmp(convname,((PetscObject)mat)->type_name,&flg));
4340       PetscCall(PetscInfo(mat,"Check superclass %s %s -> %d\n",convname,((PetscObject)mat)->type_name,flg));
4341       if (flg) {
4342         if (reuse == MAT_INPLACE_MATRIX) {
4343           PetscCall(PetscInfo(mat,"Early return\n"));
4344           PetscFunctionReturn(0);
4345         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4346           PetscCall(PetscInfo(mat,"Calling MatDuplicate\n"));
4347           PetscCall((*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M));
4348           PetscFunctionReturn(0);
4349         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4350           PetscCall(PetscInfo(mat,"Calling MatCopy\n"));
4351           PetscCall(MatCopy(mat,*M,SAME_NONZERO_PATTERN));
4352           PetscFunctionReturn(0);
4353         }
4354       }
4355     }
4356     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4357     for (i=0; i<3; i++) {
4358       PetscCall(PetscStrncpy(convname,"MatConvert_",sizeof(convname)));
4359       PetscCall(PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname)));
4360       PetscCall(PetscStrlcat(convname,"_",sizeof(convname)));
4361       PetscCall(PetscStrlcat(convname,prefix[i],sizeof(convname)));
4362       PetscCall(PetscStrlcat(convname,issame ? ((PetscObject)mat)->type_name : newtype,sizeof(convname)));
4363       PetscCall(PetscStrlcat(convname,"_C",sizeof(convname)));
4364       PetscCall(PetscObjectQueryFunction((PetscObject)mat,convname,&conv));
4365       PetscCall(PetscInfo(mat,"Check specialized (1) %s (%s) -> %d\n",convname,((PetscObject)mat)->type_name,!!conv));
4366       if (conv) goto foundconv;
4367     }
4368 
4369     /* 2)  See if a specialized converter is known to the desired matrix class. */
4370     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&B));
4371     PetscCall(MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
4372     PetscCall(MatSetType(B,newtype));
4373     for (i=0; i<3; i++) {
4374       PetscCall(PetscStrncpy(convname,"MatConvert_",sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname,"_",sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname,prefix[i],sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname,newtype,sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname,"_C",sizeof(convname)));
4380       PetscCall(PetscObjectQueryFunction((PetscObject)B,convname,&conv));
4381       PetscCall(PetscInfo(mat,"Check specialized (2) %s (%s) -> %d\n",convname,((PetscObject)B)->type_name,!!conv));
4382       if (conv) {
4383         PetscCall(MatDestroy(&B));
4384         goto foundconv;
4385       }
4386     }
4387 
4388     /* 3) See if a good general converter is registered for the desired class */
4389     conv = B->ops->convertfrom;
4390     PetscCall(PetscInfo(mat,"Check convertfrom (%s) -> %d\n",((PetscObject)B)->type_name,!!conv));
4391     PetscCall(MatDestroy(&B));
4392     if (conv) goto foundconv;
4393 
4394     /* 4) See if a good general converter is known for the current matrix */
4395     if (mat->ops->convert) conv = mat->ops->convert;
4396     PetscCall(PetscInfo(mat,"Check general convert (%s) -> %d\n",((PetscObject)mat)->type_name,!!conv));
4397     if (conv) goto foundconv;
4398 
4399     /* 5) Use a really basic converter. */
4400     PetscCall(PetscInfo(mat,"Using MatConvert_Basic\n"));
4401     conv = MatConvert_Basic;
4402 
4403 foundconv:
4404     PetscCall(PetscLogEventBegin(MAT_Convert,mat,0,0,0));
4405     PetscCall((*conv)(mat,newtype,reuse,M));
4406     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4407       /* the block sizes must be same if the mappings are copied over */
4408       (*M)->rmap->bs = mat->rmap->bs;
4409       (*M)->cmap->bs = mat->cmap->bs;
4410       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4411       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4412       (*M)->rmap->mapping = mat->rmap->mapping;
4413       (*M)->cmap->mapping = mat->cmap->mapping;
4414     }
4415     (*M)->stencil.dim = mat->stencil.dim;
4416     (*M)->stencil.noc = mat->stencil.noc;
4417     for (i=0; i<=mat->stencil.dim; i++) {
4418       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4419       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4420     }
4421     PetscCall(PetscLogEventEnd(MAT_Convert,mat,0,0,0));
4422   }
4423   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4424 
4425   /* Copy Mat options */
4426   if (issymmetric) PetscCall(MatSetOption(*M,MAT_SYMMETRIC,PETSC_TRUE));
4427   if (ishermitian) PetscCall(MatSetOption(*M,MAT_HERMITIAN,PETSC_TRUE));
4428   PetscFunctionReturn(0);
4429 }
4430 
4431 /*@C
4432    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4433 
4434    Not Collective
4435 
4436    Input Parameter:
4437 .  mat - the matrix, must be a factored matrix
4438 
4439    Output Parameter:
4440 .   type - the string name of the package (do not free this string)
4441 
4442    Notes:
4443       In Fortran you pass in a empty string and the package name will be copied into it.
4444     (Make sure the string is long enough)
4445 
4446    Level: intermediate
4447 
4448 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4449 @*/
4450 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4451 {
4452   PetscErrorCode (*conv)(Mat,MatSolverType*);
4453 
4454   PetscFunctionBegin;
4455   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4456   PetscValidType(mat,1);
4457   PetscValidPointer(type,2);
4458   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
4459   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorGetSolverType_C",&conv));
4460   if (conv) PetscCall((*conv)(mat,type));
4461   else *type = MATSOLVERPETSC;
4462   PetscFunctionReturn(0);
4463 }
4464 
4465 typedef struct _MatSolverTypeForSpecifcType* MatSolverTypeForSpecifcType;
4466 struct _MatSolverTypeForSpecifcType {
4467   MatType                        mtype;
4468   /* no entry for MAT_FACTOR_NONE */
4469   PetscErrorCode                 (*createfactor[MAT_FACTOR_NUM_TYPES-1])(Mat,MatFactorType,Mat*);
4470   MatSolverTypeForSpecifcType next;
4471 };
4472 
4473 typedef struct _MatSolverTypeHolder* MatSolverTypeHolder;
4474 struct _MatSolverTypeHolder {
4475   char                        *name;
4476   MatSolverTypeForSpecifcType handlers;
4477   MatSolverTypeHolder         next;
4478 };
4479 
4480 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4481 
4482 /*@C
4483    MatSolverTypeRegister - Registers a MatSolverType that works for a particular matrix type
4484 
4485    Input Parameters:
4486 +    package - name of the package, for example petsc or superlu
4487 .    mtype - the matrix type that works with this package
4488 .    ftype - the type of factorization supported by the package
4489 -    createfactor - routine that will create the factored matrix ready to be used
4490 
4491     Level: intermediate
4492 
4493 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4494 @*/
4495 PetscErrorCode MatSolverTypeRegister(MatSolverType package,MatType mtype,MatFactorType ftype,PetscErrorCode (*createfactor)(Mat,MatFactorType,Mat*))
4496 {
4497   MatSolverTypeHolder         next = MatSolverTypeHolders,prev = NULL;
4498   PetscBool                   flg;
4499   MatSolverTypeForSpecifcType inext,iprev = NULL;
4500 
4501   PetscFunctionBegin;
4502   PetscCall(MatInitializePackage());
4503   if (!next) {
4504     PetscCall(PetscNew(&MatSolverTypeHolders));
4505     PetscCall(PetscStrallocpy(package,&MatSolverTypeHolders->name));
4506     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4507     PetscCall(PetscStrallocpy(mtype,(char **)&MatSolverTypeHolders->handlers->mtype));
4508     MatSolverTypeHolders->handlers->createfactor[(int)ftype-1] = createfactor;
4509     PetscFunctionReturn(0);
4510   }
4511   while (next) {
4512     PetscCall(PetscStrcasecmp(package,next->name,&flg));
4513     if (flg) {
4514       PetscCheck(next->handlers,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatSolverTypeHolder is missing handlers");
4515       inext = next->handlers;
4516       while (inext) {
4517         PetscCall(PetscStrcasecmp(mtype,inext->mtype,&flg));
4518         if (flg) {
4519           inext->createfactor[(int)ftype-1] = createfactor;
4520           PetscFunctionReturn(0);
4521         }
4522         iprev = inext;
4523         inext = inext->next;
4524       }
4525       PetscCall(PetscNew(&iprev->next));
4526       PetscCall(PetscStrallocpy(mtype,(char **)&iprev->next->mtype));
4527       iprev->next->createfactor[(int)ftype-1] = createfactor;
4528       PetscFunctionReturn(0);
4529     }
4530     prev = next;
4531     next = next->next;
4532   }
4533   PetscCall(PetscNew(&prev->next));
4534   PetscCall(PetscStrallocpy(package,&prev->next->name));
4535   PetscCall(PetscNew(&prev->next->handlers));
4536   PetscCall(PetscStrallocpy(mtype,(char **)&prev->next->handlers->mtype));
4537   prev->next->handlers->createfactor[(int)ftype-1] = createfactor;
4538   PetscFunctionReturn(0);
4539 }
4540 
4541 /*@C
4542    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4543 
4544    Input Parameters:
4545 +    type - name of the package, for example petsc or superlu
4546 .    ftype - the type of factorization supported by the type
4547 -    mtype - the matrix type that works with this type
4548 
4549    Output Parameters:
4550 +   foundtype - PETSC_TRUE if the type was registered
4551 .   foundmtype - PETSC_TRUE if the type supports the requested mtype
4552 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4553 
4554     Level: intermediate
4555 
4556 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4557 @*/
4558 PetscErrorCode MatSolverTypeGet(MatSolverType type,MatType mtype,MatFactorType ftype,PetscBool *foundtype,PetscBool *foundmtype,PetscErrorCode (**createfactor)(Mat,MatFactorType,Mat*))
4559 {
4560   MatSolverTypeHolder         next = MatSolverTypeHolders;
4561   PetscBool                   flg;
4562   MatSolverTypeForSpecifcType inext;
4563 
4564   PetscFunctionBegin;
4565   if (foundtype) *foundtype = PETSC_FALSE;
4566   if (foundmtype) *foundmtype = PETSC_FALSE;
4567   if (createfactor) *createfactor = NULL;
4568 
4569   if (type) {
4570     while (next) {
4571       PetscCall(PetscStrcasecmp(type,next->name,&flg));
4572       if (flg) {
4573         if (foundtype) *foundtype = PETSC_TRUE;
4574         inext = next->handlers;
4575         while (inext) {
4576           PetscCall(PetscStrbeginswith(mtype,inext->mtype,&flg));
4577           if (flg) {
4578             if (foundmtype) *foundmtype = PETSC_TRUE;
4579             if (createfactor)  *createfactor  = inext->createfactor[(int)ftype-1];
4580             PetscFunctionReturn(0);
4581           }
4582           inext = inext->next;
4583         }
4584       }
4585       next = next->next;
4586     }
4587   } else {
4588     while (next) {
4589       inext = next->handlers;
4590       while (inext) {
4591         PetscCall(PetscStrcmp(mtype,inext->mtype,&flg));
4592         if (flg && inext->createfactor[(int)ftype-1]) {
4593           if (foundtype) *foundtype = PETSC_TRUE;
4594           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4595           if (createfactor) *createfactor = inext->createfactor[(int)ftype-1];
4596           PetscFunctionReturn(0);
4597         }
4598         inext = inext->next;
4599       }
4600       next = next->next;
4601     }
4602     /* try with base classes inext->mtype */
4603     next = MatSolverTypeHolders;
4604     while (next) {
4605       inext = next->handlers;
4606       while (inext) {
4607         PetscCall(PetscStrbeginswith(mtype,inext->mtype,&flg));
4608         if (flg && inext->createfactor[(int)ftype-1]) {
4609           if (foundtype) *foundtype = PETSC_TRUE;
4610           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4611           if (createfactor) *createfactor = inext->createfactor[(int)ftype-1];
4612           PetscFunctionReturn(0);
4613         }
4614         inext = inext->next;
4615       }
4616       next = next->next;
4617     }
4618   }
4619   PetscFunctionReturn(0);
4620 }
4621 
4622 PetscErrorCode MatSolverTypeDestroy(void)
4623 {
4624   MatSolverTypeHolder         next = MatSolverTypeHolders,prev;
4625   MatSolverTypeForSpecifcType inext,iprev;
4626 
4627   PetscFunctionBegin;
4628   while (next) {
4629     PetscCall(PetscFree(next->name));
4630     inext = next->handlers;
4631     while (inext) {
4632       PetscCall(PetscFree(inext->mtype));
4633       iprev = inext;
4634       inext = inext->next;
4635       PetscCall(PetscFree(iprev));
4636     }
4637     prev = next;
4638     next = next->next;
4639     PetscCall(PetscFree(prev));
4640   }
4641   MatSolverTypeHolders = NULL;
4642   PetscFunctionReturn(0);
4643 }
4644 
4645 /*@C
4646    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in MatLUFactorSymbolic(), MatCholeskyFactorSymbolic()
4647 
4648    Logically Collective on Mat
4649 
4650    Input Parameters:
4651 .  mat - the matrix
4652 
4653    Output Parameters:
4654 .  flg - PETSC_TRUE if uses the ordering
4655 
4656    Notes:
4657       Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4658       packages do not, thus we want to skip generating the ordering when it is not needed or used.
4659 
4660    Level: developer
4661 
4662 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4663 @*/
4664 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4665 {
4666   PetscFunctionBegin;
4667   *flg = mat->canuseordering;
4668   PetscFunctionReturn(0);
4669 }
4670 
4671 /*@C
4672    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4673 
4674    Logically Collective on Mat
4675 
4676    Input Parameters:
4677 .  mat - the matrix
4678 
4679    Output Parameters:
4680 .  otype - the preferred type
4681 
4682    Level: developer
4683 
4684 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4685 @*/
4686 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4687 {
4688   PetscFunctionBegin;
4689   *otype = mat->preferredordering[ftype];
4690   PetscCheck(*otype,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatFactor did not have a preferred ordering");
4691   PetscFunctionReturn(0);
4692 }
4693 
4694 /*@C
4695    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4696 
4697    Collective on Mat
4698 
4699    Input Parameters:
4700 +  mat - the matrix
4701 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4702 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4703 
4704    Output Parameters:
4705 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4706 
4707    Notes:
4708       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4709      such as pastix, superlu, mumps etc.
4710 
4711       PETSc must have been ./configure to use the external solver, using the option --download-package
4712 
4713       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4714       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4715       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4716 
4717    Developer Notes:
4718       This should actually be called MatCreateFactor() since it creates a new factor object
4719 
4720    Level: intermediate
4721 
4722 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`
4723 @*/
4724 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type,MatFactorType ftype,Mat *f)
4725 {
4726   PetscBool      foundtype,foundmtype;
4727   PetscErrorCode (*conv)(Mat,MatFactorType,Mat*);
4728 
4729   PetscFunctionBegin;
4730   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4731   PetscValidType(mat,1);
4732 
4733   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4734   MatCheckPreallocated(mat,1);
4735 
4736   PetscCall(MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,&foundtype,&foundmtype,&conv));
4737   if (!foundtype) {
4738     if (type) {
4739       SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s",type,MatFactorTypes[ftype],((PetscObject)mat)->type_name,type);
4740     } else {
4741       SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"Could not locate a solver type for factorization type %s and matrix type %s.",MatFactorTypes[ftype],((PetscObject)mat)->type_name);
4742     }
4743   }
4744   PetscCheck(foundmtype,PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"MatSolverType %s does not support matrix type %s",type,((PetscObject)mat)->type_name);
4745   PetscCheck(conv,PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"MatSolverType %s does not support factorization type %s for matrix type %s",type,MatFactorTypes[ftype],((PetscObject)mat)->type_name);
4746 
4747   PetscCall((*conv)(mat,ftype,f));
4748   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f,mat->factorprefix));
4749   PetscFunctionReturn(0);
4750 }
4751 
4752 /*@C
4753    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4754 
4755    Not Collective
4756 
4757    Input Parameters:
4758 +  mat - the matrix
4759 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4760 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4761 
4762    Output Parameter:
4763 .    flg - PETSC_TRUE if the factorization is available
4764 
4765    Notes:
4766       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4767      such as pastix, superlu, mumps etc.
4768 
4769       PETSc must have been ./configure to use the external solver, using the option --download-package
4770 
4771    Developer Notes:
4772       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4773 
4774    Level: intermediate
4775 
4776 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`
4777 @*/
4778 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type,MatFactorType ftype,PetscBool  *flg)
4779 {
4780   PetscErrorCode (*gconv)(Mat,MatFactorType,Mat*);
4781 
4782   PetscFunctionBegin;
4783   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4784   PetscValidType(mat,1);
4785   PetscValidBoolPointer(flg,4);
4786 
4787   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4788   MatCheckPreallocated(mat,1);
4789 
4790   PetscCall(MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,NULL,NULL,&gconv));
4791   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4792   PetscFunctionReturn(0);
4793 }
4794 
4795 /*@
4796    MatDuplicate - Duplicates a matrix including the non-zero structure.
4797 
4798    Collective on Mat
4799 
4800    Input Parameters:
4801 +  mat - the matrix
4802 -  op - One of MAT_DO_NOT_COPY_VALUES, MAT_COPY_VALUES, or MAT_SHARE_NONZERO_PATTERN.
4803         See the manual page for MatDuplicateOption for an explanation of these options.
4804 
4805    Output Parameter:
4806 .  M - pointer to place new matrix
4807 
4808    Level: intermediate
4809 
4810    Notes:
4811     You cannot change the nonzero pattern for the parent or child matrix if you use MAT_SHARE_NONZERO_PATTERN.
4812     May be called with an unassembled input Mat if MAT_DO_NOT_COPY_VALUES is used, in which case the output Mat is unassembled as well.
4813     When original mat is a product of matrix operation, e.g., an output of MatMatMult() or MatCreateSubMatrix(), only the simple matrix data structure of mat is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. User should not use MatDuplicate() to create new matrix M if M is intended to be reused as the product of matrix operation.
4814 
4815 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4816 @*/
4817 PetscErrorCode MatDuplicate(Mat mat,MatDuplicateOption op,Mat *M)
4818 {
4819   Mat            B;
4820   VecType        vtype;
4821   PetscInt       i;
4822   PetscObject    dm;
4823   void           (*viewf)(void);
4824 
4825   PetscFunctionBegin;
4826   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4827   PetscValidType(mat,1);
4828   PetscValidPointer(M,3);
4829   PetscCheck(op != MAT_COPY_VALUES || mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MAT_COPY_VALUES not allowed for unassembled matrix");
4830   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4831   MatCheckPreallocated(mat,1);
4832 
4833   *M = NULL;
4834   PetscCheck(mat->ops->duplicate,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not written for matrix type %s",((PetscObject)mat)->type_name);
4835   PetscCall(PetscLogEventBegin(MAT_Convert,mat,0,0,0));
4836   PetscCall((*mat->ops->duplicate)(mat,op,M));
4837   PetscCall(PetscLogEventEnd(MAT_Convert,mat,0,0,0));
4838   B    = *M;
4839 
4840   PetscCall(MatGetOperation(mat,MATOP_VIEW,&viewf));
4841   if (viewf) PetscCall(MatSetOperation(B,MATOP_VIEW,viewf));
4842   PetscCall(MatGetVecType(mat,&vtype));
4843   PetscCall(MatSetVecType(B,vtype));
4844 
4845   B->stencil.dim = mat->stencil.dim;
4846   B->stencil.noc = mat->stencil.noc;
4847   for (i=0; i<=mat->stencil.dim; i++) {
4848     B->stencil.dims[i]   = mat->stencil.dims[i];
4849     B->stencil.starts[i] = mat->stencil.starts[i];
4850   }
4851 
4852   B->nooffproczerorows = mat->nooffproczerorows;
4853   B->nooffprocentries  = mat->nooffprocentries;
4854 
4855   PetscCall(PetscObjectQuery((PetscObject) mat, "__PETSc_dm", &dm));
4856   if (dm) {
4857     PetscCall(PetscObjectCompose((PetscObject) B, "__PETSc_dm", dm));
4858   }
4859   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4860   PetscFunctionReturn(0);
4861 }
4862 
4863 /*@
4864    MatGetDiagonal - Gets the diagonal of a matrix.
4865 
4866    Logically Collective on Mat
4867 
4868    Input Parameters:
4869 +  mat - the matrix
4870 -  v - the vector for storing the diagonal
4871 
4872    Output Parameter:
4873 .  v - the diagonal of the matrix
4874 
4875    Level: intermediate
4876 
4877    Note:
4878    Currently only correct in parallel for square matrices.
4879 
4880 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4881 @*/
4882 PetscErrorCode MatGetDiagonal(Mat mat,Vec v)
4883 {
4884   PetscFunctionBegin;
4885   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4886   PetscValidType(mat,1);
4887   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4888   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4889   PetscCheck(mat->ops->getdiagonal,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4890   MatCheckPreallocated(mat,1);
4891 
4892   PetscCall((*mat->ops->getdiagonal)(mat,v));
4893   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4894   PetscFunctionReturn(0);
4895 }
4896 
4897 /*@C
4898    MatGetRowMin - Gets the minimum value (of the real part) of each
4899         row of the matrix
4900 
4901    Logically Collective on Mat
4902 
4903    Input Parameter:
4904 .  mat - the matrix
4905 
4906    Output Parameters:
4907 +  v - the vector for storing the maximums
4908 -  idx - the indices of the column found for each row (optional)
4909 
4910    Level: intermediate
4911 
4912    Notes:
4913     The result of this call are the same as if one converted the matrix to dense format
4914       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4915 
4916     This code is only implemented for a couple of matrix formats.
4917 
4918 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`,
4919           `MatGetRowMax()`
4920 @*/
4921 PetscErrorCode MatGetRowMin(Mat mat,Vec v,PetscInt idx[])
4922 {
4923   PetscFunctionBegin;
4924   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4925   PetscValidType(mat,1);
4926   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4927   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4928 
4929   if (!mat->cmap->N) {
4930     PetscCall(VecSet(v,PETSC_MAX_REAL));
4931     if (idx) {
4932       PetscInt i,m = mat->rmap->n;
4933       for (i=0; i<m; i++) idx[i] = -1;
4934     }
4935   } else {
4936     PetscCheck(mat->ops->getrowmin,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4937     MatCheckPreallocated(mat,1);
4938   }
4939   PetscCall((*mat->ops->getrowmin)(mat,v,idx));
4940   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4941   PetscFunctionReturn(0);
4942 }
4943 
4944 /*@C
4945    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4946         row of the matrix
4947 
4948    Logically Collective on Mat
4949 
4950    Input Parameter:
4951 .  mat - the matrix
4952 
4953    Output Parameters:
4954 +  v - the vector for storing the minimums
4955 -  idx - the indices of the column found for each row (or NULL if not needed)
4956 
4957    Level: intermediate
4958 
4959    Notes:
4960     if a row is completely empty or has only 0.0 values then the idx[] value for that
4961     row is 0 (the first column).
4962 
4963     This code is only implemented for a couple of matrix formats.
4964 
4965 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4966 @*/
4967 PetscErrorCode MatGetRowMinAbs(Mat mat,Vec v,PetscInt idx[])
4968 {
4969   PetscFunctionBegin;
4970   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4971   PetscValidType(mat,1);
4972   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4973   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4974   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4975 
4976   if (!mat->cmap->N) {
4977     PetscCall(VecSet(v,0.0));
4978     if (idx) {
4979       PetscInt i,m = mat->rmap->n;
4980       for (i=0; i<m; i++) idx[i] = -1;
4981     }
4982   } else {
4983     PetscCheck(mat->ops->getrowminabs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4984     MatCheckPreallocated(mat,1);
4985     if (idx) PetscCall(PetscArrayzero(idx,mat->rmap->n));
4986     PetscCall((*mat->ops->getrowminabs)(mat,v,idx));
4987   }
4988   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4989   PetscFunctionReturn(0);
4990 }
4991 
4992 /*@C
4993    MatGetRowMax - Gets the maximum value (of the real part) of each
4994         row of the matrix
4995 
4996    Logically Collective on Mat
4997 
4998    Input Parameter:
4999 .  mat - the matrix
5000 
5001    Output Parameters:
5002 +  v - the vector for storing the maximums
5003 -  idx - the indices of the column found for each row (optional)
5004 
5005    Level: intermediate
5006 
5007    Notes:
5008     The result of this call are the same as if one converted the matrix to dense format
5009       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5010 
5011     This code is only implemented for a couple of matrix formats.
5012 
5013 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5014 @*/
5015 PetscErrorCode MatGetRowMax(Mat mat,Vec v,PetscInt idx[])
5016 {
5017   PetscFunctionBegin;
5018   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5019   PetscValidType(mat,1);
5020   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5021   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5022 
5023   if (!mat->cmap->N) {
5024     PetscCall(VecSet(v,PETSC_MIN_REAL));
5025     if (idx) {
5026       PetscInt i,m = mat->rmap->n;
5027       for (i=0; i<m; i++) idx[i] = -1;
5028     }
5029   } else {
5030     PetscCheck(mat->ops->getrowmax,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5031     MatCheckPreallocated(mat,1);
5032     PetscCall((*mat->ops->getrowmax)(mat,v,idx));
5033   }
5034   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5035   PetscFunctionReturn(0);
5036 }
5037 
5038 /*@C
5039    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5040         row of the matrix
5041 
5042    Logically Collective on Mat
5043 
5044    Input Parameter:
5045 .  mat - the matrix
5046 
5047    Output Parameters:
5048 +  v - the vector for storing the maximums
5049 -  idx - the indices of the column found for each row (or NULL if not needed)
5050 
5051    Level: intermediate
5052 
5053    Notes:
5054     if a row is completely empty or has only 0.0 values then the idx[] value for that
5055     row is 0 (the first column).
5056 
5057     This code is only implemented for a couple of matrix formats.
5058 
5059 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`
5060 @*/
5061 PetscErrorCode MatGetRowMaxAbs(Mat mat,Vec v,PetscInt idx[])
5062 {
5063   PetscFunctionBegin;
5064   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5065   PetscValidType(mat,1);
5066   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5067   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5068 
5069   if (!mat->cmap->N) {
5070     PetscCall(VecSet(v,0.0));
5071     if (idx) {
5072       PetscInt i,m = mat->rmap->n;
5073       for (i=0; i<m; i++) idx[i] = -1;
5074     }
5075   } else {
5076     PetscCheck(mat->ops->getrowmaxabs,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5077     MatCheckPreallocated(mat,1);
5078     if (idx) PetscCall(PetscArrayzero(idx,mat->rmap->n));
5079     PetscCall((*mat->ops->getrowmaxabs)(mat,v,idx));
5080   }
5081   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5082   PetscFunctionReturn(0);
5083 }
5084 
5085 /*@
5086    MatGetRowSum - Gets the sum of each row of the matrix
5087 
5088    Logically or Neighborhood Collective on Mat
5089 
5090    Input Parameters:
5091 .  mat - the matrix
5092 
5093    Output Parameter:
5094 .  v - the vector for storing the sum of rows
5095 
5096    Level: intermediate
5097 
5098    Notes:
5099     This code is slow since it is not currently specialized for different formats
5100 
5101 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`
5102 @*/
5103 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5104 {
5105   Vec            ones;
5106 
5107   PetscFunctionBegin;
5108   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5109   PetscValidType(mat,1);
5110   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5111   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5112   MatCheckPreallocated(mat,1);
5113   PetscCall(MatCreateVecs(mat,&ones,NULL));
5114   PetscCall(VecSet(ones,1.));
5115   PetscCall(MatMult(mat,ones,v));
5116   PetscCall(VecDestroy(&ones));
5117   PetscFunctionReturn(0);
5118 }
5119 
5120 /*@
5121    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5122 
5123    Collective on Mat
5124 
5125    Input Parameters:
5126 +  mat - the matrix to transpose
5127 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5128 
5129    Output Parameter:
5130 .  B - the transpose
5131 
5132    Notes:
5133      If you use MAT_INPLACE_MATRIX then you must pass in &mat for B
5134 
5135      MAT_REUSE_MATRIX causes the B matrix from a previous call to this function with MAT_INITIAL_MATRIX to be used
5136 
5137      Consider using MatCreateTranspose() instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5138 
5139    Level: intermediate
5140 
5141 .seealso: `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5142 @*/
5143 PetscErrorCode MatTranspose(Mat mat,MatReuse reuse,Mat *B)
5144 {
5145   PetscFunctionBegin;
5146   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5147   PetscValidType(mat,1);
5148   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5149   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5150   PetscCheck(mat->ops->transpose,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5151   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires last matrix to match first");
5152   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Perhaps you mean MAT_INPLACE_MATRIX");
5153   MatCheckPreallocated(mat,1);
5154 
5155   PetscCall(PetscLogEventBegin(MAT_Transpose,mat,0,0,0));
5156   PetscCall((*mat->ops->transpose)(mat,reuse,B));
5157   PetscCall(PetscLogEventEnd(MAT_Transpose,mat,0,0,0));
5158   if (B) PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5159   PetscFunctionReturn(0);
5160 }
5161 
5162 /*@
5163    MatIsTranspose - Test whether a matrix is another one's transpose,
5164         or its own, in which case it tests symmetry.
5165 
5166    Collective on Mat
5167 
5168    Input Parameters:
5169 +  A - the matrix to test
5170 -  B - the matrix to test against, this can equal the first parameter
5171 
5172    Output Parameters:
5173 .  flg - the result
5174 
5175    Notes:
5176    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5177    has a running time of the order of the number of nonzeros; the parallel
5178    test involves parallel copies of the block-offdiagonal parts of the matrix.
5179 
5180    Level: intermediate
5181 
5182 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5183 @*/
5184 PetscErrorCode MatIsTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5185 {
5186   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5187 
5188   PetscFunctionBegin;
5189   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5190   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5191   PetscValidBoolPointer(flg,4);
5192   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsTranspose_C",&f));
5193   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsTranspose_C",&g));
5194   *flg = PETSC_FALSE;
5195   if (f && g) {
5196     PetscCheck(f == g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for symmetry test");
5197     PetscCall((*f)(A,B,tol,flg));
5198   } else {
5199     MatType mattype;
5200 
5201     PetscCall(MatGetType(f ? B : A,&mattype));
5202     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for transpose",mattype);
5203   }
5204   PetscFunctionReturn(0);
5205 }
5206 
5207 /*@
5208    MatHermitianTranspose - Computes an in-place or out-of-place transpose of a matrix in complex conjugate.
5209 
5210    Collective on Mat
5211 
5212    Input Parameters:
5213 +  mat - the matrix to transpose and complex conjugate
5214 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5215 
5216    Output Parameter:
5217 .  B - the Hermitian
5218 
5219    Level: intermediate
5220 
5221 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5222 @*/
5223 PetscErrorCode MatHermitianTranspose(Mat mat,MatReuse reuse,Mat *B)
5224 {
5225   PetscFunctionBegin;
5226   PetscCall(MatTranspose(mat,reuse,B));
5227 #if defined(PETSC_USE_COMPLEX)
5228   PetscCall(MatConjugate(*B));
5229 #endif
5230   PetscFunctionReturn(0);
5231 }
5232 
5233 /*@
5234    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5235 
5236    Collective on Mat
5237 
5238    Input Parameters:
5239 +  A - the matrix to test
5240 -  B - the matrix to test against, this can equal the first parameter
5241 
5242    Output Parameters:
5243 .  flg - the result
5244 
5245    Notes:
5246    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5247    has a running time of the order of the number of nonzeros; the parallel
5248    test involves parallel copies of the block-offdiagonal parts of the matrix.
5249 
5250    Level: intermediate
5251 
5252 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5253 @*/
5254 PetscErrorCode MatIsHermitianTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5255 {
5256   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5257 
5258   PetscFunctionBegin;
5259   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5260   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5261   PetscValidBoolPointer(flg,4);
5262   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsHermitianTranspose_C",&f));
5263   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsHermitianTranspose_C",&g));
5264   if (f && g) {
5265     PetscCheck(f != g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for Hermitian test");
5266     PetscCall((*f)(A,B,tol,flg));
5267   }
5268   PetscFunctionReturn(0);
5269 }
5270 
5271 /*@
5272    MatPermute - Creates a new matrix with rows and columns permuted from the
5273    original.
5274 
5275    Collective on Mat
5276 
5277    Input Parameters:
5278 +  mat - the matrix to permute
5279 .  row - row permutation, each processor supplies only the permutation for its rows
5280 -  col - column permutation, each processor supplies only the permutation for its columns
5281 
5282    Output Parameters:
5283 .  B - the permuted matrix
5284 
5285    Level: advanced
5286 
5287    Note:
5288    The index sets map from row/col of permuted matrix to row/col of original matrix.
5289    The index sets should be on the same communicator as Mat and have the same local sizes.
5290 
5291    Developer Note:
5292      If you want to implement MatPermute for a matrix type, and your approach doesn't
5293      exploit the fact that row and col are permutations, consider implementing the
5294      more general MatCreateSubMatrix() instead.
5295 
5296 .seealso: `MatGetOrdering()`, `ISAllGather()`
5297 
5298 @*/
5299 PetscErrorCode MatPermute(Mat mat,IS row,IS col,Mat *B)
5300 {
5301   PetscFunctionBegin;
5302   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5303   PetscValidType(mat,1);
5304   PetscValidHeaderSpecific(row,IS_CLASSID,2);
5305   PetscValidHeaderSpecific(col,IS_CLASSID,3);
5306   PetscValidPointer(B,4);
5307   PetscCheckSameComm(mat,1,row,2);
5308   if (row != col) PetscCheckSameComm(row,2,col,3);
5309   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5310   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5311   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatPermute not available for Mat type %s",((PetscObject)mat)->type_name);
5312   MatCheckPreallocated(mat,1);
5313 
5314   if (mat->ops->permute) {
5315     PetscCall((*mat->ops->permute)(mat,row,col,B));
5316     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5317   } else {
5318     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5319   }
5320   PetscFunctionReturn(0);
5321 }
5322 
5323 /*@
5324    MatEqual - Compares two matrices.
5325 
5326    Collective on Mat
5327 
5328    Input Parameters:
5329 +  A - the first matrix
5330 -  B - the second matrix
5331 
5332    Output Parameter:
5333 .  flg - PETSC_TRUE if the matrices are equal; PETSC_FALSE otherwise.
5334 
5335    Level: intermediate
5336 
5337 @*/
5338 PetscErrorCode MatEqual(Mat A,Mat B,PetscBool *flg)
5339 {
5340   PetscFunctionBegin;
5341   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5342   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5343   PetscValidType(A,1);
5344   PetscValidType(B,2);
5345   PetscValidBoolPointer(flg,3);
5346   PetscCheckSameComm(A,1,B,2);
5347   MatCheckPreallocated(A,1);
5348   MatCheckPreallocated(B,2);
5349   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5350   PetscCheck(B->assembled,PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5351   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N,A->cmap->N,B->cmap->N);
5352   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5353     PetscCall((*A->ops->equal)(A,B,flg));
5354   } else {
5355     PetscCall(MatMultEqual(A,B,10,flg));
5356   }
5357   PetscFunctionReturn(0);
5358 }
5359 
5360 /*@
5361    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5362    matrices that are stored as vectors.  Either of the two scaling
5363    matrices can be NULL.
5364 
5365    Collective on Mat
5366 
5367    Input Parameters:
5368 +  mat - the matrix to be scaled
5369 .  l - the left scaling vector (or NULL)
5370 -  r - the right scaling vector (or NULL)
5371 
5372    Notes:
5373    MatDiagonalScale() computes A = LAR, where
5374    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5375    The L scales the rows of the matrix, the R scales the columns of the matrix.
5376 
5377    Level: intermediate
5378 
5379 .seealso: `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5380 @*/
5381 PetscErrorCode MatDiagonalScale(Mat mat,Vec l,Vec r)
5382 {
5383   PetscFunctionBegin;
5384   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5385   PetscValidType(mat,1);
5386   if (l) {PetscValidHeaderSpecific(l,VEC_CLASSID,2);PetscCheckSameComm(mat,1,l,2);}
5387   if (r) {PetscValidHeaderSpecific(r,VEC_CLASSID,3);PetscCheckSameComm(mat,1,r,3);}
5388   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5389   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5390   MatCheckPreallocated(mat,1);
5391   if (!l && !r) PetscFunctionReturn(0);
5392 
5393   PetscCheck(mat->ops->diagonalscale,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5394   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5395   PetscCall((*mat->ops->diagonalscale)(mat,l,r));
5396   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5397   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5398   if (l != r && mat->symmetric) mat->symmetric = PETSC_FALSE;
5399   PetscFunctionReturn(0);
5400 }
5401 
5402 /*@
5403     MatScale - Scales all elements of a matrix by a given number.
5404 
5405     Logically Collective on Mat
5406 
5407     Input Parameters:
5408 +   mat - the matrix to be scaled
5409 -   a  - the scaling value
5410 
5411     Output Parameter:
5412 .   mat - the scaled matrix
5413 
5414     Level: intermediate
5415 
5416 .seealso: `MatDiagonalScale()`
5417 @*/
5418 PetscErrorCode MatScale(Mat mat,PetscScalar a)
5419 {
5420   PetscFunctionBegin;
5421   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5422   PetscValidType(mat,1);
5423   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5424   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5425   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5426   PetscValidLogicalCollectiveScalar(mat,a,2);
5427   MatCheckPreallocated(mat,1);
5428 
5429   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5430   if (a != (PetscScalar)1.0) {
5431     PetscCall((*mat->ops->scale)(mat,a));
5432     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5433   }
5434   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5435   PetscFunctionReturn(0);
5436 }
5437 
5438 /*@
5439    MatNorm - Calculates various norms of a matrix.
5440 
5441    Collective on Mat
5442 
5443    Input Parameters:
5444 +  mat - the matrix
5445 -  type - the type of norm, NORM_1, NORM_FROBENIUS, NORM_INFINITY
5446 
5447    Output Parameter:
5448 .  nrm - the resulting norm
5449 
5450    Level: intermediate
5451 
5452 @*/
5453 PetscErrorCode MatNorm(Mat mat,NormType type,PetscReal *nrm)
5454 {
5455   PetscFunctionBegin;
5456   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5457   PetscValidType(mat,1);
5458   PetscValidRealPointer(nrm,3);
5459 
5460   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5461   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5462   PetscCheck(mat->ops->norm,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5463   MatCheckPreallocated(mat,1);
5464 
5465   PetscCall((*mat->ops->norm)(mat,type,nrm));
5466   PetscFunctionReturn(0);
5467 }
5468 
5469 /*
5470      This variable is used to prevent counting of MatAssemblyBegin() that
5471    are called from within a MatAssemblyEnd().
5472 */
5473 static PetscInt MatAssemblyEnd_InUse = 0;
5474 /*@
5475    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5476    be called after completing all calls to MatSetValues().
5477 
5478    Collective on Mat
5479 
5480    Input Parameters:
5481 +  mat - the matrix
5482 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5483 
5484    Notes:
5485    MatSetValues() generally caches the values.  The matrix is ready to
5486    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5487    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5488    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5489    using the matrix.
5490 
5491    ALL processes that share a matrix MUST call MatAssemblyBegin() and MatAssemblyEnd() the SAME NUMBER of times, and each time with the
5492    same flag of MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY for all processes. Thus you CANNOT locally change from ADD_VALUES to INSERT_VALUES, that is
5493    a global collective operation requring all processes that share the matrix.
5494 
5495    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5496    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5497    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5498 
5499    Level: beginner
5500 
5501 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5502 @*/
5503 PetscErrorCode MatAssemblyBegin(Mat mat,MatAssemblyType type)
5504 {
5505   PetscFunctionBegin;
5506   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5507   PetscValidType(mat,1);
5508   MatCheckPreallocated(mat,1);
5509   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5510   if (mat->assembled) {
5511     mat->was_assembled = PETSC_TRUE;
5512     mat->assembled     = PETSC_FALSE;
5513   }
5514 
5515   if (!MatAssemblyEnd_InUse) {
5516     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin,mat,0,0,0));
5517     if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5518     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin,mat,0,0,0));
5519   } else if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5520   PetscFunctionReturn(0);
5521 }
5522 
5523 /*@
5524    MatAssembled - Indicates if a matrix has been assembled and is ready for
5525      use; for example, in matrix-vector product.
5526 
5527    Not Collective
5528 
5529    Input Parameter:
5530 .  mat - the matrix
5531 
5532    Output Parameter:
5533 .  assembled - PETSC_TRUE or PETSC_FALSE
5534 
5535    Level: advanced
5536 
5537 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5538 @*/
5539 PetscErrorCode MatAssembled(Mat mat,PetscBool *assembled)
5540 {
5541   PetscFunctionBegin;
5542   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5543   PetscValidBoolPointer(assembled,2);
5544   *assembled = mat->assembled;
5545   PetscFunctionReturn(0);
5546 }
5547 
5548 /*@
5549    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5550    be called after MatAssemblyBegin().
5551 
5552    Collective on Mat
5553 
5554    Input Parameters:
5555 +  mat - the matrix
5556 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5557 
5558    Options Database Keys:
5559 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatEndAssembly()
5560 .  -mat_view ::ascii_info_detail - Prints more detailed info
5561 .  -mat_view - Prints matrix in ASCII format
5562 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5563 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
5564 .  -display <name> - Sets display name (default is host)
5565 .  -draw_pause <sec> - Sets number of seconds to pause after display
5566 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab)
5567 .  -viewer_socket_machine <machine> - Machine to use for socket
5568 .  -viewer_socket_port <port> - Port number to use for socket
5569 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5570 
5571    Notes:
5572    MatSetValues() generally caches the values.  The matrix is ready to
5573    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5574    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5575    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5576    using the matrix.
5577 
5578    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5579    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5580    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5581 
5582    Level: beginner
5583 
5584 .seealso: `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5585 @*/
5586 PetscErrorCode MatAssemblyEnd(Mat mat,MatAssemblyType type)
5587 {
5588   static PetscInt inassm = 0;
5589   PetscBool       flg    = PETSC_FALSE;
5590 
5591   PetscFunctionBegin;
5592   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5593   PetscValidType(mat,1);
5594 
5595   inassm++;
5596   MatAssemblyEnd_InUse++;
5597   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5598     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd,mat,0,0,0));
5599     if (mat->ops->assemblyend) PetscCall((*mat->ops->assemblyend)(mat,type));
5600     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd,mat,0,0,0));
5601   } else if (mat->ops->assemblyend) PetscCall((*mat->ops->assemblyend)(mat,type));
5602 
5603   /* Flush assembly is not a true assembly */
5604   if (type != MAT_FLUSH_ASSEMBLY) {
5605     mat->num_ass++;
5606     mat->assembled        = PETSC_TRUE;
5607     mat->ass_nonzerostate = mat->nonzerostate;
5608   }
5609 
5610   mat->insertmode = NOT_SET_VALUES;
5611   MatAssemblyEnd_InUse--;
5612   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5613   if (!mat->symmetric_eternal) {
5614     mat->symmetric_set              = PETSC_FALSE;
5615     mat->hermitian_set              = PETSC_FALSE;
5616     mat->structurally_symmetric_set = PETSC_FALSE;
5617   }
5618   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5619     PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5620 
5621     if (mat->checksymmetryonassembly) {
5622       PetscCall(MatIsSymmetric(mat,mat->checksymmetrytol,&flg));
5623       if (flg) {
5624         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5625       } else {
5626         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is not symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5627       }
5628     }
5629     if (mat->nullsp && mat->checknullspaceonassembly) {
5630       PetscCall(MatNullSpaceTest(mat->nullsp,mat,NULL));
5631     }
5632   }
5633   inassm--;
5634   PetscFunctionReturn(0);
5635 }
5636 
5637 /*@
5638    MatSetOption - Sets a parameter option for a matrix. Some options
5639    may be specific to certain storage formats.  Some options
5640    determine how values will be inserted (or added). Sorted,
5641    row-oriented input will generally assemble the fastest. The default
5642    is row-oriented.
5643 
5644    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5645 
5646    Input Parameters:
5647 +  mat - the matrix
5648 .  option - the option, one of those listed below (and possibly others),
5649 -  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5650 
5651   Options Describing Matrix Structure:
5652 +    MAT_SPD - symmetric positive definite
5653 .    MAT_SYMMETRIC - symmetric in terms of both structure and value
5654 .    MAT_HERMITIAN - transpose is the complex conjugation
5655 .    MAT_STRUCTURALLY_SYMMETRIC - symmetric nonzero structure
5656 -    MAT_SYMMETRY_ETERNAL - if you would like the symmetry/Hermitian flag
5657                             you set to be kept with all future use of the matrix
5658                             including after MatAssemblyBegin/End() which could
5659                             potentially change the symmetry structure, i.e. you
5660                             KNOW the matrix will ALWAYS have the property you set.
5661                             Note that setting this flag alone implies nothing about whether the matrix is symmetric/Hermitian;
5662                             the relevant flags must be set independently.
5663 
5664    Options For Use with MatSetValues():
5665    Insert a logically dense subblock, which can be
5666 .    MAT_ROW_ORIENTED - row-oriented (default)
5667 
5668    Note these options reflect the data you pass in with MatSetValues(); it has
5669    nothing to do with how the data is stored internally in the matrix
5670    data structure.
5671 
5672    When (re)assembling a matrix, we can restrict the input for
5673    efficiency/debugging purposes.  These options include
5674 +    MAT_NEW_NONZERO_LOCATIONS - additional insertions will be allowed if they generate a new nonzero (slow)
5675 .    MAT_FORCE_DIAGONAL_ENTRIES - forces diagonal entries to be allocated
5676 .    MAT_IGNORE_OFF_PROC_ENTRIES - drops off-processor entries
5677 .    MAT_NEW_NONZERO_LOCATION_ERR - generates an error for new matrix entry
5678 .    MAT_USE_HASH_TABLE - uses a hash table to speed up matrix assembly
5679 .    MAT_NO_OFF_PROC_ENTRIES - you know each process will only set values for its own rows, will generate an error if
5680         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5681         performance for very large process counts.
5682 -    MAT_SUBSET_OFF_PROC_ENTRIES - you know that the first assembly after setting this flag will set a superset
5683         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5684         functions, instead sending only neighbor messages.
5685 
5686    Notes:
5687    Except for MAT_UNUSED_NONZERO_LOCATION_ERR and  MAT_ROW_ORIENTED all processes that share the matrix must pass the same value in flg!
5688 
5689    Some options are relevant only for particular matrix types and
5690    are thus ignored by others.  Other options are not supported by
5691    certain matrix types and will generate an error message if set.
5692 
5693    If using a Fortran 77 module to compute a matrix, one may need to
5694    use the column-oriented option (or convert to the row-oriented
5695    format).
5696 
5697    MAT_NEW_NONZERO_LOCATIONS set to PETSC_FALSE indicates that any add or insertion
5698    that would generate a new entry in the nonzero structure is instead
5699    ignored.  Thus, if memory has not alredy been allocated for this particular
5700    data, then the insertion is ignored. For dense matrices, in which
5701    the entire array is allocated, no entries are ever ignored.
5702    Set after the first MatAssemblyEnd(). If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5703 
5704    MAT_NEW_NONZERO_LOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5705    that would generate a new entry in the nonzero structure instead produces
5706    an error. (Currently supported for AIJ and BAIJ formats only.) If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5707 
5708    MAT_NEW_NONZERO_ALLOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5709    that would generate a new entry that has not been preallocated will
5710    instead produce an error. (Currently supported for AIJ and BAIJ formats
5711    only.) This is a useful flag when debugging matrix memory preallocation.
5712    If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5713 
5714    MAT_IGNORE_OFF_PROC_ENTRIES set to PETSC_TRUE indicates entries destined for
5715    other processors should be dropped, rather than stashed.
5716    This is useful if you know that the "owning" processor is also
5717    always generating the correct matrix entries, so that PETSc need
5718    not transfer duplicate entries generated on another processor.
5719 
5720    MAT_USE_HASH_TABLE indicates that a hash table be used to improve the
5721    searches during matrix assembly. When this flag is set, the hash table
5722    is created during the first Matrix Assembly. This hash table is
5723    used the next time through, during MatSetVaules()/MatSetVaulesBlocked()
5724    to improve the searching of indices. MAT_NEW_NONZERO_LOCATIONS flag
5725    should be used with MAT_USE_HASH_TABLE flag. This option is currently
5726    supported by MATMPIBAIJ format only.
5727 
5728    MAT_KEEP_NONZERO_PATTERN indicates when MatZeroRows() is called the zeroed entries
5729    are kept in the nonzero structure
5730 
5731    MAT_IGNORE_ZERO_ENTRIES - for AIJ/IS matrices this will stop zero values from creating
5732    a zero location in the matrix
5733 
5734    MAT_USE_INODES - indicates using inode version of the code - works with AIJ matrix types
5735 
5736    MAT_NO_OFF_PROC_ZERO_ROWS - you know each process will only zero its own rows. This avoids all reductions in the
5737         zero row routines and thus improves performance for very large process counts.
5738 
5739    MAT_IGNORE_LOWER_TRIANGULAR - For SBAIJ matrices will ignore any insertions you make in the lower triangular
5740         part of the matrix (since they should match the upper triangular part).
5741 
5742    MAT_SORTED_FULL - each process provides exactly its local rows; all column indices for a given row are passed in a
5743                      single call to MatSetValues(), preallocation is perfect, row oriented, INSERT_VALUES is used. Common
5744                      with finite difference schemes with non-periodic boundary conditions.
5745 
5746    Level: intermediate
5747 
5748 .seealso: `MatOption`, `Mat`
5749 
5750 @*/
5751 PetscErrorCode MatSetOption(Mat mat,MatOption op,PetscBool flg)
5752 {
5753   PetscFunctionBegin;
5754   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5755   if (op > 0) {
5756     PetscValidLogicalCollectiveEnum(mat,op,2);
5757     PetscValidLogicalCollectiveBool(mat,flg,3);
5758   }
5759 
5760   PetscCheck(((int) op) > MAT_OPTION_MIN && ((int) op) < MAT_OPTION_MAX,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Options %d is out of range",(int)op);
5761 
5762   switch (op) {
5763   case MAT_FORCE_DIAGONAL_ENTRIES:
5764     mat->force_diagonals = flg;
5765     PetscFunctionReturn(0);
5766   case MAT_NO_OFF_PROC_ENTRIES:
5767     mat->nooffprocentries = flg;
5768     PetscFunctionReturn(0);
5769   case MAT_SUBSET_OFF_PROC_ENTRIES:
5770     mat->assembly_subset = flg;
5771     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5772 #if !defined(PETSC_HAVE_MPIUNI)
5773       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5774 #endif
5775       mat->stash.first_assembly_done = PETSC_FALSE;
5776     }
5777     PetscFunctionReturn(0);
5778   case MAT_NO_OFF_PROC_ZERO_ROWS:
5779     mat->nooffproczerorows = flg;
5780     PetscFunctionReturn(0);
5781   case MAT_SPD:
5782     mat->spd_set = PETSC_TRUE;
5783     mat->spd     = flg;
5784     if (flg) {
5785       mat->symmetric                  = PETSC_TRUE;
5786       mat->structurally_symmetric     = PETSC_TRUE;
5787       mat->symmetric_set              = PETSC_TRUE;
5788       mat->structurally_symmetric_set = PETSC_TRUE;
5789     }
5790     break;
5791   case MAT_SYMMETRIC:
5792     mat->symmetric = flg;
5793     if (flg) mat->structurally_symmetric = PETSC_TRUE;
5794     mat->symmetric_set              = PETSC_TRUE;
5795     mat->structurally_symmetric_set = flg;
5796 #if !defined(PETSC_USE_COMPLEX)
5797     mat->hermitian     = flg;
5798     mat->hermitian_set = PETSC_TRUE;
5799 #endif
5800     break;
5801   case MAT_HERMITIAN:
5802     mat->hermitian = flg;
5803     if (flg) mat->structurally_symmetric = PETSC_TRUE;
5804     mat->hermitian_set              = PETSC_TRUE;
5805     mat->structurally_symmetric_set = flg;
5806 #if !defined(PETSC_USE_COMPLEX)
5807     mat->symmetric     = flg;
5808     mat->symmetric_set = PETSC_TRUE;
5809 #endif
5810     break;
5811   case MAT_STRUCTURALLY_SYMMETRIC:
5812     mat->structurally_symmetric     = flg;
5813     mat->structurally_symmetric_set = PETSC_TRUE;
5814     break;
5815   case MAT_SYMMETRY_ETERNAL:
5816     mat->symmetric_eternal = flg;
5817     break;
5818   case MAT_STRUCTURE_ONLY:
5819     mat->structure_only = flg;
5820     break;
5821   case MAT_SORTED_FULL:
5822     mat->sortedfull = flg;
5823     break;
5824   default:
5825     break;
5826   }
5827   if (mat->ops->setoption) PetscCall((*mat->ops->setoption)(mat,op,flg));
5828   PetscFunctionReturn(0);
5829 }
5830 
5831 /*@
5832    MatGetOption - Gets a parameter option that has been set for a matrix.
5833 
5834    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5835 
5836    Input Parameters:
5837 +  mat - the matrix
5838 -  option - the option, this only responds to certain options, check the code for which ones
5839 
5840    Output Parameter:
5841 .  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5842 
5843     Notes:
5844     Can only be called after MatSetSizes() and MatSetType() have been set.
5845 
5846    Level: intermediate
5847 
5848 .seealso: `MatOption`, `MatSetOption()`
5849 
5850 @*/
5851 PetscErrorCode MatGetOption(Mat mat,MatOption op,PetscBool *flg)
5852 {
5853   PetscFunctionBegin;
5854   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5855   PetscValidType(mat,1);
5856 
5857   PetscCheck(((int) op) > MAT_OPTION_MIN && ((int) op) < MAT_OPTION_MAX,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Options %d is out of range",(int)op);
5858   PetscCheck(((PetscObject)mat)->type_name,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_TYPENOTSET,"Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()");
5859 
5860   switch (op) {
5861   case MAT_NO_OFF_PROC_ENTRIES:
5862     *flg = mat->nooffprocentries;
5863     break;
5864   case MAT_NO_OFF_PROC_ZERO_ROWS:
5865     *flg = mat->nooffproczerorows;
5866     break;
5867   case MAT_SYMMETRIC:
5868     *flg = mat->symmetric;
5869     break;
5870   case MAT_HERMITIAN:
5871     *flg = mat->hermitian;
5872     break;
5873   case MAT_STRUCTURALLY_SYMMETRIC:
5874     *flg = mat->structurally_symmetric;
5875     break;
5876   case MAT_SYMMETRY_ETERNAL:
5877     *flg = mat->symmetric_eternal;
5878     break;
5879   case MAT_SPD:
5880     *flg = mat->spd;
5881     break;
5882   default:
5883     break;
5884   }
5885   PetscFunctionReturn(0);
5886 }
5887 
5888 /*@
5889    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5890    this routine retains the old nonzero structure.
5891 
5892    Logically Collective on Mat
5893 
5894    Input Parameters:
5895 .  mat - the matrix
5896 
5897    Level: intermediate
5898 
5899    Notes:
5900     If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase.
5901    See the Performance chapter of the users manual for information on preallocating matrices.
5902 
5903 .seealso: `MatZeroRows()`
5904 @*/
5905 PetscErrorCode MatZeroEntries(Mat mat)
5906 {
5907   PetscFunctionBegin;
5908   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5909   PetscValidType(mat,1);
5910   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5911   PetscCheck(mat->insertmode == NOT_SET_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for matrices where you have set values but not yet assembled");
5912   PetscCheck(mat->ops->zeroentries,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5913   MatCheckPreallocated(mat,1);
5914 
5915   PetscCall(PetscLogEventBegin(MAT_ZeroEntries,mat,0,0,0));
5916   PetscCall((*mat->ops->zeroentries)(mat));
5917   PetscCall(PetscLogEventEnd(MAT_ZeroEntries,mat,0,0,0));
5918   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5919   PetscFunctionReturn(0);
5920 }
5921 
5922 /*@
5923    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5924    of a set of rows and columns of a matrix.
5925 
5926    Collective on Mat
5927 
5928    Input Parameters:
5929 +  mat - the matrix
5930 .  numRows - the number of rows to remove
5931 .  rows - the global row indices
5932 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5933 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5934 -  b - optional vector of right hand side, that will be adjusted by provided solution
5935 
5936    Notes:
5937    This does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5938 
5939    The user can set a value in the diagonal entry (or for the AIJ and
5940    row formats can optionally remove the main diagonal entry from the
5941    nonzero structure as well, by passing 0.0 as the final argument).
5942 
5943    For the parallel case, all processes that share the matrix (i.e.,
5944    those in the communicator used for matrix creation) MUST call this
5945    routine, regardless of whether any rows being zeroed are owned by
5946    them.
5947 
5948    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5949    list only rows local to itself).
5950 
5951    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
5952 
5953    Level: intermediate
5954 
5955 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5956           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5957 @*/
5958 PetscErrorCode MatZeroRowsColumns(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
5959 {
5960   PetscFunctionBegin;
5961   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5962   PetscValidType(mat,1);
5963   if (numRows) PetscValidIntPointer(rows,3);
5964   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5965   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5966   PetscCheck(mat->ops->zerorowscolumns,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5967   MatCheckPreallocated(mat,1);
5968 
5969   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,rows,diag,x,b));
5970   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5971   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5972   PetscFunctionReturn(0);
5973 }
5974 
5975 /*@
5976    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5977    of a set of rows and columns of a matrix.
5978 
5979    Collective on Mat
5980 
5981    Input Parameters:
5982 +  mat - the matrix
5983 .  is - the rows to zero
5984 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5985 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5986 -  b - optional vector of right hand side, that will be adjusted by provided solution
5987 
5988    Notes:
5989    This does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5990 
5991    The user can set a value in the diagonal entry (or for the AIJ and
5992    row formats can optionally remove the main diagonal entry from the
5993    nonzero structure as well, by passing 0.0 as the final argument).
5994 
5995    For the parallel case, all processes that share the matrix (i.e.,
5996    those in the communicator used for matrix creation) MUST call this
5997    routine, regardless of whether any rows being zeroed are owned by
5998    them.
5999 
6000    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6001    list only rows local to itself).
6002 
6003    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
6004 
6005    Level: intermediate
6006 
6007 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6008           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6009 @*/
6010 PetscErrorCode MatZeroRowsColumnsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6011 {
6012   PetscInt       numRows;
6013   const PetscInt *rows;
6014 
6015   PetscFunctionBegin;
6016   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6017   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6018   PetscValidType(mat,1);
6019   PetscValidType(is,2);
6020   PetscCall(ISGetLocalSize(is,&numRows));
6021   PetscCall(ISGetIndices(is,&rows));
6022   PetscCall(MatZeroRowsColumns(mat,numRows,rows,diag,x,b));
6023   PetscCall(ISRestoreIndices(is,&rows));
6024   PetscFunctionReturn(0);
6025 }
6026 
6027 /*@
6028    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6029    of a set of rows of a matrix.
6030 
6031    Collective on Mat
6032 
6033    Input Parameters:
6034 +  mat - the matrix
6035 .  numRows - the number of rows to remove
6036 .  rows - the global row indices
6037 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6038 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6039 -  b - optional vector of right hand side, that will be adjusted by provided solution
6040 
6041    Notes:
6042    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6043    but does not release memory.  For the dense and block diagonal
6044    formats this does not alter the nonzero structure.
6045 
6046    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6047    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6048    merely zeroed.
6049 
6050    The user can set a value in the diagonal entry (or for the AIJ and
6051    row formats can optionally remove the main diagonal entry from the
6052    nonzero structure as well, by passing 0.0 as the final argument).
6053 
6054    For the parallel case, all processes that share the matrix (i.e.,
6055    those in the communicator used for matrix creation) MUST call this
6056    routine, regardless of whether any rows being zeroed are owned by
6057    them.
6058 
6059    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6060    list only rows local to itself).
6061 
6062    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6063    owns that are to be zeroed. This saves a global synchronization in the implementation.
6064 
6065    Level: intermediate
6066 
6067 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6068           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6069 @*/
6070 PetscErrorCode MatZeroRows(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6071 {
6072   PetscFunctionBegin;
6073   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6074   PetscValidType(mat,1);
6075   if (numRows) PetscValidIntPointer(rows,3);
6076   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6077   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6078   PetscCheck(mat->ops->zerorows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6079   MatCheckPreallocated(mat,1);
6080 
6081   PetscCall((*mat->ops->zerorows)(mat,numRows,rows,diag,x,b));
6082   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
6083   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6084   PetscFunctionReturn(0);
6085 }
6086 
6087 /*@
6088    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6089    of a set of rows of a matrix.
6090 
6091    Collective on Mat
6092 
6093    Input Parameters:
6094 +  mat - the matrix
6095 .  is - index set of rows to remove (if NULL then no row is removed)
6096 .  diag - value put in all diagonals of eliminated rows
6097 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6098 -  b - optional vector of right hand side, that will be adjusted by provided solution
6099 
6100    Notes:
6101    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6102    but does not release memory.  For the dense and block diagonal
6103    formats this does not alter the nonzero structure.
6104 
6105    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6106    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6107    merely zeroed.
6108 
6109    The user can set a value in the diagonal entry (or for the AIJ and
6110    row formats can optionally remove the main diagonal entry from the
6111    nonzero structure as well, by passing 0.0 as the final argument).
6112 
6113    For the parallel case, all processes that share the matrix (i.e.,
6114    those in the communicator used for matrix creation) MUST call this
6115    routine, regardless of whether any rows being zeroed are owned by
6116    them.
6117 
6118    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6119    list only rows local to itself).
6120 
6121    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6122    owns that are to be zeroed. This saves a global synchronization in the implementation.
6123 
6124    Level: intermediate
6125 
6126 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6127           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6128 @*/
6129 PetscErrorCode MatZeroRowsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6130 {
6131   PetscInt       numRows = 0;
6132   const PetscInt *rows = NULL;
6133 
6134   PetscFunctionBegin;
6135   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6136   PetscValidType(mat,1);
6137   if (is) {
6138     PetscValidHeaderSpecific(is,IS_CLASSID,2);
6139     PetscCall(ISGetLocalSize(is,&numRows));
6140     PetscCall(ISGetIndices(is,&rows));
6141   }
6142   PetscCall(MatZeroRows(mat,numRows,rows,diag,x,b));
6143   if (is) {
6144     PetscCall(ISRestoreIndices(is,&rows));
6145   }
6146   PetscFunctionReturn(0);
6147 }
6148 
6149 /*@
6150    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6151    of a set of rows of a matrix. These rows must be local to the process.
6152 
6153    Collective on Mat
6154 
6155    Input Parameters:
6156 +  mat - the matrix
6157 .  numRows - the number of rows to remove
6158 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6159 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6160 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6161 -  b - optional vector of right hand side, that will be adjusted by provided solution
6162 
6163    Notes:
6164    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6165    but does not release memory.  For the dense and block diagonal
6166    formats this does not alter the nonzero structure.
6167 
6168    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6169    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6170    merely zeroed.
6171 
6172    The user can set a value in the diagonal entry (or for the AIJ and
6173    row formats can optionally remove the main diagonal entry from the
6174    nonzero structure as well, by passing 0.0 as the final argument).
6175 
6176    For the parallel case, all processes that share the matrix (i.e.,
6177    those in the communicator used for matrix creation) MUST call this
6178    routine, regardless of whether any rows being zeroed are owned by
6179    them.
6180 
6181    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6182    list only rows local to itself).
6183 
6184    The grid coordinates are across the entire grid, not just the local portion
6185 
6186    In Fortran idxm and idxn should be declared as
6187 $     MatStencil idxm(4,m)
6188    and the values inserted using
6189 $    idxm(MatStencil_i,1) = i
6190 $    idxm(MatStencil_j,1) = j
6191 $    idxm(MatStencil_k,1) = k
6192 $    idxm(MatStencil_c,1) = c
6193    etc
6194 
6195    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6196    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6197    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6198    DM_BOUNDARY_PERIODIC boundary type.
6199 
6200    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
6201    a single value per point) you can skip filling those indices.
6202 
6203    Level: intermediate
6204 
6205 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6206           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6207 @*/
6208 PetscErrorCode MatZeroRowsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6209 {
6210   PetscInt       dim     = mat->stencil.dim;
6211   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6212   PetscInt       *dims   = mat->stencil.dims+1;
6213   PetscInt       *starts = mat->stencil.starts;
6214   PetscInt       *dxm    = (PetscInt*) rows;
6215   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6216 
6217   PetscFunctionBegin;
6218   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6219   PetscValidType(mat,1);
6220   if (numRows) PetscValidPointer(rows,3);
6221 
6222   PetscCall(PetscMalloc1(numRows, &jdxm));
6223   for (i = 0; i < numRows; ++i) {
6224     /* Skip unused dimensions (they are ordered k, j, i, c) */
6225     for (j = 0; j < 3-sdim; ++j) dxm++;
6226     /* Local index in X dir */
6227     tmp = *dxm++ - starts[0];
6228     /* Loop over remaining dimensions */
6229     for (j = 0; j < dim-1; ++j) {
6230       /* If nonlocal, set index to be negative */
6231       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6232       /* Update local index */
6233       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6234     }
6235     /* Skip component slot if necessary */
6236     if (mat->stencil.noc) dxm++;
6237     /* Local row number */
6238     if (tmp >= 0) {
6239       jdxm[numNewRows++] = tmp;
6240     }
6241   }
6242   PetscCall(MatZeroRowsLocal(mat,numNewRows,jdxm,diag,x,b));
6243   PetscCall(PetscFree(jdxm));
6244   PetscFunctionReturn(0);
6245 }
6246 
6247 /*@
6248    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6249    of a set of rows and columns of a matrix.
6250 
6251    Collective on Mat
6252 
6253    Input Parameters:
6254 +  mat - the matrix
6255 .  numRows - the number of rows/columns to remove
6256 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6257 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6258 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6259 -  b - optional vector of right hand side, that will be adjusted by provided solution
6260 
6261    Notes:
6262    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6263    but does not release memory.  For the dense and block diagonal
6264    formats this does not alter the nonzero structure.
6265 
6266    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6267    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6268    merely zeroed.
6269 
6270    The user can set a value in the diagonal entry (or for the AIJ and
6271    row formats can optionally remove the main diagonal entry from the
6272    nonzero structure as well, by passing 0.0 as the final argument).
6273 
6274    For the parallel case, all processes that share the matrix (i.e.,
6275    those in the communicator used for matrix creation) MUST call this
6276    routine, regardless of whether any rows being zeroed are owned by
6277    them.
6278 
6279    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6280    list only rows local to itself, but the row/column numbers are given in local numbering).
6281 
6282    The grid coordinates are across the entire grid, not just the local portion
6283 
6284    In Fortran idxm and idxn should be declared as
6285 $     MatStencil idxm(4,m)
6286    and the values inserted using
6287 $    idxm(MatStencil_i,1) = i
6288 $    idxm(MatStencil_j,1) = j
6289 $    idxm(MatStencil_k,1) = k
6290 $    idxm(MatStencil_c,1) = c
6291    etc
6292 
6293    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6294    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6295    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6296    DM_BOUNDARY_PERIODIC boundary type.
6297 
6298    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
6299    a single value per point) you can skip filling those indices.
6300 
6301    Level: intermediate
6302 
6303 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6304           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6305 @*/
6306 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6307 {
6308   PetscInt       dim     = mat->stencil.dim;
6309   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6310   PetscInt       *dims   = mat->stencil.dims+1;
6311   PetscInt       *starts = mat->stencil.starts;
6312   PetscInt       *dxm    = (PetscInt*) rows;
6313   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6314 
6315   PetscFunctionBegin;
6316   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6317   PetscValidType(mat,1);
6318   if (numRows) PetscValidPointer(rows,3);
6319 
6320   PetscCall(PetscMalloc1(numRows, &jdxm));
6321   for (i = 0; i < numRows; ++i) {
6322     /* Skip unused dimensions (they are ordered k, j, i, c) */
6323     for (j = 0; j < 3-sdim; ++j) dxm++;
6324     /* Local index in X dir */
6325     tmp = *dxm++ - starts[0];
6326     /* Loop over remaining dimensions */
6327     for (j = 0; j < dim-1; ++j) {
6328       /* If nonlocal, set index to be negative */
6329       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6330       /* Update local index */
6331       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6332     }
6333     /* Skip component slot if necessary */
6334     if (mat->stencil.noc) dxm++;
6335     /* Local row number */
6336     if (tmp >= 0) {
6337       jdxm[numNewRows++] = tmp;
6338     }
6339   }
6340   PetscCall(MatZeroRowsColumnsLocal(mat,numNewRows,jdxm,diag,x,b));
6341   PetscCall(PetscFree(jdxm));
6342   PetscFunctionReturn(0);
6343 }
6344 
6345 /*@C
6346    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6347    of a set of rows of a matrix; using local numbering of rows.
6348 
6349    Collective on Mat
6350 
6351    Input Parameters:
6352 +  mat - the matrix
6353 .  numRows - the number of rows to remove
6354 .  rows - the local row indices
6355 .  diag - value put in all diagonals of eliminated rows
6356 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6357 -  b - optional vector of right hand side, that will be adjusted by provided solution
6358 
6359    Notes:
6360    Before calling MatZeroRowsLocal(), the user must first set the
6361    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6362 
6363    For the AIJ matrix formats this removes the old nonzero structure,
6364    but does not release memory.  For the dense and block diagonal
6365    formats this does not alter the nonzero structure.
6366 
6367    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6368    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6369    merely zeroed.
6370 
6371    The user can set a value in the diagonal entry (or for the AIJ and
6372    row formats can optionally remove the main diagonal entry from the
6373    nonzero structure as well, by passing 0.0 as the final argument).
6374 
6375    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6376    owns that are to be zeroed. This saves a global synchronization in the implementation.
6377 
6378    Level: intermediate
6379 
6380 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6381           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6382 @*/
6383 PetscErrorCode MatZeroRowsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6384 {
6385   PetscFunctionBegin;
6386   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6387   PetscValidType(mat,1);
6388   if (numRows) PetscValidIntPointer(rows,3);
6389   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6390   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6391   MatCheckPreallocated(mat,1);
6392 
6393   if (mat->ops->zerorowslocal) {
6394     PetscCall((*mat->ops->zerorowslocal)(mat,numRows,rows,diag,x,b));
6395   } else {
6396     IS             is, newis;
6397     const PetscInt *newRows;
6398 
6399     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6400     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6401     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping,is,&newis));
6402     PetscCall(ISGetIndices(newis,&newRows));
6403     PetscCall((*mat->ops->zerorows)(mat,numRows,newRows,diag,x,b));
6404     PetscCall(ISRestoreIndices(newis,&newRows));
6405     PetscCall(ISDestroy(&newis));
6406     PetscCall(ISDestroy(&is));
6407   }
6408   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6409   PetscFunctionReturn(0);
6410 }
6411 
6412 /*@
6413    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6414    of a set of rows of a matrix; using local numbering of rows.
6415 
6416    Collective on Mat
6417 
6418    Input Parameters:
6419 +  mat - the matrix
6420 .  is - index set of rows to remove
6421 .  diag - value put in all diagonals of eliminated rows
6422 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6423 -  b - optional vector of right hand side, that will be adjusted by provided solution
6424 
6425    Notes:
6426    Before calling MatZeroRowsLocalIS(), the user must first set the
6427    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6428 
6429    For the AIJ matrix formats this removes the old nonzero structure,
6430    but does not release memory.  For the dense and block diagonal
6431    formats this does not alter the nonzero structure.
6432 
6433    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6434    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6435    merely zeroed.
6436 
6437    The user can set a value in the diagonal entry (or for the AIJ and
6438    row formats can optionally remove the main diagonal entry from the
6439    nonzero structure as well, by passing 0.0 as the final argument).
6440 
6441    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6442    owns that are to be zeroed. This saves a global synchronization in the implementation.
6443 
6444    Level: intermediate
6445 
6446 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6447           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6448 @*/
6449 PetscErrorCode MatZeroRowsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6450 {
6451   PetscInt       numRows;
6452   const PetscInt *rows;
6453 
6454   PetscFunctionBegin;
6455   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6456   PetscValidType(mat,1);
6457   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6458   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6459   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6460   MatCheckPreallocated(mat,1);
6461 
6462   PetscCall(ISGetLocalSize(is,&numRows));
6463   PetscCall(ISGetIndices(is,&rows));
6464   PetscCall(MatZeroRowsLocal(mat,numRows,rows,diag,x,b));
6465   PetscCall(ISRestoreIndices(is,&rows));
6466   PetscFunctionReturn(0);
6467 }
6468 
6469 /*@
6470    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6471    of a set of rows and columns of a matrix; using local numbering of rows.
6472 
6473    Collective on Mat
6474 
6475    Input Parameters:
6476 +  mat - the matrix
6477 .  numRows - the number of rows to remove
6478 .  rows - the global row indices
6479 .  diag - value put in all diagonals of eliminated rows
6480 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6481 -  b - optional vector of right hand side, that will be adjusted by provided solution
6482 
6483    Notes:
6484    Before calling MatZeroRowsColumnsLocal(), the user must first set the
6485    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6486 
6487    The user can set a value in the diagonal entry (or for the AIJ and
6488    row formats can optionally remove the main diagonal entry from the
6489    nonzero structure as well, by passing 0.0 as the final argument).
6490 
6491    Level: intermediate
6492 
6493 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6494           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6495 @*/
6496 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6497 {
6498   IS             is, newis;
6499   const PetscInt *newRows;
6500 
6501   PetscFunctionBegin;
6502   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6503   PetscValidType(mat,1);
6504   if (numRows) PetscValidIntPointer(rows,3);
6505   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6506   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6507   MatCheckPreallocated(mat,1);
6508 
6509   PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6510   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6511   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping,is,&newis));
6512   PetscCall(ISGetIndices(newis,&newRows));
6513   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,newRows,diag,x,b));
6514   PetscCall(ISRestoreIndices(newis,&newRows));
6515   PetscCall(ISDestroy(&newis));
6516   PetscCall(ISDestroy(&is));
6517   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6518   PetscFunctionReturn(0);
6519 }
6520 
6521 /*@
6522    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6523    of a set of rows and columns of a matrix; using local numbering of rows.
6524 
6525    Collective on Mat
6526 
6527    Input Parameters:
6528 +  mat - the matrix
6529 .  is - index set of rows to remove
6530 .  diag - value put in all diagonals of eliminated rows
6531 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6532 -  b - optional vector of right hand side, that will be adjusted by provided solution
6533 
6534    Notes:
6535    Before calling MatZeroRowsColumnsLocalIS(), the user must first set the
6536    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6537 
6538    The user can set a value in the diagonal entry (or for the AIJ and
6539    row formats can optionally remove the main diagonal entry from the
6540    nonzero structure as well, by passing 0.0 as the final argument).
6541 
6542    Level: intermediate
6543 
6544 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6545           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6546 @*/
6547 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6548 {
6549   PetscInt       numRows;
6550   const PetscInt *rows;
6551 
6552   PetscFunctionBegin;
6553   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6554   PetscValidType(mat,1);
6555   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6556   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6557   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6558   MatCheckPreallocated(mat,1);
6559 
6560   PetscCall(ISGetLocalSize(is,&numRows));
6561   PetscCall(ISGetIndices(is,&rows));
6562   PetscCall(MatZeroRowsColumnsLocal(mat,numRows,rows,diag,x,b));
6563   PetscCall(ISRestoreIndices(is,&rows));
6564   PetscFunctionReturn(0);
6565 }
6566 
6567 /*@C
6568    MatGetSize - Returns the numbers of rows and columns in a matrix.
6569 
6570    Not Collective
6571 
6572    Input Parameter:
6573 .  mat - the matrix
6574 
6575    Output Parameters:
6576 +  m - the number of global rows
6577 -  n - the number of global columns
6578 
6579    Note: both output parameters can be NULL on input.
6580 
6581    Level: beginner
6582 
6583 .seealso: `MatGetLocalSize()`
6584 @*/
6585 PetscErrorCode MatGetSize(Mat mat,PetscInt *m,PetscInt *n)
6586 {
6587   PetscFunctionBegin;
6588   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6589   if (m) *m = mat->rmap->N;
6590   if (n) *n = mat->cmap->N;
6591   PetscFunctionReturn(0);
6592 }
6593 
6594 /*@C
6595    MatGetLocalSize - Returns the number of local rows and local columns
6596    of a matrix, that is the local size of the left and right vectors as returned by MatCreateVecs().
6597 
6598    Not Collective
6599 
6600    Input Parameter:
6601 .  mat - the matrix
6602 
6603    Output Parameters:
6604 +  m - the number of local rows
6605 -  n - the number of local columns
6606 
6607    Note: both output parameters can be NULL on input.
6608 
6609    Level: beginner
6610 
6611 .seealso: `MatGetSize()`
6612 @*/
6613 PetscErrorCode MatGetLocalSize(Mat mat,PetscInt *m,PetscInt *n)
6614 {
6615   PetscFunctionBegin;
6616   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6617   if (m) PetscValidIntPointer(m,2);
6618   if (n) PetscValidIntPointer(n,3);
6619   if (m) *m = mat->rmap->n;
6620   if (n) *n = mat->cmap->n;
6621   PetscFunctionReturn(0);
6622 }
6623 
6624 /*@C
6625    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies by that owned by
6626    this processor. (The columns of the "diagonal block")
6627 
6628    Not Collective, unless matrix has not been allocated, then collective on Mat
6629 
6630    Input Parameter:
6631 .  mat - the matrix
6632 
6633    Output Parameters:
6634 +  m - the global index of the first local column
6635 -  n - one more than the global index of the last local column
6636 
6637    Notes:
6638     both output parameters can be NULL on input.
6639 
6640    Level: developer
6641 
6642 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`
6643 
6644 @*/
6645 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat,PetscInt *m,PetscInt *n)
6646 {
6647   PetscFunctionBegin;
6648   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6649   PetscValidType(mat,1);
6650   if (m) PetscValidIntPointer(m,2);
6651   if (n) PetscValidIntPointer(n,3);
6652   MatCheckPreallocated(mat,1);
6653   if (m) *m = mat->cmap->rstart;
6654   if (n) *n = mat->cmap->rend;
6655   PetscFunctionReturn(0);
6656 }
6657 
6658 /*@C
6659    MatGetOwnershipRange - Returns the range of matrix rows owned by
6660    this processor, assuming that the matrix is laid out with the first
6661    n1 rows on the first processor, the next n2 rows on the second, etc.
6662    For certain parallel layouts this range may not be well defined.
6663 
6664    Not Collective
6665 
6666    Input Parameter:
6667 .  mat - the matrix
6668 
6669    Output Parameters:
6670 +  m - the global index of the first local row
6671 -  n - one more than the global index of the last local row
6672 
6673    Note: Both output parameters can be NULL on input.
6674 $  This function requires that the matrix be preallocated. If you have not preallocated, consider using
6675 $    PetscSplitOwnership(MPI_Comm comm, PetscInt *n, PetscInt *N)
6676 $  and then MPI_Scan() to calculate prefix sums of the local sizes.
6677 
6678    Level: beginner
6679 
6680 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`
6681 
6682 @*/
6683 PetscErrorCode MatGetOwnershipRange(Mat mat,PetscInt *m,PetscInt *n)
6684 {
6685   PetscFunctionBegin;
6686   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6687   PetscValidType(mat,1);
6688   if (m) PetscValidIntPointer(m,2);
6689   if (n) PetscValidIntPointer(n,3);
6690   MatCheckPreallocated(mat,1);
6691   if (m) *m = mat->rmap->rstart;
6692   if (n) *n = mat->rmap->rend;
6693   PetscFunctionReturn(0);
6694 }
6695 
6696 /*@C
6697    MatGetOwnershipRanges - Returns the range of matrix rows owned by
6698    each process
6699 
6700    Not Collective, unless matrix has not been allocated, then collective on Mat
6701 
6702    Input Parameters:
6703 .  mat - the matrix
6704 
6705    Output Parameters:
6706 .  ranges - start of each processors portion plus one more than the total length at the end
6707 
6708    Level: beginner
6709 
6710 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`
6711 
6712 @*/
6713 PetscErrorCode MatGetOwnershipRanges(Mat mat,const PetscInt **ranges)
6714 {
6715   PetscFunctionBegin;
6716   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6717   PetscValidType(mat,1);
6718   MatCheckPreallocated(mat,1);
6719   PetscCall(PetscLayoutGetRanges(mat->rmap,ranges));
6720   PetscFunctionReturn(0);
6721 }
6722 
6723 /*@C
6724    MatGetOwnershipRangesColumn - Returns the range of matrix columns associated with rows of a vector one multiplies by that owned by
6725    this processor. (The columns of the "diagonal blocks" for each process)
6726 
6727    Not Collective, unless matrix has not been allocated, then collective on Mat
6728 
6729    Input Parameters:
6730 .  mat - the matrix
6731 
6732    Output Parameters:
6733 .  ranges - start of each processors portion plus one more then the total length at the end
6734 
6735    Level: beginner
6736 
6737 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6738 
6739 @*/
6740 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat,const PetscInt **ranges)
6741 {
6742   PetscFunctionBegin;
6743   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6744   PetscValidType(mat,1);
6745   MatCheckPreallocated(mat,1);
6746   PetscCall(PetscLayoutGetRanges(mat->cmap,ranges));
6747   PetscFunctionReturn(0);
6748 }
6749 
6750 /*@C
6751    MatGetOwnershipIS - Get row and column ownership as index sets
6752 
6753    Not Collective
6754 
6755    Input Parameter:
6756 .  A - matrix
6757 
6758    Output Parameters:
6759 +  rows - rows in which this process owns elements
6760 -  cols - columns in which this process owns elements
6761 
6762    Level: intermediate
6763 
6764 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
6765 @*/
6766 PetscErrorCode MatGetOwnershipIS(Mat A,IS *rows,IS *cols)
6767 {
6768   PetscErrorCode (*f)(Mat,IS*,IS*);
6769 
6770   PetscFunctionBegin;
6771   MatCheckPreallocated(A,1);
6772   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatGetOwnershipIS_C",&f));
6773   if (f) {
6774     PetscCall((*f)(A,rows,cols));
6775   } else {   /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6776     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->rmap->n,A->rmap->rstart,1,rows));
6777     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->cmap->N,0,1,cols));
6778   }
6779   PetscFunctionReturn(0);
6780 }
6781 
6782 /*@C
6783    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix.
6784    Uses levels of fill only, not drop tolerance. Use MatLUFactorNumeric()
6785    to complete the factorization.
6786 
6787    Collective on Mat
6788 
6789    Input Parameters:
6790 +  mat - the matrix
6791 .  row - row permutation
6792 .  column - column permutation
6793 -  info - structure containing
6794 $      levels - number of levels of fill.
6795 $      expected fill - as ratio of original fill.
6796 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6797                 missing diagonal entries)
6798 
6799    Output Parameters:
6800 .  fact - new matrix that has been symbolically factored
6801 
6802    Notes:
6803     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
6804 
6805    Most users should employ the simplified KSP interface for linear solvers
6806    instead of working directly with matrix algebra routines such as this.
6807    See, e.g., KSPCreate().
6808 
6809    Level: developer
6810 
6811 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6812           `MatGetOrdering()`, `MatFactorInfo`
6813 
6814     Note: this uses the definition of level of fill as in Y. Saad, 2003
6815 
6816     Developer Note: fortran interface is not autogenerated as the f90
6817     interface definition cannot be generated correctly [due to MatFactorInfo]
6818 
6819    References:
6820 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6821 @*/
6822 PetscErrorCode MatILUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
6823 {
6824   PetscFunctionBegin;
6825   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6826   PetscValidType(mat,2);
6827   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
6828   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
6829   PetscValidPointer(info,5);
6830   PetscValidPointer(fact,1);
6831   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels of fill negative %" PetscInt_FMT,(PetscInt)info->levels);
6832   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6833   if (!fact->ops->ilufactorsymbolic) {
6834     MatSolverType stype;
6835     PetscCall(MatFactorGetSolverType(fact,&stype));
6836     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ILU using solver type %s",((PetscObject)mat)->type_name,stype);
6837   }
6838   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6839   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6840   MatCheckPreallocated(mat,2);
6841 
6842   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic,mat,row,col,0));
6843   PetscCall((fact->ops->ilufactorsymbolic)(fact,mat,row,col,info));
6844   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic,mat,row,col,0));
6845   PetscFunctionReturn(0);
6846 }
6847 
6848 /*@C
6849    MatICCFactorSymbolic - Performs symbolic incomplete
6850    Cholesky factorization for a symmetric matrix.  Use
6851    MatCholeskyFactorNumeric() to complete the factorization.
6852 
6853    Collective on Mat
6854 
6855    Input Parameters:
6856 +  mat - the matrix
6857 .  perm - row and column permutation
6858 -  info - structure containing
6859 $      levels - number of levels of fill.
6860 $      expected fill - as ratio of original fill.
6861 
6862    Output Parameter:
6863 .  fact - the factored matrix
6864 
6865    Notes:
6866    Most users should employ the KSP interface for linear solvers
6867    instead of working directly with matrix algebra routines such as this.
6868    See, e.g., KSPCreate().
6869 
6870    Level: developer
6871 
6872 .seealso: `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6873 
6874     Note: this uses the definition of level of fill as in Y. Saad, 2003
6875 
6876     Developer Note: fortran interface is not autogenerated as the f90
6877     interface definition cannot be generated correctly [due to MatFactorInfo]
6878 
6879    References:
6880 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6881 @*/
6882 PetscErrorCode MatICCFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
6883 {
6884   PetscFunctionBegin;
6885   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6886   PetscValidType(mat,2);
6887   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
6888   PetscValidPointer(info,4);
6889   PetscValidPointer(fact,1);
6890   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6891   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels negative %" PetscInt_FMT,(PetscInt) info->levels);
6892   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6893   if (!(fact)->ops->iccfactorsymbolic) {
6894     MatSolverType stype;
6895     PetscCall(MatFactorGetSolverType(fact,&stype));
6896     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ICC using solver type %s",((PetscObject)mat)->type_name,stype);
6897   }
6898   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6899   MatCheckPreallocated(mat,2);
6900 
6901   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic,mat,perm,0,0));
6902   PetscCall((fact->ops->iccfactorsymbolic)(fact,mat,perm,info));
6903   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic,mat,perm,0,0));
6904   PetscFunctionReturn(0);
6905 }
6906 
6907 /*@C
6908    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6909    points to an array of valid matrices, they may be reused to store the new
6910    submatrices.
6911 
6912    Collective on Mat
6913 
6914    Input Parameters:
6915 +  mat - the matrix
6916 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6917 .  irow, icol - index sets of rows and columns to extract
6918 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6919 
6920    Output Parameter:
6921 .  submat - the array of submatrices
6922 
6923    Notes:
6924    MatCreateSubMatrices() can extract ONLY sequential submatrices
6925    (from both sequential and parallel matrices). Use MatCreateSubMatrix()
6926    to extract a parallel submatrix.
6927 
6928    Some matrix types place restrictions on the row and column
6929    indices, such as that they be sorted or that they be equal to each other.
6930 
6931    The index sets may not have duplicate entries.
6932 
6933    When extracting submatrices from a parallel matrix, each processor can
6934    form a different submatrix by setting the rows and columns of its
6935    individual index sets according to the local submatrix desired.
6936 
6937    When finished using the submatrices, the user should destroy
6938    them with MatDestroySubMatrices().
6939 
6940    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
6941    original matrix has not changed from that last call to MatCreateSubMatrices().
6942 
6943    This routine creates the matrices in submat; you should NOT create them before
6944    calling it. It also allocates the array of matrix pointers submat.
6945 
6946    For BAIJ matrices the index sets must respect the block structure, that is if they
6947    request one row/column in a block, they must request all rows/columns that are in
6948    that block. For example, if the block size is 2 you cannot request just row 0 and
6949    column 0.
6950 
6951    Fortran Note:
6952    The Fortran interface is slightly different from that given below; it
6953    requires one to pass in  as submat a Mat (integer) array of size at least n+1.
6954 
6955    Level: advanced
6956 
6957 .seealso: `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6958 @*/
6959 PetscErrorCode MatCreateSubMatrices(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
6960 {
6961   PetscInt       i;
6962   PetscBool      eq;
6963 
6964   PetscFunctionBegin;
6965   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6966   PetscValidType(mat,1);
6967   if (n) {
6968     PetscValidPointer(irow,3);
6969     for (i=0; i<n; i++) PetscValidHeaderSpecific(irow[i],IS_CLASSID,3);
6970     PetscValidPointer(icol,4);
6971     for (i=0; i<n; i++) PetscValidHeaderSpecific(icol[i],IS_CLASSID,4);
6972   }
6973   PetscValidPointer(submat,6);
6974   if (n && scall == MAT_REUSE_MATRIX) {
6975     PetscValidPointer(*submat,6);
6976     for (i=0; i<n; i++) PetscValidHeaderSpecific((*submat)[i],MAT_CLASSID,6);
6977   }
6978   PetscCheck(mat->ops->createsubmatrices,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6979   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6980   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6981   MatCheckPreallocated(mat,1);
6982   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
6983   PetscCall((*mat->ops->createsubmatrices)(mat,n,irow,icol,scall,submat));
6984   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
6985   for (i=0; i<n; i++) {
6986     (*submat)[i]->factortype = MAT_FACTOR_NONE;  /* in case in place factorization was previously done on submatrix */
6987     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
6988     if (eq) {
6989       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
6990     }
6991 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6992     if (mat->boundtocpu && mat->bindingpropagates) {
6993       PetscCall(MatBindToCPU((*submat)[i],PETSC_TRUE));
6994       PetscCall(MatSetBindingPropagates((*submat)[i],PETSC_TRUE));
6995     }
6996 #endif
6997   }
6998   PetscFunctionReturn(0);
6999 }
7000 
7001 /*@C
7002    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of IS that may live on subcomms).
7003 
7004    Collective on Mat
7005 
7006    Input Parameters:
7007 +  mat - the matrix
7008 .  n   - the number of submatrixes to be extracted
7009 .  irow, icol - index sets of rows and columns to extract
7010 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
7011 
7012    Output Parameter:
7013 .  submat - the array of submatrices
7014 
7015    Level: advanced
7016 
7017 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7018 @*/
7019 PetscErrorCode MatCreateSubMatricesMPI(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
7020 {
7021   PetscInt       i;
7022   PetscBool      eq;
7023 
7024   PetscFunctionBegin;
7025   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7026   PetscValidType(mat,1);
7027   if (n) {
7028     PetscValidPointer(irow,3);
7029     PetscValidHeaderSpecific(*irow,IS_CLASSID,3);
7030     PetscValidPointer(icol,4);
7031     PetscValidHeaderSpecific(*icol,IS_CLASSID,4);
7032   }
7033   PetscValidPointer(submat,6);
7034   if (n && scall == MAT_REUSE_MATRIX) {
7035     PetscValidPointer(*submat,6);
7036     PetscValidHeaderSpecific(**submat,MAT_CLASSID,6);
7037   }
7038   PetscCheck(mat->ops->createsubmatricesmpi,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7039   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7040   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7041   MatCheckPreallocated(mat,1);
7042 
7043   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
7044   PetscCall((*mat->ops->createsubmatricesmpi)(mat,n,irow,icol,scall,submat));
7045   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
7046   for (i=0; i<n; i++) {
7047     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
7048     if (eq) {
7049       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
7050     }
7051   }
7052   PetscFunctionReturn(0);
7053 }
7054 
7055 /*@C
7056    MatDestroyMatrices - Destroys an array of matrices.
7057 
7058    Collective on Mat
7059 
7060    Input Parameters:
7061 +  n - the number of local matrices
7062 -  mat - the matrices (note that this is a pointer to the array of matrices)
7063 
7064    Level: advanced
7065 
7066     Notes:
7067     Frees not only the matrices, but also the array that contains the matrices
7068            In Fortran will not free the array.
7069 
7070 .seealso: `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7071 @*/
7072 PetscErrorCode MatDestroyMatrices(PetscInt n,Mat *mat[])
7073 {
7074   PetscInt       i;
7075 
7076   PetscFunctionBegin;
7077   if (!*mat) PetscFunctionReturn(0);
7078   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7079   PetscValidPointer(mat,2);
7080 
7081   for (i=0; i<n; i++) {
7082     PetscCall(MatDestroy(&(*mat)[i]));
7083   }
7084 
7085   /* memory is allocated even if n = 0 */
7086   PetscCall(PetscFree(*mat));
7087   PetscFunctionReturn(0);
7088 }
7089 
7090 /*@C
7091    MatDestroySubMatrices - Destroys a set of matrices obtained with MatCreateSubMatrices().
7092 
7093    Collective on Mat
7094 
7095    Input Parameters:
7096 +  n - the number of local matrices
7097 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7098                        sequence of MatCreateSubMatrices())
7099 
7100    Level: advanced
7101 
7102     Notes:
7103     Frees not only the matrices, but also the array that contains the matrices
7104            In Fortran will not free the array.
7105 
7106 .seealso: `MatCreateSubMatrices()`
7107 @*/
7108 PetscErrorCode MatDestroySubMatrices(PetscInt n,Mat *mat[])
7109 {
7110   Mat            mat0;
7111 
7112   PetscFunctionBegin;
7113   if (!*mat) PetscFunctionReturn(0);
7114   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7115   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7116   PetscValidPointer(mat,2);
7117 
7118   mat0 = (*mat)[0];
7119   if (mat0 && mat0->ops->destroysubmatrices) {
7120     PetscCall((mat0->ops->destroysubmatrices)(n,mat));
7121   } else {
7122     PetscCall(MatDestroyMatrices(n,mat));
7123   }
7124   PetscFunctionReturn(0);
7125 }
7126 
7127 /*@C
7128    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7129 
7130    Collective on Mat
7131 
7132    Input Parameters:
7133 .  mat - the matrix
7134 
7135    Output Parameter:
7136 .  matstruct - the sequential matrix with the nonzero structure of mat
7137 
7138   Level: intermediate
7139 
7140 .seealso: `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7141 @*/
7142 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat,Mat *matstruct)
7143 {
7144   PetscFunctionBegin;
7145   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7146   PetscValidPointer(matstruct,2);
7147 
7148   PetscValidType(mat,1);
7149   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7150   MatCheckPreallocated(mat,1);
7151 
7152   PetscCheck(mat->ops->getseqnonzerostructure,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)mat)->type_name);
7153   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7154   PetscCall((*mat->ops->getseqnonzerostructure)(mat,matstruct));
7155   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7156   PetscFunctionReturn(0);
7157 }
7158 
7159 /*@C
7160    MatDestroySeqNonzeroStructure - Destroys matrix obtained with MatGetSeqNonzeroStructure().
7161 
7162    Collective on Mat
7163 
7164    Input Parameters:
7165 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7166                        sequence of MatGetSequentialNonzeroStructure())
7167 
7168    Level: advanced
7169 
7170     Notes:
7171     Frees not only the matrices, but also the array that contains the matrices
7172 
7173 .seealso: `MatGetSeqNonzeroStructure()`
7174 @*/
7175 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7176 {
7177   PetscFunctionBegin;
7178   PetscValidPointer(mat,1);
7179   PetscCall(MatDestroy(mat));
7180   PetscFunctionReturn(0);
7181 }
7182 
7183 /*@
7184    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7185    replaces the index sets by larger ones that represent submatrices with
7186    additional overlap.
7187 
7188    Collective on Mat
7189 
7190    Input Parameters:
7191 +  mat - the matrix
7192 .  n   - the number of index sets
7193 .  is  - the array of index sets (these index sets will changed during the call)
7194 -  ov  - the additional overlap requested
7195 
7196    Options Database:
7197 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7198 
7199    Level: developer
7200 
7201    Developer Note:
7202    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.
7203 
7204 .seealso: `MatCreateSubMatrices()`
7205 @*/
7206 PetscErrorCode MatIncreaseOverlap(Mat mat,PetscInt n,IS is[],PetscInt ov)
7207 {
7208   PetscInt       i,bs,cbs;
7209 
7210   PetscFunctionBegin;
7211   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7212   PetscValidType(mat,1);
7213   PetscValidLogicalCollectiveInt(mat,n,2);
7214   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7215   if (n) {
7216     PetscValidPointer(is,3);
7217     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i],IS_CLASSID,3);
7218   }
7219   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7220   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7221   MatCheckPreallocated(mat,1);
7222 
7223   if (!ov || !n) PetscFunctionReturn(0);
7224   PetscCheck(mat->ops->increaseoverlap,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7225   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7226   PetscCall((*mat->ops->increaseoverlap)(mat,n,is,ov));
7227   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7228   PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
7229   if (bs == cbs) {
7230     for (i=0; i<n; i++) {
7231       PetscCall(ISSetBlockSize(is[i],bs));
7232     }
7233   }
7234   PetscFunctionReturn(0);
7235 }
7236 
7237 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat,IS*,PetscInt);
7238 
7239 /*@
7240    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7241    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7242    additional overlap.
7243 
7244    Collective on Mat
7245 
7246    Input Parameters:
7247 +  mat - the matrix
7248 .  n   - the number of index sets
7249 .  is  - the array of index sets (these index sets will changed during the call)
7250 -  ov  - the additional overlap requested
7251 
7252    Options Database:
7253 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7254 
7255    Level: developer
7256 
7257 .seealso: `MatCreateSubMatrices()`
7258 @*/
7259 PetscErrorCode MatIncreaseOverlapSplit(Mat mat,PetscInt n,IS is[],PetscInt ov)
7260 {
7261   PetscInt       i;
7262 
7263   PetscFunctionBegin;
7264   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7265   PetscValidType(mat,1);
7266   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7267   if (n) {
7268     PetscValidPointer(is,3);
7269     PetscValidHeaderSpecific(*is,IS_CLASSID,3);
7270   }
7271   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7272   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7273   MatCheckPreallocated(mat,1);
7274   if (!ov) PetscFunctionReturn(0);
7275   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7276   for (i=0; i<n; i++) {
7277     PetscCall(MatIncreaseOverlapSplit_Single(mat,&is[i],ov));
7278   }
7279   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7280   PetscFunctionReturn(0);
7281 }
7282 
7283 /*@
7284    MatGetBlockSize - Returns the matrix block size.
7285 
7286    Not Collective
7287 
7288    Input Parameter:
7289 .  mat - the matrix
7290 
7291    Output Parameter:
7292 .  bs - block size
7293 
7294    Notes:
7295     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7296 
7297    If the block size has not been set yet this routine returns 1.
7298 
7299    Level: intermediate
7300 
7301 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7302 @*/
7303 PetscErrorCode MatGetBlockSize(Mat mat,PetscInt *bs)
7304 {
7305   PetscFunctionBegin;
7306   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7307   PetscValidIntPointer(bs,2);
7308   *bs = PetscAbs(mat->rmap->bs);
7309   PetscFunctionReturn(0);
7310 }
7311 
7312 /*@
7313    MatGetBlockSizes - Returns the matrix block row and column sizes.
7314 
7315    Not Collective
7316 
7317    Input Parameter:
7318 .  mat - the matrix
7319 
7320    Output Parameters:
7321 +  rbs - row block size
7322 -  cbs - column block size
7323 
7324    Notes:
7325     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7326     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7327 
7328    If a block size has not been set yet this routine returns 1.
7329 
7330    Level: intermediate
7331 
7332 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7333 @*/
7334 PetscErrorCode MatGetBlockSizes(Mat mat,PetscInt *rbs, PetscInt *cbs)
7335 {
7336   PetscFunctionBegin;
7337   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7338   if (rbs) PetscValidIntPointer(rbs,2);
7339   if (cbs) PetscValidIntPointer(cbs,3);
7340   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7341   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7342   PetscFunctionReturn(0);
7343 }
7344 
7345 /*@
7346    MatSetBlockSize - Sets the matrix block size.
7347 
7348    Logically Collective on Mat
7349 
7350    Input Parameters:
7351 +  mat - the matrix
7352 -  bs - block size
7353 
7354    Notes:
7355     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7356     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7357 
7358     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block size
7359     is compatible with the matrix local sizes.
7360 
7361    Level: intermediate
7362 
7363 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7364 @*/
7365 PetscErrorCode MatSetBlockSize(Mat mat,PetscInt bs)
7366 {
7367   PetscFunctionBegin;
7368   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7369   PetscValidLogicalCollectiveInt(mat,bs,2);
7370   PetscCall(MatSetBlockSizes(mat,bs,bs));
7371   PetscFunctionReturn(0);
7372 }
7373 
7374 typedef struct {
7375   PetscInt         n;
7376   IS               *is;
7377   Mat              *mat;
7378   PetscObjectState nonzerostate;
7379   Mat              C;
7380 } EnvelopeData;
7381 
7382 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7383 {
7384   for (PetscInt i=0; i<edata->n; i++) {
7385     PetscCall(ISDestroy(&edata->is[i]));
7386   }
7387   PetscCall(PetscFree(edata->is));
7388   PetscCall(PetscFree(edata));
7389   return 0;
7390 }
7391 
7392 /*
7393    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7394          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7395 
7396    Collective on mat
7397 
7398    Input Parameter:
7399 .  mat - the matrix
7400 
7401    Notes:
7402      There can be zeros within the blocks
7403 
7404      The blocks can overlap between processes, including laying on more than two processes
7405 
7406 */
7407 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7408 {
7409   PetscInt                    n,*sizes,*starts,i = 0,env = 0, tbs = 0, lblocks = 0,rstart,II,ln = 0,cnt = 0,cstart,cend;
7410   PetscInt                    *diag,*odiag,sc;
7411   VecScatter                  scatter;
7412   PetscScalar                 *seqv;
7413   const PetscScalar           *parv;
7414   const PetscInt              *ia,*ja;
7415   PetscBool                   set,flag,done;
7416   Mat                         AA = mat,A;
7417   MPI_Comm                    comm;
7418   PetscMPIInt                 rank,size,tag;
7419   MPI_Status                  status;
7420   PetscContainer              container;
7421   EnvelopeData                *edata;
7422   Vec                         seq,par;
7423   IS                          isglobal;
7424 
7425   PetscFunctionBegin;
7426   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7427   PetscCall(MatIsSymmetricKnown(mat,&set,&flag));
7428   if (!set || !flag) {
7429     /* TOO: only needs nonzero structure of transpose */
7430     PetscCall(MatTranspose(mat,MAT_INITIAL_MATRIX,&AA));
7431     PetscCall(MatAXPY(AA,1.0,mat,DIFFERENT_NONZERO_PATTERN));
7432   }
7433   PetscCall(MatAIJGetLocalMat(AA,&A));
7434   PetscCall(MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7435   PetscCheck(done,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unable to get IJ structure from matrix");
7436 
7437   PetscCall(MatGetLocalSize(mat,&n,NULL));
7438   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag));
7439   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
7440   PetscCallMPI(MPI_Comm_size(comm,&size));
7441   PetscCallMPI(MPI_Comm_rank(comm,&rank));
7442 
7443   PetscCall(PetscMalloc2(n,&sizes,n,&starts));
7444 
7445   if (rank > 0) {
7446     PetscCallMPI(MPI_Recv(&env,1,MPIU_INT,rank-1,tag,comm,&status));
7447     PetscCallMPI(MPI_Recv(&tbs,1,MPIU_INT,rank-1,tag,comm,&status));
7448   }
7449   PetscCall(MatGetOwnershipRange(mat,&rstart,NULL));
7450   for (i=0; i<n; i++) {
7451     env = PetscMax(env,ja[ia[i+1]-1]);
7452     II = rstart + i;
7453     if (env == II) {
7454       starts[lblocks]  = tbs;
7455       sizes[lblocks++] = 1 + II - tbs;
7456       tbs = 1 + II;
7457     }
7458   }
7459   if (rank < size-1) {
7460     PetscCallMPI(MPI_Send(&env,1,MPIU_INT,rank+1,tag,comm));
7461     PetscCallMPI(MPI_Send(&tbs,1,MPIU_INT,rank+1,tag,comm));
7462   }
7463 
7464   PetscCall(MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7465   if (!set || !flag) {
7466     PetscCall(MatDestroy(&AA));
7467   }
7468   PetscCall(MatDestroy(&A));
7469 
7470   PetscCall(PetscNew(&edata));
7471   PetscCall(MatGetNonzeroState(mat,&edata->nonzerostate));
7472   edata->n = lblocks;
7473   /* create IS needed for extracting blocks from the original matrix */
7474   PetscCall(PetscMalloc1(lblocks,&edata->is));
7475   for (PetscInt i=0; i<lblocks; i++) {
7476     PetscCall(ISCreateStride(PETSC_COMM_SELF,sizes[i],starts[i],1,&edata->is[i]));
7477   }
7478 
7479   /* Create the resulting inverse matrix structure with preallocation information */
7480   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&edata->C));
7481   PetscCall(MatSetSizes(edata->C,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
7482   PetscCall(MatSetBlockSizesFromMats(edata->C,mat,mat));
7483   PetscCall(MatSetType(edata->C,MATAIJ));
7484 
7485   /* Communicate the start and end of each row, from each block to the correct rank */
7486   /* TODO: Use PetscSF instead of VecScatter */
7487   for (PetscInt i=0; i<lblocks; i++) ln += sizes[i];
7488   PetscCall(VecCreateSeq(PETSC_COMM_SELF,2*ln,&seq));
7489   PetscCall(VecGetArrayWrite(seq,&seqv));
7490   for (PetscInt i=0; i<lblocks; i++) {
7491     for (PetscInt j=0; j<sizes[i]; j++) {
7492       seqv[cnt]   = starts[i];
7493       seqv[cnt+1] = starts[i] + sizes[i];
7494       cnt += 2;
7495     }
7496   }
7497   PetscCall(VecRestoreArrayWrite(seq,&seqv));
7498   PetscCallMPI(MPI_Scan(&cnt,&sc,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
7499   sc -= cnt;
7500   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat),2*mat->rmap->n,2*mat->rmap->N,&par));
7501   PetscCall(ISCreateStride(PETSC_COMM_SELF,cnt,sc,1,&isglobal));
7502   PetscCall(VecScatterCreate(seq, NULL  ,par, isglobal,&scatter));
7503   PetscCall(ISDestroy(&isglobal));
7504   PetscCall(VecScatterBegin(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7505   PetscCall(VecScatterEnd(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7506   PetscCall(VecScatterDestroy(&scatter));
7507   PetscCall(VecDestroy(&seq));
7508   PetscCall(MatGetOwnershipRangeColumn(mat,&cstart,&cend));
7509   PetscCall(PetscMalloc2(mat->rmap->n,&diag,mat->rmap->n,&odiag));
7510   PetscCall(VecGetArrayRead(par,&parv));
7511   cnt = 0;
7512   PetscCall(MatGetSize(mat,NULL,&n));
7513   for (PetscInt i=0; i<mat->rmap->n; i++) {
7514     PetscInt start,end,d = 0,od = 0;
7515 
7516     start = (PetscInt)PetscRealPart(parv[cnt]);
7517     end   = (PetscInt)PetscRealPart(parv[cnt+1]);
7518     cnt  += 2;
7519 
7520     if (start < cstart) {od += cstart - start + n - cend; d += cend - cstart;}
7521     else if (start < cend) {od += n - cend; d += cend - start;}
7522     else od += n - start;
7523     if (end <= cstart) {od -= cstart - end + n - cend; d -= cend - cstart;}
7524     else if (end < cend) {od -= n - cend; d -= cend - end;}
7525     else od -= n - end;
7526 
7527     odiag[i] = od;
7528     diag[i]  = d;
7529   }
7530   PetscCall(VecRestoreArrayRead(par,&parv));
7531   PetscCall(VecDestroy(&par));
7532   PetscCall(MatXAIJSetPreallocation(edata->C,mat->rmap->bs,diag,odiag,NULL,NULL));
7533   PetscCall(PetscFree2(diag,odiag));
7534   PetscCall(PetscFree2(sizes,starts));
7535 
7536   PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&container));
7537   PetscCall(PetscContainerSetPointer(container,edata));
7538   PetscCall(PetscContainerSetUserDestroy(container,(PetscErrorCode (*)(void*))EnvelopeDataDestroy));
7539   PetscCall(PetscObjectCompose((PetscObject)mat,"EnvelopeData",(PetscObject)container));
7540   PetscCall(PetscObjectDereference((PetscObject)container));
7541   PetscFunctionReturn(0);
7542 }
7543 
7544 /*@
7545   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7546 
7547   Collective on Mat
7548 
7549   Input Parameters:
7550 . A - the matrix
7551 
7552   Output Parameters:
7553 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7554 
7555   Notes:
7556      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7557 
7558   Level: advanced
7559 
7560 .seealso: MatInvertBlockDiagonal(), MatComputeBlockDiagonal()
7561 @*/
7562 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A,MatReuse reuse, Mat *C)
7563 {
7564   PetscContainer    container;
7565   EnvelopeData      *edata;
7566   PetscObjectState  nonzerostate;
7567 
7568   PetscFunctionBegin;
7569   PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7570   if (!container) {
7571     PetscCall(MatComputeVariableBlockEnvelope(A));
7572     PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7573   }
7574   PetscCall(PetscContainerGetPointer(container,(void**)&edata));
7575   PetscCall(MatGetNonzeroState(A,&nonzerostate));
7576   PetscCheck(nonzerostate <= edata->nonzerostate,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Cannot handle changes to matrix nonzero structure");
7577   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"C matrix must be the same as previously output");
7578 
7579   PetscCall(MatCreateSubMatrices(A,edata->n,edata->is,edata->is,MAT_INITIAL_MATRIX,&edata->mat));
7580   *C   = edata->C;
7581 
7582   for (PetscInt i=0; i<edata->n; i++) {
7583     Mat         D;
7584     PetscScalar *dvalues;
7585 
7586     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE,MAT_INITIAL_MATRIX,&D));
7587     PetscCall(MatSetOption(*C,MAT_ROW_ORIENTED,PETSC_FALSE));
7588     PetscCall(MatSeqDenseInvert(D));
7589     PetscCall(MatDenseGetArray(D,&dvalues));
7590     PetscCall(MatSetValuesIS(*C,edata->is[i],edata->is[i],dvalues,INSERT_VALUES));
7591     PetscCall(MatDestroy(&D));
7592   }
7593   PetscCall(MatDestroySubMatrices(edata->n,&edata->mat));
7594   PetscCall(MatAssemblyBegin(*C,MAT_FINAL_ASSEMBLY));
7595   PetscCall(MatAssemblyEnd(*C,MAT_FINAL_ASSEMBLY));
7596   PetscFunctionReturn(0);
7597 }
7598 
7599 /*@
7600    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7601 
7602    Logically Collective on Mat
7603 
7604    Input Parameters:
7605 +  mat - the matrix
7606 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7607 -  bsizes - the block sizes
7608 
7609    Notes:
7610     Currently used by PCVPBJACOBI for AIJ matrices
7611 
7612     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.
7613 
7614    Level: intermediate
7615 
7616 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7617 @*/
7618 PetscErrorCode MatSetVariableBlockSizes(Mat mat,PetscInt nblocks,PetscInt *bsizes)
7619 {
7620   PetscInt       i,ncnt = 0, nlocal;
7621 
7622   PetscFunctionBegin;
7623   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7624   PetscCheck(nblocks >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Number of local blocks must be great than or equal to zero");
7625   PetscCall(MatGetLocalSize(mat,&nlocal,NULL));
7626   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
7627   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);
7628   PetscCall(PetscFree(mat->bsizes));
7629   mat->nblocks = nblocks;
7630   PetscCall(PetscMalloc1(nblocks,&mat->bsizes));
7631   PetscCall(PetscArraycpy(mat->bsizes,bsizes,nblocks));
7632   PetscFunctionReturn(0);
7633 }
7634 
7635 /*@C
7636    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7637 
7638    Logically Collective on Mat
7639 
7640    Input Parameter:
7641 .  mat - the matrix
7642 
7643    Output Parameters:
7644 +  nblocks - the number of blocks on this process
7645 -  bsizes - the block sizes
7646 
7647    Notes: Currently not supported from Fortran
7648 
7649    Level: intermediate
7650 
7651 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7652 @*/
7653 PetscErrorCode MatGetVariableBlockSizes(Mat mat,PetscInt *nblocks,const PetscInt **bsizes)
7654 {
7655   PetscFunctionBegin;
7656   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7657   *nblocks = mat->nblocks;
7658   *bsizes  = mat->bsizes;
7659   PetscFunctionReturn(0);
7660 }
7661 
7662 /*@
7663    MatSetBlockSizes - Sets the matrix block row and column sizes.
7664 
7665    Logically Collective on Mat
7666 
7667    Input Parameters:
7668 +  mat - the matrix
7669 .  rbs - row block size
7670 -  cbs - column block size
7671 
7672    Notes:
7673     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7674     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7675     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7676 
7677     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block sizes
7678     are compatible with the matrix local sizes.
7679 
7680     The row and column block size determine the blocksize of the "row" and "column" vectors returned by MatCreateVecs().
7681 
7682    Level: intermediate
7683 
7684 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7685 @*/
7686 PetscErrorCode MatSetBlockSizes(Mat mat,PetscInt rbs,PetscInt cbs)
7687 {
7688   PetscFunctionBegin;
7689   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7690   PetscValidLogicalCollectiveInt(mat,rbs,2);
7691   PetscValidLogicalCollectiveInt(mat,cbs,3);
7692   if (mat->ops->setblocksizes) PetscCall((*mat->ops->setblocksizes)(mat,rbs,cbs));
7693   if (mat->rmap->refcnt) {
7694     ISLocalToGlobalMapping l2g = NULL;
7695     PetscLayout            nmap = NULL;
7696 
7697     PetscCall(PetscLayoutDuplicate(mat->rmap,&nmap));
7698     if (mat->rmap->mapping) {
7699       PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping,&l2g));
7700     }
7701     PetscCall(PetscLayoutDestroy(&mat->rmap));
7702     mat->rmap = nmap;
7703     mat->rmap->mapping = l2g;
7704   }
7705   if (mat->cmap->refcnt) {
7706     ISLocalToGlobalMapping l2g = NULL;
7707     PetscLayout            nmap = NULL;
7708 
7709     PetscCall(PetscLayoutDuplicate(mat->cmap,&nmap));
7710     if (mat->cmap->mapping) {
7711       PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping,&l2g));
7712     }
7713     PetscCall(PetscLayoutDestroy(&mat->cmap));
7714     mat->cmap = nmap;
7715     mat->cmap->mapping = l2g;
7716   }
7717   PetscCall(PetscLayoutSetBlockSize(mat->rmap,rbs));
7718   PetscCall(PetscLayoutSetBlockSize(mat->cmap,cbs));
7719   PetscFunctionReturn(0);
7720 }
7721 
7722 /*@
7723    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7724 
7725    Logically Collective on Mat
7726 
7727    Input Parameters:
7728 +  mat - the matrix
7729 .  fromRow - matrix from which to copy row block size
7730 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7731 
7732    Level: developer
7733 
7734 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7735 @*/
7736 PetscErrorCode MatSetBlockSizesFromMats(Mat mat,Mat fromRow,Mat fromCol)
7737 {
7738   PetscFunctionBegin;
7739   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7740   PetscValidHeaderSpecific(fromRow,MAT_CLASSID,2);
7741   PetscValidHeaderSpecific(fromCol,MAT_CLASSID,3);
7742   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap,fromRow->rmap->bs));
7743   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap,fromCol->cmap->bs));
7744   PetscFunctionReturn(0);
7745 }
7746 
7747 /*@
7748    MatResidual - Default routine to calculate the residual.
7749 
7750    Collective on Mat
7751 
7752    Input Parameters:
7753 +  mat - the matrix
7754 .  b   - the right-hand-side
7755 -  x   - the approximate solution
7756 
7757    Output Parameter:
7758 .  r - location to store the residual
7759 
7760    Level: developer
7761 
7762 .seealso: `PCMGSetResidual()`
7763 @*/
7764 PetscErrorCode MatResidual(Mat mat,Vec b,Vec x,Vec r)
7765 {
7766   PetscFunctionBegin;
7767   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7768   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
7769   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
7770   PetscValidHeaderSpecific(r,VEC_CLASSID,4);
7771   PetscValidType(mat,1);
7772   MatCheckPreallocated(mat,1);
7773   PetscCall(PetscLogEventBegin(MAT_Residual,mat,0,0,0));
7774   if (!mat->ops->residual) {
7775     PetscCall(MatMult(mat,x,r));
7776     PetscCall(VecAYPX(r,-1.0,b));
7777   } else {
7778     PetscCall((*mat->ops->residual)(mat,b,x,r));
7779   }
7780   PetscCall(PetscLogEventEnd(MAT_Residual,mat,0,0,0));
7781   PetscFunctionReturn(0);
7782 }
7783 
7784 /*@C
7785     MatGetRowIJ - Returns the compressed row storage i and j indices for sequential matrices.
7786 
7787    Collective on Mat
7788 
7789     Input Parameters:
7790 +   mat - the matrix
7791 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7792 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be   symmetrized
7793 -   inodecompressed - PETSC_TRUE or PETSC_FALSE  indicating if the nonzero structure of the
7794                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7795                  always used.
7796 
7797     Output Parameters:
7798 +   n - number of rows in the (possibly compressed) matrix
7799 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7800 .   ja - the column indices
7801 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7802            are responsible for handling the case when done == PETSC_FALSE and ia and ja are not set
7803 
7804     Level: developer
7805 
7806     Notes:
7807     You CANNOT change any of the ia[] or ja[] values.
7808 
7809     Use MatRestoreRowIJ() when you are finished accessing the ia[] and ja[] values.
7810 
7811     Fortran Notes:
7812     In Fortran use
7813 $
7814 $      PetscInt ia(1), ja(1)
7815 $      PetscOffset iia, jja
7816 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7817 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7818 
7819      or
7820 $
7821 $    PetscInt, pointer :: ia(:),ja(:)
7822 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7823 $    ! Access the ith and jth entries via ia(i) and ja(j)
7824 
7825 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7826 @*/
7827 PetscErrorCode MatGetRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7828 {
7829   PetscFunctionBegin;
7830   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7831   PetscValidType(mat,1);
7832   PetscValidIntPointer(n,5);
7833   if (ia) PetscValidPointer(ia,6);
7834   if (ja) PetscValidPointer(ja,7);
7835   PetscValidBoolPointer(done,8);
7836   MatCheckPreallocated(mat,1);
7837   if (!mat->ops->getrowij) *done = PETSC_FALSE;
7838   else {
7839     *done = PETSC_TRUE;
7840     PetscCall(PetscLogEventBegin(MAT_GetRowIJ,mat,0,0,0));
7841     PetscCall((*mat->ops->getrowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7842     PetscCall(PetscLogEventEnd(MAT_GetRowIJ,mat,0,0,0));
7843   }
7844   PetscFunctionReturn(0);
7845 }
7846 
7847 /*@C
7848     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7849 
7850     Collective on Mat
7851 
7852     Input Parameters:
7853 +   mat - the matrix
7854 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7855 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7856                 symmetrized
7857 .   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7858                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7859                  always used.
7860 .   n - number of columns in the (possibly compressed) matrix
7861 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7862 -   ja - the row indices
7863 
7864     Output Parameters:
7865 .   done - PETSC_TRUE or PETSC_FALSE, indicating whether the values have been returned
7866 
7867     Level: developer
7868 
7869 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7870 @*/
7871 PetscErrorCode MatGetColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7872 {
7873   PetscFunctionBegin;
7874   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7875   PetscValidType(mat,1);
7876   PetscValidIntPointer(n,5);
7877   if (ia) PetscValidPointer(ia,6);
7878   if (ja) PetscValidPointer(ja,7);
7879   PetscValidBoolPointer(done,8);
7880   MatCheckPreallocated(mat,1);
7881   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7882   else {
7883     *done = PETSC_TRUE;
7884     PetscCall((*mat->ops->getcolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7885   }
7886   PetscFunctionReturn(0);
7887 }
7888 
7889 /*@C
7890     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with
7891     MatGetRowIJ().
7892 
7893     Collective on Mat
7894 
7895     Input Parameters:
7896 +   mat - the matrix
7897 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7898 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7899                 symmetrized
7900 .   inodecompressed -  PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7901                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7902                  always used.
7903 .   n - size of (possibly compressed) matrix
7904 .   ia - the row pointers
7905 -   ja - the column indices
7906 
7907     Output Parameters:
7908 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7909 
7910     Note:
7911     This routine zeros out n, ia, and ja. This is to prevent accidental
7912     us of the array after it has been restored. If you pass NULL, it will
7913     not zero the pointers.  Use of ia or ja after MatRestoreRowIJ() is invalid.
7914 
7915     Level: developer
7916 
7917 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7918 @*/
7919 PetscErrorCode MatRestoreRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7920 {
7921   PetscFunctionBegin;
7922   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7923   PetscValidType(mat,1);
7924   if (ia) PetscValidPointer(ia,6);
7925   if (ja) PetscValidPointer(ja,7);
7926   PetscValidBoolPointer(done,8);
7927   MatCheckPreallocated(mat,1);
7928 
7929   if (!mat->ops->restorerowij) *done = PETSC_FALSE;
7930   else {
7931     *done = PETSC_TRUE;
7932     PetscCall((*mat->ops->restorerowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7933     if (n)  *n = 0;
7934     if (ia) *ia = NULL;
7935     if (ja) *ja = NULL;
7936   }
7937   PetscFunctionReturn(0);
7938 }
7939 
7940 /*@C
7941     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with
7942     MatGetColumnIJ().
7943 
7944     Collective on Mat
7945 
7946     Input Parameters:
7947 +   mat - the matrix
7948 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7949 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7950                 symmetrized
7951 -   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7952                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7953                  always used.
7954 
7955     Output Parameters:
7956 +   n - size of (possibly compressed) matrix
7957 .   ia - the column pointers
7958 .   ja - the row indices
7959 -   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7960 
7961     Level: developer
7962 
7963 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7964 @*/
7965 PetscErrorCode MatRestoreColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7966 {
7967   PetscFunctionBegin;
7968   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7969   PetscValidType(mat,1);
7970   if (ia) PetscValidPointer(ia,6);
7971   if (ja) PetscValidPointer(ja,7);
7972   PetscValidBoolPointer(done,8);
7973   MatCheckPreallocated(mat,1);
7974 
7975   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7976   else {
7977     *done = PETSC_TRUE;
7978     PetscCall((*mat->ops->restorecolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7979     if (n)  *n = 0;
7980     if (ia) *ia = NULL;
7981     if (ja) *ja = NULL;
7982   }
7983   PetscFunctionReturn(0);
7984 }
7985 
7986 /*@C
7987     MatColoringPatch -Used inside matrix coloring routines that
7988     use MatGetRowIJ() and/or MatGetColumnIJ().
7989 
7990     Collective on Mat
7991 
7992     Input Parameters:
7993 +   mat - the matrix
7994 .   ncolors - max color value
7995 .   n   - number of entries in colorarray
7996 -   colorarray - array indicating color for each column
7997 
7998     Output Parameters:
7999 .   iscoloring - coloring generated using colorarray information
8000 
8001     Level: developer
8002 
8003 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
8004 
8005 @*/
8006 PetscErrorCode MatColoringPatch(Mat mat,PetscInt ncolors,PetscInt n,ISColoringValue colorarray[],ISColoring *iscoloring)
8007 {
8008   PetscFunctionBegin;
8009   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8010   PetscValidType(mat,1);
8011   PetscValidIntPointer(colorarray,4);
8012   PetscValidPointer(iscoloring,5);
8013   MatCheckPreallocated(mat,1);
8014 
8015   if (!mat->ops->coloringpatch) {
8016     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat),ncolors,n,colorarray,PETSC_OWN_POINTER,iscoloring));
8017   } else {
8018     PetscCall((*mat->ops->coloringpatch)(mat,ncolors,n,colorarray,iscoloring));
8019   }
8020   PetscFunctionReturn(0);
8021 }
8022 
8023 /*@
8024    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8025 
8026    Logically Collective on Mat
8027 
8028    Input Parameter:
8029 .  mat - the factored matrix to be reset
8030 
8031    Notes:
8032    This routine should be used only with factored matrices formed by in-place
8033    factorization via ILU(0) (or by in-place LU factorization for the MATSEQDENSE
8034    format).  This option can save memory, for example, when solving nonlinear
8035    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8036    ILU(0) preconditioner.
8037 
8038    Note that one can specify in-place ILU(0) factorization by calling
8039 .vb
8040      PCType(pc,PCILU);
8041      PCFactorSeUseInPlace(pc);
8042 .ve
8043    or by using the options -pc_type ilu -pc_factor_in_place
8044 
8045    In-place factorization ILU(0) can also be used as a local
8046    solver for the blocks within the block Jacobi or additive Schwarz
8047    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8048    for details on setting local solver options.
8049 
8050    Most users should employ the simplified KSP interface for linear solvers
8051    instead of working directly with matrix algebra routines such as this.
8052    See, e.g., KSPCreate().
8053 
8054    Level: developer
8055 
8056 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8057 
8058 @*/
8059 PetscErrorCode MatSetUnfactored(Mat mat)
8060 {
8061   PetscFunctionBegin;
8062   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8063   PetscValidType(mat,1);
8064   MatCheckPreallocated(mat,1);
8065   mat->factortype = MAT_FACTOR_NONE;
8066   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
8067   PetscCall((*mat->ops->setunfactored)(mat));
8068   PetscFunctionReturn(0);
8069 }
8070 
8071 /*MC
8072     MatDenseGetArrayF90 - Accesses a matrix array from Fortran90.
8073 
8074     Synopsis:
8075     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8076 
8077     Not collective
8078 
8079     Input Parameter:
8080 .   x - matrix
8081 
8082     Output Parameters:
8083 +   xx_v - the Fortran90 pointer to the array
8084 -   ierr - error code
8085 
8086     Example of Usage:
8087 .vb
8088       PetscScalar, pointer xx_v(:,:)
8089       ....
8090       call MatDenseGetArrayF90(x,xx_v,ierr)
8091       a = xx_v(3)
8092       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8093 .ve
8094 
8095     Level: advanced
8096 
8097 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8098 
8099 M*/
8100 
8101 /*MC
8102     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8103     accessed with MatDenseGetArrayF90().
8104 
8105     Synopsis:
8106     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8107 
8108     Not collective
8109 
8110     Input Parameters:
8111 +   x - matrix
8112 -   xx_v - the Fortran90 pointer to the array
8113 
8114     Output Parameter:
8115 .   ierr - error code
8116 
8117     Example of Usage:
8118 .vb
8119        PetscScalar, pointer xx_v(:,:)
8120        ....
8121        call MatDenseGetArrayF90(x,xx_v,ierr)
8122        a = xx_v(3)
8123        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8124 .ve
8125 
8126     Level: advanced
8127 
8128 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8129 
8130 M*/
8131 
8132 /*MC
8133     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran90.
8134 
8135     Synopsis:
8136     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8137 
8138     Not collective
8139 
8140     Input Parameter:
8141 .   x - matrix
8142 
8143     Output Parameters:
8144 +   xx_v - the Fortran90 pointer to the array
8145 -   ierr - error code
8146 
8147     Example of Usage:
8148 .vb
8149       PetscScalar, pointer xx_v(:)
8150       ....
8151       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8152       a = xx_v(3)
8153       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8154 .ve
8155 
8156     Level: advanced
8157 
8158 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8159 
8160 M*/
8161 
8162 /*MC
8163     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8164     accessed with MatSeqAIJGetArrayF90().
8165 
8166     Synopsis:
8167     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8168 
8169     Not collective
8170 
8171     Input Parameters:
8172 +   x - matrix
8173 -   xx_v - the Fortran90 pointer to the array
8174 
8175     Output Parameter:
8176 .   ierr - error code
8177 
8178     Example of Usage:
8179 .vb
8180        PetscScalar, pointer xx_v(:)
8181        ....
8182        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8183        a = xx_v(3)
8184        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8185 .ve
8186 
8187     Level: advanced
8188 
8189 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8190 
8191 M*/
8192 
8193 /*@
8194     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8195                       as the original matrix.
8196 
8197     Collective on Mat
8198 
8199     Input Parameters:
8200 +   mat - the original matrix
8201 .   isrow - parallel IS containing the rows this processor should obtain
8202 .   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.
8203 -   cll - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
8204 
8205     Output Parameter:
8206 .   newmat - the new submatrix, of the same type as the old
8207 
8208     Level: advanced
8209 
8210     Notes:
8211     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8212 
8213     Some matrix types place restrictions on the row and column indices, such
8214     as that they be sorted or that they be equal to each other.
8215 
8216     The index sets may not have duplicate entries.
8217 
8218       The first time this is called you should use a cll of MAT_INITIAL_MATRIX,
8219    the MatCreateSubMatrix() routine will create the newmat for you. Any additional calls
8220    to this routine with a mat of the same nonzero structure and with a call of MAT_REUSE_MATRIX
8221    will reuse the matrix generated the first time.  You should call MatDestroy() on newmat when
8222    you are finished using it.
8223 
8224     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8225     the input matrix.
8226 
8227     If iscol is NULL then all columns are obtained (not supported in Fortran).
8228 
8229    Example usage:
8230    Consider the following 8x8 matrix with 34 non-zero values, that is
8231    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8232    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8233    as follows:
8234 
8235 .vb
8236             1  2  0  |  0  3  0  |  0  4
8237     Proc0   0  5  6  |  7  0  0  |  8  0
8238             9  0 10  | 11  0  0  | 12  0
8239     -------------------------------------
8240            13  0 14  | 15 16 17  |  0  0
8241     Proc1   0 18  0  | 19 20 21  |  0  0
8242             0  0  0  | 22 23  0  | 24  0
8243     -------------------------------------
8244     Proc2  25 26 27  |  0  0 28  | 29  0
8245            30  0  0  | 31 32 33  |  0 34
8246 .ve
8247 
8248     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8249 
8250 .vb
8251             2  0  |  0  3  0  |  0
8252     Proc0   5  6  |  7  0  0  |  8
8253     -------------------------------
8254     Proc1  18  0  | 19 20 21  |  0
8255     -------------------------------
8256     Proc2  26 27  |  0  0 28  | 29
8257             0  0  | 31 32 33  |  0
8258 .ve
8259 
8260 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8261 @*/
8262 PetscErrorCode MatCreateSubMatrix(Mat mat,IS isrow,IS iscol,MatReuse cll,Mat *newmat)
8263 {
8264   PetscMPIInt    size;
8265   Mat            *local;
8266   IS             iscoltmp;
8267   PetscBool      flg;
8268 
8269   PetscFunctionBegin;
8270   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8271   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
8272   if (iscol) PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
8273   PetscValidPointer(newmat,5);
8274   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat,MAT_CLASSID,5);
8275   PetscValidType(mat,1);
8276   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8277   PetscCheck(cll != MAT_IGNORE_MATRIX,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Cannot use MAT_IGNORE_MATRIX");
8278 
8279   MatCheckPreallocated(mat,1);
8280   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8281 
8282   if (!iscol || isrow == iscol) {
8283     PetscBool   stride;
8284     PetscMPIInt grabentirematrix = 0,grab;
8285     PetscCall(PetscObjectTypeCompare((PetscObject)isrow,ISSTRIDE,&stride));
8286     if (stride) {
8287       PetscInt first,step,n,rstart,rend;
8288       PetscCall(ISStrideGetInfo(isrow,&first,&step));
8289       if (step == 1) {
8290         PetscCall(MatGetOwnershipRange(mat,&rstart,&rend));
8291         if (rstart == first) {
8292           PetscCall(ISGetLocalSize(isrow,&n));
8293           if (n == rend-rstart) {
8294             grabentirematrix = 1;
8295           }
8296         }
8297       }
8298     }
8299     PetscCall(MPIU_Allreduce(&grabentirematrix,&grab,1,MPI_INT,MPI_MIN,PetscObjectComm((PetscObject)mat)));
8300     if (grab) {
8301       PetscCall(PetscInfo(mat,"Getting entire matrix as submatrix\n"));
8302       if (cll == MAT_INITIAL_MATRIX) {
8303         *newmat = mat;
8304         PetscCall(PetscObjectReference((PetscObject)mat));
8305       }
8306       PetscFunctionReturn(0);
8307     }
8308   }
8309 
8310   if (!iscol) {
8311     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat),mat->cmap->n,mat->cmap->rstart,1,&iscoltmp));
8312   } else {
8313     iscoltmp = iscol;
8314   }
8315 
8316   /* if original matrix is on just one processor then use submatrix generated */
8317   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8318     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_REUSE_MATRIX,&newmat));
8319     goto setproperties;
8320   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8321     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_INITIAL_MATRIX,&local));
8322     *newmat = *local;
8323     PetscCall(PetscFree(local));
8324     goto setproperties;
8325   } else if (!mat->ops->createsubmatrix) {
8326     /* Create a new matrix type that implements the operation using the full matrix */
8327     PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8328     switch (cll) {
8329     case MAT_INITIAL_MATRIX:
8330       PetscCall(MatCreateSubMatrixVirtual(mat,isrow,iscoltmp,newmat));
8331       break;
8332     case MAT_REUSE_MATRIX:
8333       PetscCall(MatSubMatrixVirtualUpdate(*newmat,mat,isrow,iscoltmp));
8334       break;
8335     default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8336     }
8337     PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8338     goto setproperties;
8339   }
8340 
8341   PetscCheck(mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8342   PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8343   PetscCall((*mat->ops->createsubmatrix)(mat,isrow,iscoltmp,cll,newmat));
8344   PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8345 
8346 setproperties:
8347   PetscCall(ISEqualUnsorted(isrow,iscoltmp,&flg));
8348   if (flg) PetscCall(MatPropagateSymmetryOptions(mat,*newmat));
8349   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8350   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8351   PetscFunctionReturn(0);
8352 }
8353 
8354 /*@
8355    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8356 
8357    Not Collective
8358 
8359    Input Parameters:
8360 +  A - the matrix we wish to propagate options from
8361 -  B - the matrix we wish to propagate options to
8362 
8363    Level: beginner
8364 
8365    Notes: Propagates the options associated to MAT_SYMMETRY_ETERNAL, MAT_STRUCTURALLY_SYMMETRIC, MAT_HERMITIAN, MAT_SPD and MAT_SYMMETRIC
8366 
8367 .seealso: `MatSetOption()`
8368 @*/
8369 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8370 {
8371   PetscFunctionBegin;
8372   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8373   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
8374   if (A->symmetric_eternal) { /* symmetric_eternal does not have a corresponding *set flag */
8375     PetscCall(MatSetOption(B,MAT_SYMMETRY_ETERNAL,A->symmetric_eternal));
8376   }
8377   if (A->structurally_symmetric_set) PetscCall(MatSetOption(B,MAT_STRUCTURALLY_SYMMETRIC,A->structurally_symmetric));
8378   if (A->hermitian_set) PetscCall(MatSetOption(B,MAT_HERMITIAN,A->hermitian));
8379   if (A->spd_set) PetscCall(MatSetOption(B,MAT_SPD,A->spd));
8380   if (A->symmetric_set) PetscCall(MatSetOption(B,MAT_SYMMETRIC,A->symmetric));
8381   PetscFunctionReturn(0);
8382 }
8383 
8384 /*@
8385    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8386    used during the assembly process to store values that belong to
8387    other processors.
8388 
8389    Not Collective
8390 
8391    Input Parameters:
8392 +  mat   - the matrix
8393 .  size  - the initial size of the stash.
8394 -  bsize - the initial size of the block-stash(if used).
8395 
8396    Options Database Keys:
8397 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8398 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8399 
8400    Level: intermediate
8401 
8402    Notes:
8403      The block-stash is used for values set with MatSetValuesBlocked() while
8404      the stash is used for values set with MatSetValues()
8405 
8406      Run with the option -info and look for output of the form
8407      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8408      to determine the appropriate value, MM, to use for size and
8409      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8410      to determine the value, BMM to use for bsize
8411 
8412 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8413 
8414 @*/
8415 PetscErrorCode MatStashSetInitialSize(Mat mat,PetscInt size, PetscInt bsize)
8416 {
8417   PetscFunctionBegin;
8418   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8419   PetscValidType(mat,1);
8420   PetscCall(MatStashSetInitialSize_Private(&mat->stash,size));
8421   PetscCall(MatStashSetInitialSize_Private(&mat->bstash,bsize));
8422   PetscFunctionReturn(0);
8423 }
8424 
8425 /*@
8426    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8427      the matrix
8428 
8429    Neighbor-wise Collective on Mat
8430 
8431    Input Parameters:
8432 +  mat   - the matrix
8433 .  x,y - the vectors
8434 -  w - where the result is stored
8435 
8436    Level: intermediate
8437 
8438    Notes:
8439     w may be the same vector as y.
8440 
8441     This allows one to use either the restriction or interpolation (its transpose)
8442     matrix to do the interpolation
8443 
8444 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8445 
8446 @*/
8447 PetscErrorCode MatInterpolateAdd(Mat A,Vec x,Vec y,Vec w)
8448 {
8449   PetscInt       M,N,Ny;
8450 
8451   PetscFunctionBegin;
8452   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8453   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8454   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8455   PetscValidHeaderSpecific(w,VEC_CLASSID,4);
8456   PetscCall(MatGetSize(A,&M,&N));
8457   PetscCall(VecGetSize(y,&Ny));
8458   if (M == Ny) {
8459     PetscCall(MatMultAdd(A,x,y,w));
8460   } else {
8461     PetscCall(MatMultTransposeAdd(A,x,y,w));
8462   }
8463   PetscFunctionReturn(0);
8464 }
8465 
8466 /*@
8467    MatInterpolate - y = A*x or A'*x depending on the shape of
8468      the matrix
8469 
8470    Neighbor-wise Collective on Mat
8471 
8472    Input Parameters:
8473 +  mat   - the matrix
8474 -  x,y - the vectors
8475 
8476    Level: intermediate
8477 
8478    Notes:
8479     This allows one to use either the restriction or interpolation (its transpose)
8480     matrix to do the interpolation
8481 
8482 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8483 
8484 @*/
8485 PetscErrorCode MatInterpolate(Mat A,Vec x,Vec y)
8486 {
8487   PetscInt       M,N,Ny;
8488 
8489   PetscFunctionBegin;
8490   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8491   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8492   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8493   PetscCall(MatGetSize(A,&M,&N));
8494   PetscCall(VecGetSize(y,&Ny));
8495   if (M == Ny) {
8496     PetscCall(MatMult(A,x,y));
8497   } else {
8498     PetscCall(MatMultTranspose(A,x,y));
8499   }
8500   PetscFunctionReturn(0);
8501 }
8502 
8503 /*@
8504    MatRestrict - y = A*x or A'*x
8505 
8506    Neighbor-wise Collective on Mat
8507 
8508    Input Parameters:
8509 +  mat   - the matrix
8510 -  x,y - the vectors
8511 
8512    Level: intermediate
8513 
8514    Notes:
8515     This allows one to use either the restriction or interpolation (its transpose)
8516     matrix to do the restriction
8517 
8518 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`
8519 
8520 @*/
8521 PetscErrorCode MatRestrict(Mat A,Vec x,Vec y)
8522 {
8523   PetscInt       M,N,Ny;
8524 
8525   PetscFunctionBegin;
8526   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8527   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8528   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8529   PetscCall(MatGetSize(A,&M,&N));
8530   PetscCall(VecGetSize(y,&Ny));
8531   if (M == Ny) {
8532     PetscCall(MatMult(A,x,y));
8533   } else {
8534     PetscCall(MatMultTranspose(A,x,y));
8535   }
8536   PetscFunctionReturn(0);
8537 }
8538 
8539 /*@
8540    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8541 
8542    Neighbor-wise Collective on Mat
8543 
8544    Input Parameters:
8545 +  mat   - the matrix
8546 -  w, x - the input dense matrices
8547 
8548    Output Parameters:
8549 .  y - the output dense matrix
8550 
8551    Level: intermediate
8552 
8553    Notes:
8554     This allows one to use either the restriction or interpolation (its transpose)
8555     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8556     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8557 
8558 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`
8559 
8560 @*/
8561 PetscErrorCode MatMatInterpolateAdd(Mat A,Mat x,Mat w,Mat *y)
8562 {
8563   PetscInt       M,N,Mx,Nx,Mo,My = 0,Ny = 0;
8564   PetscBool      trans = PETSC_TRUE;
8565   MatReuse       reuse = MAT_INITIAL_MATRIX;
8566 
8567   PetscFunctionBegin;
8568   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8569   PetscValidHeaderSpecific(x,MAT_CLASSID,2);
8570   PetscValidType(x,2);
8571   if (w) PetscValidHeaderSpecific(w,MAT_CLASSID,3);
8572   if (*y) PetscValidHeaderSpecific(*y,MAT_CLASSID,4);
8573   PetscCall(MatGetSize(A,&M,&N));
8574   PetscCall(MatGetSize(x,&Mx,&Nx));
8575   if (N == Mx) trans = PETSC_FALSE;
8576   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);
8577   Mo = trans ? N : M;
8578   if (*y) {
8579     PetscCall(MatGetSize(*y,&My,&Ny));
8580     if (Mo == My && Nx == Ny) { reuse = MAT_REUSE_MATRIX; }
8581     else {
8582       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);
8583       PetscCall(MatDestroy(y));
8584     }
8585   }
8586 
8587   if (w && *y == w) { /* this is to minimize changes in PCMG */
8588     PetscBool flg;
8589 
8590     PetscCall(PetscObjectQuery((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject*)&w));
8591     if (w) {
8592       PetscInt My,Ny,Mw,Nw;
8593 
8594       PetscCall(PetscObjectTypeCompare((PetscObject)*y,((PetscObject)w)->type_name,&flg));
8595       PetscCall(MatGetSize(*y,&My,&Ny));
8596       PetscCall(MatGetSize(w,&Mw,&Nw));
8597       if (!flg || My != Mw || Ny != Nw) w = NULL;
8598     }
8599     if (!w) {
8600       PetscCall(MatDuplicate(*y,MAT_COPY_VALUES,&w));
8601       PetscCall(PetscObjectCompose((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject)w));
8602       PetscCall(PetscLogObjectParent((PetscObject)*y,(PetscObject)w));
8603       PetscCall(PetscObjectDereference((PetscObject)w));
8604     } else {
8605       PetscCall(MatCopy(*y,w,UNKNOWN_NONZERO_PATTERN));
8606     }
8607   }
8608   if (!trans) {
8609     PetscCall(MatMatMult(A,x,reuse,PETSC_DEFAULT,y));
8610   } else {
8611     PetscCall(MatTransposeMatMult(A,x,reuse,PETSC_DEFAULT,y));
8612   }
8613   if (w) PetscCall(MatAXPY(*y,1.0,w,UNKNOWN_NONZERO_PATTERN));
8614   PetscFunctionReturn(0);
8615 }
8616 
8617 /*@
8618    MatMatInterpolate - Y = A*X or A'*X
8619 
8620    Neighbor-wise Collective on Mat
8621 
8622    Input Parameters:
8623 +  mat   - the matrix
8624 -  x - the input dense matrix
8625 
8626    Output Parameters:
8627 .  y - the output dense matrix
8628 
8629    Level: intermediate
8630 
8631    Notes:
8632     This allows one to use either the restriction or interpolation (its transpose)
8633     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8634     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8635 
8636 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`
8637 
8638 @*/
8639 PetscErrorCode MatMatInterpolate(Mat A,Mat x,Mat *y)
8640 {
8641   PetscFunctionBegin;
8642   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8643   PetscFunctionReturn(0);
8644 }
8645 
8646 /*@
8647    MatMatRestrict - Y = A*X or A'*X
8648 
8649    Neighbor-wise Collective on Mat
8650 
8651    Input Parameters:
8652 +  mat   - the matrix
8653 -  x - the input dense matrix
8654 
8655    Output Parameters:
8656 .  y - the output dense matrix
8657 
8658    Level: intermediate
8659 
8660    Notes:
8661     This allows one to use either the restriction or interpolation (its transpose)
8662     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8663     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8664 
8665 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`
8666 @*/
8667 PetscErrorCode MatMatRestrict(Mat A,Mat x,Mat *y)
8668 {
8669   PetscFunctionBegin;
8670   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8671   PetscFunctionReturn(0);
8672 }
8673 
8674 /*@
8675    MatGetNullSpace - retrieves the null space of a matrix.
8676 
8677    Logically Collective on Mat
8678 
8679    Input Parameters:
8680 +  mat - the matrix
8681 -  nullsp - the null space object
8682 
8683    Level: developer
8684 
8685 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`
8686 @*/
8687 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8688 {
8689   PetscFunctionBegin;
8690   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8691   PetscValidPointer(nullsp,2);
8692   *nullsp = (mat->symmetric_set && mat->symmetric && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8693   PetscFunctionReturn(0);
8694 }
8695 
8696 /*@
8697    MatSetNullSpace - attaches a null space to a matrix.
8698 
8699    Logically Collective on Mat
8700 
8701    Input Parameters:
8702 +  mat - the matrix
8703 -  nullsp - the null space object
8704 
8705    Level: advanced
8706 
8707    Notes:
8708       This null space is used by the KSP linear solvers to solve singular systems.
8709 
8710       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
8711 
8712       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
8713       to zero but the linear system will still be solved in a least squares sense.
8714 
8715       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8716    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).
8717    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
8718    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
8719    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).
8720    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8721 
8722     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
8723     routine also automatically calls MatSetTransposeNullSpace().
8724 
8725     The user should call `MatNullSpaceDestroy()`.
8726 
8727 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8728           `KSPSetPCSide()`
8729 @*/
8730 PetscErrorCode MatSetNullSpace(Mat mat,MatNullSpace nullsp)
8731 {
8732   PetscFunctionBegin;
8733   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8734   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8735   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8736   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8737   mat->nullsp = nullsp;
8738   if (mat->symmetric_set && mat->symmetric) {
8739     PetscCall(MatSetTransposeNullSpace(mat,nullsp));
8740   }
8741   PetscFunctionReturn(0);
8742 }
8743 
8744 /*@
8745    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8746 
8747    Logically Collective on Mat
8748 
8749    Input Parameters:
8750 +  mat - the matrix
8751 -  nullsp - the null space object
8752 
8753    Level: developer
8754 
8755 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8756 @*/
8757 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8758 {
8759   PetscFunctionBegin;
8760   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8761   PetscValidType(mat,1);
8762   PetscValidPointer(nullsp,2);
8763   *nullsp = (mat->symmetric_set && mat->symmetric && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8764   PetscFunctionReturn(0);
8765 }
8766 
8767 /*@
8768    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8769 
8770    Logically Collective on Mat
8771 
8772    Input Parameters:
8773 +  mat - the matrix
8774 -  nullsp - the null space object
8775 
8776    Level: advanced
8777 
8778    Notes:
8779       This allows solving singular linear systems defined by the transpose of the matrix using KSP solvers with left preconditioning.
8780 
8781       See MatSetNullSpace()
8782 
8783 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8784 @*/
8785 PetscErrorCode MatSetTransposeNullSpace(Mat mat,MatNullSpace nullsp)
8786 {
8787   PetscFunctionBegin;
8788   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8789   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8790   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8791   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8792   mat->transnullsp = nullsp;
8793   PetscFunctionReturn(0);
8794 }
8795 
8796 /*@
8797    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8798         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this 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       Overwrites any previous near null space that may have been attached
8810 
8811       You can remove the null space by calling this routine with an nullsp of NULL
8812 
8813 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8814 @*/
8815 PetscErrorCode MatSetNearNullSpace(Mat mat,MatNullSpace nullsp)
8816 {
8817   PetscFunctionBegin;
8818   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8819   PetscValidType(mat,1);
8820   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8821   MatCheckPreallocated(mat,1);
8822   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8823   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8824   mat->nearnullsp = nullsp;
8825   PetscFunctionReturn(0);
8826 }
8827 
8828 /*@
8829    MatGetNearNullSpace - Get null space attached with MatSetNearNullSpace()
8830 
8831    Not Collective
8832 
8833    Input Parameter:
8834 .  mat - the matrix
8835 
8836    Output Parameter:
8837 .  nullsp - the null space object, NULL if not set
8838 
8839    Level: developer
8840 
8841 .seealso: `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8842 @*/
8843 PetscErrorCode MatGetNearNullSpace(Mat mat,MatNullSpace *nullsp)
8844 {
8845   PetscFunctionBegin;
8846   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8847   PetscValidType(mat,1);
8848   PetscValidPointer(nullsp,2);
8849   MatCheckPreallocated(mat,1);
8850   *nullsp = mat->nearnullsp;
8851   PetscFunctionReturn(0);
8852 }
8853 
8854 /*@C
8855    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8856 
8857    Collective on Mat
8858 
8859    Input Parameters:
8860 +  mat - the matrix
8861 .  row - row/column permutation
8862 .  fill - expected fill factor >= 1.0
8863 -  level - level of fill, for ICC(k)
8864 
8865    Notes:
8866    Probably really in-place only when level of fill is zero, otherwise allocates
8867    new space to store factored matrix and deletes previous memory.
8868 
8869    Most users should employ the simplified KSP interface for linear solvers
8870    instead of working directly with matrix algebra routines such as this.
8871    See, e.g., KSPCreate().
8872 
8873    Level: developer
8874 
8875 .seealso: `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8876 
8877     Developer Note: fortran interface is not autogenerated as the f90
8878     interface definition cannot be generated correctly [due to MatFactorInfo]
8879 
8880 @*/
8881 PetscErrorCode MatICCFactor(Mat mat,IS row,const MatFactorInfo *info)
8882 {
8883   PetscFunctionBegin;
8884   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8885   PetscValidType(mat,1);
8886   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
8887   PetscValidPointer(info,3);
8888   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
8889   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
8890   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8891   PetscCheck(mat->ops->iccfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8892   MatCheckPreallocated(mat,1);
8893   PetscCall((*mat->ops->iccfactor)(mat,row,info));
8894   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8895   PetscFunctionReturn(0);
8896 }
8897 
8898 /*@
8899    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8900          ghosted ones.
8901 
8902    Not Collective
8903 
8904    Input Parameters:
8905 +  mat - the matrix
8906 -  diag - the diagonal values, including ghost ones
8907 
8908    Level: developer
8909 
8910    Notes:
8911     Works only for MPIAIJ and MPIBAIJ matrices
8912 
8913 .seealso: `MatDiagonalScale()`
8914 @*/
8915 PetscErrorCode MatDiagonalScaleLocal(Mat mat,Vec diag)
8916 {
8917   PetscMPIInt    size;
8918 
8919   PetscFunctionBegin;
8920   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8921   PetscValidHeaderSpecific(diag,VEC_CLASSID,2);
8922   PetscValidType(mat,1);
8923 
8924   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be already assembled");
8925   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
8926   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8927   if (size == 1) {
8928     PetscInt n,m;
8929     PetscCall(VecGetSize(diag,&n));
8930     PetscCall(MatGetSize(mat,NULL,&m));
8931     if (m == n) {
8932       PetscCall(MatDiagonalScale(mat,NULL,diag));
8933     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only supported for sequential matrices when no ghost points/periodic conditions");
8934   } else {
8935     PetscUseMethod(mat,"MatDiagonalScaleLocal_C",(Mat,Vec),(mat,diag));
8936   }
8937   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
8938   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8939   PetscFunctionReturn(0);
8940 }
8941 
8942 /*@
8943    MatGetInertia - Gets the inertia from a factored matrix
8944 
8945    Collective on Mat
8946 
8947    Input Parameter:
8948 .  mat - the matrix
8949 
8950    Output Parameters:
8951 +   nneg - number of negative eigenvalues
8952 .   nzero - number of zero eigenvalues
8953 -   npos - number of positive eigenvalues
8954 
8955    Level: advanced
8956 
8957    Notes:
8958     Matrix must have been factored by MatCholeskyFactor()
8959 
8960 @*/
8961 PetscErrorCode MatGetInertia(Mat mat,PetscInt *nneg,PetscInt *nzero,PetscInt *npos)
8962 {
8963   PetscFunctionBegin;
8964   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8965   PetscValidType(mat,1);
8966   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
8967   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Numeric factor mat is not assembled");
8968   PetscCheck(mat->ops->getinertia,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8969   PetscCall((*mat->ops->getinertia)(mat,nneg,nzero,npos));
8970   PetscFunctionReturn(0);
8971 }
8972 
8973 /* ----------------------------------------------------------------*/
8974 /*@C
8975    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8976 
8977    Neighbor-wise Collective on Mats
8978 
8979    Input Parameters:
8980 +  mat - the factored matrix
8981 -  b - the right-hand-side vectors
8982 
8983    Output Parameter:
8984 .  x - the result vectors
8985 
8986    Notes:
8987    The vectors b and x cannot be the same.  I.e., one cannot
8988    call MatSolves(A,x,x).
8989 
8990    Notes:
8991    Most users should employ the simplified KSP interface for linear solvers
8992    instead of working directly with matrix algebra routines such as this.
8993    See, e.g., KSPCreate().
8994 
8995    Level: developer
8996 
8997 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8998 @*/
8999 PetscErrorCode MatSolves(Mat mat,Vecs b,Vecs x)
9000 {
9001   PetscFunctionBegin;
9002   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9003   PetscValidType(mat,1);
9004   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
9005   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
9006   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
9007 
9008   PetscCheck(mat->ops->solves,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
9009   MatCheckPreallocated(mat,1);
9010   PetscCall(PetscLogEventBegin(MAT_Solves,mat,0,0,0));
9011   PetscCall((*mat->ops->solves)(mat,b,x));
9012   PetscCall(PetscLogEventEnd(MAT_Solves,mat,0,0,0));
9013   PetscFunctionReturn(0);
9014 }
9015 
9016 /*@
9017    MatIsSymmetric - Test whether a matrix is symmetric
9018 
9019    Collective on Mat
9020 
9021    Input Parameters:
9022 +  A - the matrix to test
9023 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9024 
9025    Output Parameters:
9026 .  flg - the result
9027 
9028    Notes:
9029     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
9030 
9031    Level: intermediate
9032 
9033 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`
9034 @*/
9035 PetscErrorCode MatIsSymmetric(Mat A,PetscReal tol,PetscBool *flg)
9036 {
9037   PetscFunctionBegin;
9038   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9039   PetscValidBoolPointer(flg,3);
9040 
9041   if (!A->symmetric_set) {
9042     if (!A->ops->issymmetric) {
9043       MatType mattype;
9044       PetscCall(MatGetType(A,&mattype));
9045       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for symmetric",mattype);
9046     }
9047     PetscCall((*A->ops->issymmetric)(A,tol,flg));
9048     if (!tol) {
9049       PetscCall(MatSetOption(A,MAT_SYMMETRIC,*flg));
9050     }
9051   } else if (A->symmetric) {
9052     *flg = PETSC_TRUE;
9053   } else if (!tol) {
9054     *flg = PETSC_FALSE;
9055   } else {
9056     if (!A->ops->issymmetric) {
9057       MatType mattype;
9058       PetscCall(MatGetType(A,&mattype));
9059       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for symmetric",mattype);
9060     }
9061     PetscCall((*A->ops->issymmetric)(A,tol,flg));
9062   }
9063   PetscFunctionReturn(0);
9064 }
9065 
9066 /*@
9067    MatIsHermitian - Test whether a matrix is Hermitian
9068 
9069    Collective on Mat
9070 
9071    Input Parameters:
9072 +  A - the matrix to test
9073 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9074 
9075    Output Parameters:
9076 .  flg - the result
9077 
9078    Level: intermediate
9079 
9080 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9081           `MatIsSymmetricKnown()`, `MatIsSymmetric()`
9082 @*/
9083 PetscErrorCode MatIsHermitian(Mat A,PetscReal tol,PetscBool *flg)
9084 {
9085   PetscFunctionBegin;
9086   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9087   PetscValidBoolPointer(flg,3);
9088 
9089   if (!A->hermitian_set) {
9090     if (!A->ops->ishermitian) {
9091       MatType mattype;
9092       PetscCall(MatGetType(A,&mattype));
9093       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for hermitian",mattype);
9094     }
9095     PetscCall((*A->ops->ishermitian)(A,tol,flg));
9096     if (!tol) {
9097       PetscCall(MatSetOption(A,MAT_HERMITIAN,*flg));
9098     }
9099   } else if (A->hermitian) {
9100     *flg = PETSC_TRUE;
9101   } else if (!tol) {
9102     *flg = PETSC_FALSE;
9103   } else {
9104     if (!A->ops->ishermitian) {
9105       MatType mattype;
9106       PetscCall(MatGetType(A,&mattype));
9107       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for hermitian",mattype);
9108     }
9109     PetscCall((*A->ops->ishermitian)(A,tol,flg));
9110   }
9111   PetscFunctionReturn(0);
9112 }
9113 
9114 /*@
9115    MatIsSymmetricKnown - Checks the flag on the matrix to see if it is symmetric.
9116 
9117    Not Collective
9118 
9119    Input Parameter:
9120 .  A - the matrix to check
9121 
9122    Output Parameters:
9123 +  set - if the symmetric flag is set (this tells you if the next flag is valid)
9124 -  flg - the result
9125 
9126    Level: advanced
9127 
9128    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsSymmetric()
9129          if you want it explicitly checked
9130 
9131 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9132 @*/
9133 PetscErrorCode MatIsSymmetricKnown(Mat A,PetscBool *set,PetscBool *flg)
9134 {
9135   PetscFunctionBegin;
9136   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9137   PetscValidBoolPointer(set,2);
9138   PetscValidBoolPointer(flg,3);
9139   if (A->symmetric_set) {
9140     *set = PETSC_TRUE;
9141     *flg = A->symmetric;
9142   } else {
9143     *set = PETSC_FALSE;
9144   }
9145   PetscFunctionReturn(0);
9146 }
9147 
9148 /*@
9149    MatIsHermitianKnown - Checks the flag on the matrix to see if it is hermitian.
9150 
9151    Not Collective
9152 
9153    Input Parameter:
9154 .  A - the matrix to check
9155 
9156    Output Parameters:
9157 +  set - if the hermitian flag is set (this tells you if the next flag is valid)
9158 -  flg - the result
9159 
9160    Level: advanced
9161 
9162    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsHermitian()
9163          if you want it explicitly checked
9164 
9165 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9166 @*/
9167 PetscErrorCode MatIsHermitianKnown(Mat A,PetscBool *set,PetscBool *flg)
9168 {
9169   PetscFunctionBegin;
9170   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9171   PetscValidBoolPointer(set,2);
9172   PetscValidBoolPointer(flg,3);
9173   if (A->hermitian_set) {
9174     *set = PETSC_TRUE;
9175     *flg = A->hermitian;
9176   } else {
9177     *set = PETSC_FALSE;
9178   }
9179   PetscFunctionReturn(0);
9180 }
9181 
9182 /*@
9183    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9184 
9185    Collective on Mat
9186 
9187    Input Parameter:
9188 .  A - the matrix to test
9189 
9190    Output Parameters:
9191 .  flg - the result
9192 
9193    Level: intermediate
9194 
9195 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`
9196 @*/
9197 PetscErrorCode MatIsStructurallySymmetric(Mat A,PetscBool *flg)
9198 {
9199   PetscFunctionBegin;
9200   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9201   PetscValidBoolPointer(flg,2);
9202   if (!A->structurally_symmetric_set) {
9203     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);
9204     PetscCall((*A->ops->isstructurallysymmetric)(A,flg));
9205     PetscCall(MatSetOption(A,MAT_STRUCTURALLY_SYMMETRIC,*flg));
9206   } else *flg = A->structurally_symmetric;
9207   PetscFunctionReturn(0);
9208 }
9209 
9210 /*@
9211    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9212        to be communicated to other processors during the MatAssemblyBegin/End() process
9213 
9214     Not collective
9215 
9216    Input Parameter:
9217 .   vec - the vector
9218 
9219    Output Parameters:
9220 +   nstash   - the size of the stash
9221 .   reallocs - the number of additional mallocs incurred.
9222 .   bnstash   - the size of the block stash
9223 -   breallocs - the number of additional mallocs incurred.in the block stash
9224 
9225    Level: advanced
9226 
9227 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9228 
9229 @*/
9230 PetscErrorCode MatStashGetInfo(Mat mat,PetscInt *nstash,PetscInt *reallocs,PetscInt *bnstash,PetscInt *breallocs)
9231 {
9232   PetscFunctionBegin;
9233   PetscCall(MatStashGetInfo_Private(&mat->stash,nstash,reallocs));
9234   PetscCall(MatStashGetInfo_Private(&mat->bstash,bnstash,breallocs));
9235   PetscFunctionReturn(0);
9236 }
9237 
9238 /*@C
9239    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9240      parallel layout
9241 
9242    Collective on Mat
9243 
9244    Input Parameter:
9245 .  mat - the matrix
9246 
9247    Output Parameters:
9248 +   right - (optional) vector that the matrix can be multiplied against
9249 -   left - (optional) vector that the matrix vector product can be stored in
9250 
9251    Notes:
9252     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().
9253 
9254   Notes:
9255     These are new vectors which are not owned by the Mat, they should be destroyed in VecDestroy() when no longer needed
9256 
9257   Level: advanced
9258 
9259 .seealso: `MatCreate()`, `VecDestroy()`
9260 @*/
9261 PetscErrorCode MatCreateVecs(Mat mat,Vec *right,Vec *left)
9262 {
9263   PetscFunctionBegin;
9264   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9265   PetscValidType(mat,1);
9266   if (mat->ops->getvecs) {
9267     PetscCall((*mat->ops->getvecs)(mat,right,left));
9268   } else {
9269     PetscInt rbs,cbs;
9270     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
9271     if (right) {
9272       PetscCheck(mat->cmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for columns not yet setup");
9273       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),right));
9274       PetscCall(VecSetSizes(*right,mat->cmap->n,PETSC_DETERMINE));
9275       PetscCall(VecSetBlockSize(*right,cbs));
9276       PetscCall(VecSetType(*right,mat->defaultvectype));
9277 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9278       if (mat->boundtocpu && mat->bindingpropagates) {
9279         PetscCall(VecSetBindingPropagates(*right,PETSC_TRUE));
9280         PetscCall(VecBindToCPU(*right,PETSC_TRUE));
9281       }
9282 #endif
9283       PetscCall(PetscLayoutReference(mat->cmap,&(*right)->map));
9284     }
9285     if (left) {
9286       PetscCheck(mat->rmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for rows not yet setup");
9287       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),left));
9288       PetscCall(VecSetSizes(*left,mat->rmap->n,PETSC_DETERMINE));
9289       PetscCall(VecSetBlockSize(*left,rbs));
9290       PetscCall(VecSetType(*left,mat->defaultvectype));
9291 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9292       if (mat->boundtocpu && mat->bindingpropagates) {
9293         PetscCall(VecSetBindingPropagates(*left,PETSC_TRUE));
9294         PetscCall(VecBindToCPU(*left,PETSC_TRUE));
9295       }
9296 #endif
9297       PetscCall(PetscLayoutReference(mat->rmap,&(*left)->map));
9298     }
9299   }
9300   PetscFunctionReturn(0);
9301 }
9302 
9303 /*@C
9304    MatFactorInfoInitialize - Initializes a MatFactorInfo data structure
9305      with default values.
9306 
9307    Not Collective
9308 
9309    Input Parameters:
9310 .    info - the MatFactorInfo data structure
9311 
9312    Notes:
9313     The solvers are generally used through the KSP and PC objects, for example
9314           PCLU, PCILU, PCCHOLESKY, PCICC
9315 
9316    Level: developer
9317 
9318 .seealso: `MatFactorInfo`
9319 
9320     Developer Note: fortran interface is not autogenerated as the f90
9321     interface definition cannot be generated correctly [due to MatFactorInfo]
9322 
9323 @*/
9324 
9325 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9326 {
9327   PetscFunctionBegin;
9328   PetscCall(PetscMemzero(info,sizeof(MatFactorInfo)));
9329   PetscFunctionReturn(0);
9330 }
9331 
9332 /*@
9333    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9334 
9335    Collective on Mat
9336 
9337    Input Parameters:
9338 +  mat - the factored matrix
9339 -  is - the index set defining the Schur indices (0-based)
9340 
9341    Notes:
9342     Call MatFactorSolveSchurComplement() or MatFactorSolveSchurComplementTranspose() after this call to solve a Schur complement system.
9343 
9344    You can call MatFactorGetSchurComplement() or MatFactorCreateSchurComplement() after this call.
9345 
9346    Level: developer
9347 
9348 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9349           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`
9350 
9351 @*/
9352 PetscErrorCode MatFactorSetSchurIS(Mat mat,IS is)
9353 {
9354   PetscErrorCode (*f)(Mat,IS);
9355 
9356   PetscFunctionBegin;
9357   PetscValidType(mat,1);
9358   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9359   PetscValidType(is,2);
9360   PetscValidHeaderSpecific(is,IS_CLASSID,2);
9361   PetscCheckSameComm(mat,1,is,2);
9362   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
9363   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorSetSchurIS_C",&f));
9364   PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9365   PetscCall(MatDestroy(&mat->schur));
9366   PetscCall((*f)(mat,is));
9367   PetscCheck(mat->schur,PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Schur complement has not been created");
9368   PetscFunctionReturn(0);
9369 }
9370 
9371 /*@
9372   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9373 
9374    Logically Collective on Mat
9375 
9376    Input Parameters:
9377 +  F - the factored matrix obtained by calling MatGetFactor() from PETSc-MUMPS interface
9378 .  S - location where to return the Schur complement, can be NULL
9379 -  status - the status of the Schur complement matrix, can be NULL
9380 
9381    Notes:
9382    You must call MatFactorSetSchurIS() before calling this routine.
9383 
9384    The routine provides a copy of the Schur matrix stored within the solver data structures.
9385    The caller must destroy the object when it is no longer needed.
9386    If MatFactorInvertSchurComplement() has been called, the routine gets back the inverse.
9387 
9388    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)
9389 
9390    Developer Notes:
9391     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9392    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9393 
9394    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9395 
9396    Level: advanced
9397 
9398    References:
9399 
9400 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`
9401 @*/
9402 PetscErrorCode MatFactorCreateSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9403 {
9404   PetscFunctionBegin;
9405   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9406   if (S) PetscValidPointer(S,2);
9407   if (status) PetscValidPointer(status,3);
9408   if (S) {
9409     PetscErrorCode (*f)(Mat,Mat*);
9410 
9411     PetscCall(PetscObjectQueryFunction((PetscObject)F,"MatFactorCreateSchurComplement_C",&f));
9412     if (f) {
9413       PetscCall((*f)(F,S));
9414     } else {
9415       PetscCall(MatDuplicate(F->schur,MAT_COPY_VALUES,S));
9416     }
9417   }
9418   if (status) *status = F->schur_status;
9419   PetscFunctionReturn(0);
9420 }
9421 
9422 /*@
9423   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9424 
9425    Logically Collective on Mat
9426 
9427    Input Parameters:
9428 +  F - the factored matrix obtained by calling MatGetFactor()
9429 .  *S - location where to return the Schur complement, can be NULL
9430 -  status - the status of the Schur complement matrix, can be NULL
9431 
9432    Notes:
9433    You must call MatFactorSetSchurIS() before calling this routine.
9434 
9435    Schur complement mode is currently implemented for sequential matrices.
9436    The routine returns a the Schur Complement stored within the data strutures of the solver.
9437    If MatFactorInvertSchurComplement() has previously been called, the returned matrix is actually the inverse of the Schur complement.
9438    The returned matrix should not be destroyed; the caller should call MatFactorRestoreSchurComplement() when the object is no longer needed.
9439 
9440    Use MatFactorCreateSchurComplement() to create a copy of the Schur complement matrix that is within a factored matrix
9441 
9442    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9443 
9444    Level: advanced
9445 
9446    References:
9447 
9448 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9449 @*/
9450 PetscErrorCode MatFactorGetSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9451 {
9452   PetscFunctionBegin;
9453   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9454   if (S) PetscValidPointer(S,2);
9455   if (status) PetscValidPointer(status,3);
9456   if (S) *S = F->schur;
9457   if (status) *status = F->schur_status;
9458   PetscFunctionReturn(0);
9459 }
9460 
9461 /*@
9462   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to MatFactorGetSchurComplement
9463 
9464    Logically Collective on Mat
9465 
9466    Input Parameters:
9467 +  F - the factored matrix obtained by calling MatGetFactor()
9468 .  *S - location where the Schur complement is stored
9469 -  status - the status of the Schur complement matrix (see MatFactorSchurStatus)
9470 
9471    Notes:
9472 
9473    Level: advanced
9474 
9475    References:
9476 
9477 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9478 @*/
9479 PetscErrorCode MatFactorRestoreSchurComplement(Mat F,Mat* S,MatFactorSchurStatus status)
9480 {
9481   PetscFunctionBegin;
9482   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9483   if (S) {
9484     PetscValidHeaderSpecific(*S,MAT_CLASSID,2);
9485     *S = NULL;
9486   }
9487   F->schur_status = status;
9488   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9489   PetscFunctionReturn(0);
9490 }
9491 
9492 /*@
9493   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9494 
9495    Logically Collective on Mat
9496 
9497    Input Parameters:
9498 +  F - the factored matrix obtained by calling MatGetFactor()
9499 .  rhs - location where the right hand side of the Schur complement system is stored
9500 -  sol - location where the solution of the Schur complement system has to be returned
9501 
9502    Notes:
9503    The sizes of the vectors should match the size of the Schur complement
9504 
9505    Must be called after MatFactorSetSchurIS()
9506 
9507    Level: advanced
9508 
9509    References:
9510 
9511 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9512 @*/
9513 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9514 {
9515   PetscFunctionBegin;
9516   PetscValidType(F,1);
9517   PetscValidType(rhs,2);
9518   PetscValidType(sol,3);
9519   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9520   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9521   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9522   PetscCheckSameComm(F,1,rhs,2);
9523   PetscCheckSameComm(F,1,sol,3);
9524   PetscCall(MatFactorFactorizeSchurComplement(F));
9525   switch (F->schur_status) {
9526   case MAT_FACTOR_SCHUR_FACTORED:
9527     PetscCall(MatSolveTranspose(F->schur,rhs,sol));
9528     break;
9529   case MAT_FACTOR_SCHUR_INVERTED:
9530     PetscCall(MatMultTranspose(F->schur,rhs,sol));
9531     break;
9532   default:
9533     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9534   }
9535   PetscFunctionReturn(0);
9536 }
9537 
9538 /*@
9539   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9540 
9541    Logically Collective on Mat
9542 
9543    Input Parameters:
9544 +  F - the factored matrix obtained by calling MatGetFactor()
9545 .  rhs - location where the right hand side of the Schur complement system is stored
9546 -  sol - location where the solution of the Schur complement system has to be returned
9547 
9548    Notes:
9549    The sizes of the vectors should match the size of the Schur complement
9550 
9551    Must be called after MatFactorSetSchurIS()
9552 
9553    Level: advanced
9554 
9555    References:
9556 
9557 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9558 @*/
9559 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9560 {
9561   PetscFunctionBegin;
9562   PetscValidType(F,1);
9563   PetscValidType(rhs,2);
9564   PetscValidType(sol,3);
9565   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9566   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9567   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9568   PetscCheckSameComm(F,1,rhs,2);
9569   PetscCheckSameComm(F,1,sol,3);
9570   PetscCall(MatFactorFactorizeSchurComplement(F));
9571   switch (F->schur_status) {
9572   case MAT_FACTOR_SCHUR_FACTORED:
9573     PetscCall(MatSolve(F->schur,rhs,sol));
9574     break;
9575   case MAT_FACTOR_SCHUR_INVERTED:
9576     PetscCall(MatMult(F->schur,rhs,sol));
9577     break;
9578   default:
9579     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9580   }
9581   PetscFunctionReturn(0);
9582 }
9583 
9584 /*@
9585   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9586 
9587    Logically Collective on Mat
9588 
9589    Input Parameters:
9590 .  F - the factored matrix obtained by calling MatGetFactor()
9591 
9592    Notes:
9593     Must be called after MatFactorSetSchurIS().
9594 
9595    Call MatFactorGetSchurComplement() or  MatFactorCreateSchurComplement() AFTER this call to actually compute the inverse and get access to it.
9596 
9597    Level: advanced
9598 
9599    References:
9600 
9601 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9602 @*/
9603 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9604 {
9605   PetscFunctionBegin;
9606   PetscValidType(F,1);
9607   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9608   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9609   PetscCall(MatFactorFactorizeSchurComplement(F));
9610   PetscCall(MatFactorInvertSchurComplement_Private(F));
9611   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9612   PetscFunctionReturn(0);
9613 }
9614 
9615 /*@
9616   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9617 
9618    Logically Collective on Mat
9619 
9620    Input Parameters:
9621 .  F - the factored matrix obtained by calling MatGetFactor()
9622 
9623    Notes:
9624     Must be called after MatFactorSetSchurIS().
9625 
9626    Level: advanced
9627 
9628    References:
9629 
9630 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9631 @*/
9632 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9633 {
9634   PetscFunctionBegin;
9635   PetscValidType(F,1);
9636   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9637   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9638   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9639   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9640   PetscFunctionReturn(0);
9641 }
9642 
9643 /*@
9644    MatPtAP - Creates the matrix product C = P^T * A * P
9645 
9646    Neighbor-wise Collective on Mat
9647 
9648    Input Parameters:
9649 +  A - the matrix
9650 .  P - the projection matrix
9651 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9652 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use PETSC_DEFAULT if you do not have a good estimate
9653           if the result is a dense matrix this is irrelevant
9654 
9655    Output Parameters:
9656 .  C - the product matrix
9657 
9658    Notes:
9659    C will be created and must be destroyed by the user with MatDestroy().
9660 
9661    For matrix types without special implementation the function fallbacks to MatMatMult() followed by MatTransposeMatMult().
9662 
9663    Level: intermediate
9664 
9665 .seealso: `MatMatMult()`, `MatRARt()`
9666 @*/
9667 PetscErrorCode MatPtAP(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
9668 {
9669   PetscFunctionBegin;
9670   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9671   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9672 
9673   if (scall == MAT_INITIAL_MATRIX) {
9674     PetscCall(MatProductCreate(A,P,NULL,C));
9675     PetscCall(MatProductSetType(*C,MATPRODUCT_PtAP));
9676     PetscCall(MatProductSetAlgorithm(*C,"default"));
9677     PetscCall(MatProductSetFill(*C,fill));
9678 
9679     (*C)->product->api_user = PETSC_TRUE;
9680     PetscCall(MatProductSetFromOptions(*C));
9681     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);
9682     PetscCall(MatProductSymbolic(*C));
9683   } else { /* scall == MAT_REUSE_MATRIX */
9684     PetscCall(MatProductReplaceMats(A,P,NULL,*C));
9685   }
9686 
9687   PetscCall(MatProductNumeric(*C));
9688   if (A->symmetric) {
9689     if (A->spd) {
9690       PetscCall(MatSetOption(*C,MAT_SPD,PETSC_TRUE));
9691     } else {
9692       PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9693     }
9694   }
9695   PetscFunctionReturn(0);
9696 }
9697 
9698 /*@
9699    MatRARt - Creates the matrix product C = R * A * R^T
9700 
9701    Neighbor-wise Collective on Mat
9702 
9703    Input Parameters:
9704 +  A - the matrix
9705 .  R - the projection matrix
9706 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9707 -  fill - expected fill as ratio of nnz(C)/nnz(A), use PETSC_DEFAULT if you do not have a good estimate
9708           if the result is a dense matrix this is irrelevant
9709 
9710    Output Parameters:
9711 .  C - the product matrix
9712 
9713    Notes:
9714    C will be created and must be destroyed by the user with MatDestroy().
9715 
9716    This routine is currently only implemented for pairs of AIJ matrices and classes
9717    which inherit from AIJ. Due to PETSc sparse matrix block row distribution among processes,
9718    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9719    We recommend using MatPtAP().
9720 
9721    Level: intermediate
9722 
9723 .seealso: `MatMatMult()`, `MatPtAP()`
9724 @*/
9725 PetscErrorCode MatRARt(Mat A,Mat R,MatReuse scall,PetscReal fill,Mat *C)
9726 {
9727   PetscFunctionBegin;
9728   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9729   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9730 
9731   if (scall == MAT_INITIAL_MATRIX) {
9732     PetscCall(MatProductCreate(A,R,NULL,C));
9733     PetscCall(MatProductSetType(*C,MATPRODUCT_RARt));
9734     PetscCall(MatProductSetAlgorithm(*C,"default"));
9735     PetscCall(MatProductSetFill(*C,fill));
9736 
9737     (*C)->product->api_user = PETSC_TRUE;
9738     PetscCall(MatProductSetFromOptions(*C));
9739     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);
9740     PetscCall(MatProductSymbolic(*C));
9741   } else { /* scall == MAT_REUSE_MATRIX */
9742     PetscCall(MatProductReplaceMats(A,R,NULL,*C));
9743   }
9744 
9745   PetscCall(MatProductNumeric(*C));
9746   if (A->symmetric_set && A->symmetric) {
9747     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9748   }
9749   PetscFunctionReturn(0);
9750 }
9751 
9752 static PetscErrorCode MatProduct_Private(Mat A,Mat B,MatReuse scall,PetscReal fill,MatProductType ptype, Mat *C)
9753 {
9754   PetscFunctionBegin;
9755   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9756 
9757   if (scall == MAT_INITIAL_MATRIX) {
9758     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n",MatProductTypes[ptype]));
9759     PetscCall(MatProductCreate(A,B,NULL,C));
9760     PetscCall(MatProductSetType(*C,ptype));
9761     PetscCall(MatProductSetAlgorithm(*C,MATPRODUCTALGORITHMDEFAULT));
9762     PetscCall(MatProductSetFill(*C,fill));
9763 
9764     (*C)->product->api_user = PETSC_TRUE;
9765     PetscCall(MatProductSetFromOptions(*C));
9766     PetscCall(MatProductSymbolic(*C));
9767   } else { /* scall == MAT_REUSE_MATRIX */
9768     Mat_Product *product = (*C)->product;
9769     PetscBool isdense;
9770 
9771     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C),&isdense,MATSEQDENSE,MATMPIDENSE,""));
9772     if (isdense && product && product->type != ptype) {
9773       PetscCall(MatProductClear(*C));
9774       product = NULL;
9775     }
9776     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n",product ? "with" : "without",MatProductTypes[ptype]));
9777     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9778       if (isdense) {
9779         PetscCall(MatProductCreate_Private(A,B,NULL,*C));
9780         product = (*C)->product;
9781         product->fill     = fill;
9782         product->api_user = PETSC_TRUE;
9783         product->clear    = PETSC_TRUE;
9784 
9785         PetscCall(MatProductSetType(*C,ptype));
9786         PetscCall(MatProductSetFromOptions(*C));
9787         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);
9788         PetscCall(MatProductSymbolic(*C));
9789       } else SETERRQ(PetscObjectComm((PetscObject)(*C)),PETSC_ERR_SUP,"Call MatProductCreate() first");
9790     } else { /* user may change input matrices A or B when REUSE */
9791       PetscCall(MatProductReplaceMats(A,B,NULL,*C));
9792     }
9793   }
9794   PetscCall(MatProductNumeric(*C));
9795   PetscFunctionReturn(0);
9796 }
9797 
9798 /*@
9799    MatMatMult - Performs Matrix-Matrix Multiplication C=A*B.
9800 
9801    Neighbor-wise Collective on Mat
9802 
9803    Input Parameters:
9804 +  A - the left matrix
9805 .  B - the right matrix
9806 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9807 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if you do not have a good estimate
9808           if the result is a dense matrix this is irrelevant
9809 
9810    Output Parameters:
9811 .  C - the product matrix
9812 
9813    Notes:
9814    Unless scall is MAT_REUSE_MATRIX C will be created.
9815 
9816    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
9817    call to this function with MAT_INITIAL_MATRIX.
9818 
9819    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9820 
9821    If you have many matrices with the same non-zero structure to multiply, you should use MatProductCreate()/MatProductSymbolic()/MatProductReplaceMats(), and call MatProductNumeric() repeatedly.
9822 
9823    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.
9824 
9825    Example of Usage:
9826 .vb
9827      MatProductCreate(A,B,NULL,&C);
9828      MatProductSetType(C,MATPRODUCT_AB);
9829      MatProductSymbolic(C);
9830      MatProductNumeric(C); // compute C=A * B
9831      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9832      MatProductNumeric(C);
9833      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9834      MatProductNumeric(C);
9835 .ve
9836 
9837    Level: intermediate
9838 
9839 .seealso: `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9840 @*/
9841 PetscErrorCode MatMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9842 {
9843   PetscFunctionBegin;
9844   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AB,C));
9845   PetscFunctionReturn(0);
9846 }
9847 
9848 /*@
9849    MatMatTransposeMult - Performs Matrix-Matrix Multiplication C=A*B^T.
9850 
9851    Neighbor-wise Collective on Mat
9852 
9853    Input Parameters:
9854 +  A - the left matrix
9855 .  B - the right matrix
9856 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9857 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9858 
9859    Output Parameters:
9860 .  C - the product matrix
9861 
9862    Notes:
9863    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9864 
9865    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9866 
9867   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9868    actually needed.
9869 
9870    This routine is currently only implemented for pairs of SeqAIJ matrices, for the SeqDense class,
9871    and for pairs of MPIDense matrices.
9872 
9873    Options Database Keys:
9874 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for MPIDense matrices: the
9875               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9876               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9877 
9878    Level: intermediate
9879 
9880 .seealso: `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`
9881 @*/
9882 PetscErrorCode MatMatTransposeMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9883 {
9884   PetscFunctionBegin;
9885   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_ABt,C));
9886   if (A == B) {
9887     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9888   }
9889   PetscFunctionReturn(0);
9890 }
9891 
9892 /*@
9893    MatTransposeMatMult - Performs Matrix-Matrix Multiplication C=A^T*B.
9894 
9895    Neighbor-wise Collective on Mat
9896 
9897    Input Parameters:
9898 +  A - the left matrix
9899 .  B - the right matrix
9900 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9901 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9902 
9903    Output Parameters:
9904 .  C - the product matrix
9905 
9906    Notes:
9907    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9908 
9909    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9910 
9911   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9912    actually needed.
9913 
9914    This routine is currently implemented for pairs of AIJ matrices and pairs of SeqDense matrices and classes
9915    which inherit from SeqAIJ.  C will be of the same type as the input matrices.
9916 
9917    Level: intermediate
9918 
9919 .seealso: `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9920 @*/
9921 PetscErrorCode MatTransposeMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9922 {
9923   PetscFunctionBegin;
9924   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AtB,C));
9925   PetscFunctionReturn(0);
9926 }
9927 
9928 /*@
9929    MatMatMatMult - Performs Matrix-Matrix-Matrix Multiplication D=A*B*C.
9930 
9931    Neighbor-wise Collective on Mat
9932 
9933    Input Parameters:
9934 +  A - the left matrix
9935 .  B - the middle matrix
9936 .  C - the right matrix
9937 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9938 -  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
9939           if the result is a dense matrix this is irrelevant
9940 
9941    Output Parameters:
9942 .  D - the product matrix
9943 
9944    Notes:
9945    Unless scall is MAT_REUSE_MATRIX D will be created.
9946 
9947    MAT_REUSE_MATRIX can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9948 
9949    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9950    actually needed.
9951 
9952    If you have many matrices with the same non-zero structure to multiply, you
9953    should use MAT_REUSE_MATRIX in all calls but the first
9954 
9955    Level: intermediate
9956 
9957 .seealso: `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9958 @*/
9959 PetscErrorCode MatMatMatMult(Mat A,Mat B,Mat C,MatReuse scall,PetscReal fill,Mat *D)
9960 {
9961   PetscFunctionBegin;
9962   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D,6);
9963   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9964 
9965   if (scall == MAT_INITIAL_MATRIX) {
9966     PetscCall(MatProductCreate(A,B,C,D));
9967     PetscCall(MatProductSetType(*D,MATPRODUCT_ABC));
9968     PetscCall(MatProductSetAlgorithm(*D,"default"));
9969     PetscCall(MatProductSetFill(*D,fill));
9970 
9971     (*D)->product->api_user = PETSC_TRUE;
9972     PetscCall(MatProductSetFromOptions(*D));
9973     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);
9974     PetscCall(MatProductSymbolic(*D));
9975   } else { /* user may change input matrices when REUSE */
9976     PetscCall(MatProductReplaceMats(A,B,C,*D));
9977   }
9978   PetscCall(MatProductNumeric(*D));
9979   PetscFunctionReturn(0);
9980 }
9981 
9982 /*@
9983    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9984 
9985    Collective on Mat
9986 
9987    Input Parameters:
9988 +  mat - the matrix
9989 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9990 .  subcomm - MPI communicator split from the communicator where mat resides in (or MPI_COMM_NULL if nsubcomm is used)
9991 -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9992 
9993    Output Parameter:
9994 .  matredundant - redundant matrix
9995 
9996    Notes:
9997    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
9998    original matrix has not changed from that last call to MatCreateRedundantMatrix().
9999 
10000    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10001    calling it.
10002 
10003    Level: advanced
10004 
10005 .seealso: `MatDestroy()`
10006 @*/
10007 PetscErrorCode MatCreateRedundantMatrix(Mat mat,PetscInt nsubcomm,MPI_Comm subcomm,MatReuse reuse,Mat *matredundant)
10008 {
10009   MPI_Comm       comm;
10010   PetscMPIInt    size;
10011   PetscInt       mloc_sub,nloc_sub,rstart,rend,M=mat->rmap->N,N=mat->cmap->N,bs=mat->rmap->bs;
10012   Mat_Redundant  *redund=NULL;
10013   PetscSubcomm   psubcomm=NULL;
10014   MPI_Comm       subcomm_in=subcomm;
10015   Mat            *matseq;
10016   IS             isrow,iscol;
10017   PetscBool      newsubcomm=PETSC_FALSE;
10018 
10019   PetscFunctionBegin;
10020   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10021   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10022     PetscValidPointer(*matredundant,5);
10023     PetscValidHeaderSpecific(*matredundant,MAT_CLASSID,5);
10024   }
10025 
10026   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10027   if (size == 1 || nsubcomm == 1) {
10028     if (reuse == MAT_INITIAL_MATRIX) {
10029       PetscCall(MatDuplicate(mat,MAT_COPY_VALUES,matredundant));
10030     } else {
10031       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");
10032       PetscCall(MatCopy(mat,*matredundant,SAME_NONZERO_PATTERN));
10033     }
10034     PetscFunctionReturn(0);
10035   }
10036 
10037   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10038   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10039   MatCheckPreallocated(mat,1);
10040 
10041   PetscCall(PetscLogEventBegin(MAT_RedundantMat,mat,0,0,0));
10042   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10043     /* create psubcomm, then get subcomm */
10044     PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10045     PetscCallMPI(MPI_Comm_size(comm,&size));
10046     PetscCheck(nsubcomm >= 1 && nsubcomm <= size,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"nsubcomm must between 1 and %d",size);
10047 
10048     PetscCall(PetscSubcommCreate(comm,&psubcomm));
10049     PetscCall(PetscSubcommSetNumber(psubcomm,nsubcomm));
10050     PetscCall(PetscSubcommSetType(psubcomm,PETSC_SUBCOMM_CONTIGUOUS));
10051     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10052     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm),&subcomm,NULL));
10053     newsubcomm = PETSC_TRUE;
10054     PetscCall(PetscSubcommDestroy(&psubcomm));
10055   }
10056 
10057   /* get isrow, iscol and a local sequential matrix matseq[0] */
10058   if (reuse == MAT_INITIAL_MATRIX) {
10059     mloc_sub = PETSC_DECIDE;
10060     nloc_sub = PETSC_DECIDE;
10061     if (bs < 1) {
10062       PetscCall(PetscSplitOwnership(subcomm,&mloc_sub,&M));
10063       PetscCall(PetscSplitOwnership(subcomm,&nloc_sub,&N));
10064     } else {
10065       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&mloc_sub,&M));
10066       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&nloc_sub,&N));
10067     }
10068     PetscCallMPI(MPI_Scan(&mloc_sub,&rend,1,MPIU_INT,MPI_SUM,subcomm));
10069     rstart = rend - mloc_sub;
10070     PetscCall(ISCreateStride(PETSC_COMM_SELF,mloc_sub,rstart,1,&isrow));
10071     PetscCall(ISCreateStride(PETSC_COMM_SELF,N,0,1,&iscol));
10072   } else { /* reuse == MAT_REUSE_MATRIX */
10073     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");
10074     /* retrieve subcomm */
10075     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant),&subcomm));
10076     redund = (*matredundant)->redundant;
10077     isrow  = redund->isrow;
10078     iscol  = redund->iscol;
10079     matseq = redund->matseq;
10080   }
10081   PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscol,reuse,&matseq));
10082 
10083   /* get matredundant over subcomm */
10084   if (reuse == MAT_INITIAL_MATRIX) {
10085     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],nloc_sub,reuse,matredundant));
10086 
10087     /* create a supporting struct and attach it to C for reuse */
10088     PetscCall(PetscNewLog(*matredundant,&redund));
10089     (*matredundant)->redundant = redund;
10090     redund->isrow              = isrow;
10091     redund->iscol              = iscol;
10092     redund->matseq             = matseq;
10093     if (newsubcomm) {
10094       redund->subcomm          = subcomm;
10095     } else {
10096       redund->subcomm          = MPI_COMM_NULL;
10097     }
10098   } else {
10099     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],PETSC_DECIDE,reuse,matredundant));
10100   }
10101 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
10102   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10103     PetscCall(MatBindToCPU(*matredundant,PETSC_TRUE));
10104     PetscCall(MatSetBindingPropagates(*matredundant,PETSC_TRUE));
10105   }
10106 #endif
10107   PetscCall(PetscLogEventEnd(MAT_RedundantMat,mat,0,0,0));
10108   PetscFunctionReturn(0);
10109 }
10110 
10111 /*@C
10112    MatGetMultiProcBlock - Create multiple [bjacobi] 'parallel submatrices' from
10113    a given 'mat' object. Each submatrix can span multiple procs.
10114 
10115    Collective on Mat
10116 
10117    Input Parameters:
10118 +  mat - the matrix
10119 .  subcomm - the subcommunicator obtained by com_split(comm)
10120 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10121 
10122    Output Parameter:
10123 .  subMat - 'parallel submatrices each spans a given subcomm
10124 
10125   Notes:
10126   The submatrix partition across processors is dictated by 'subComm' a
10127   communicator obtained by MPI_comm_split(). The subComm
10128   is not restriced to be grouped with consecutive original ranks.
10129 
10130   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10131   map directly to the layout of the original matrix [wrt the local
10132   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10133   into the 'DiagonalMat' of the subMat, hence it is used directly from
10134   the subMat. However the offDiagMat looses some columns - and this is
10135   reconstructed with MatSetValues()
10136 
10137   Level: advanced
10138 
10139 .seealso: `MatCreateSubMatrices()`
10140 @*/
10141 PetscErrorCode   MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall,Mat *subMat)
10142 {
10143   PetscMPIInt    commsize,subCommSize;
10144 
10145   PetscFunctionBegin;
10146   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&commsize));
10147   PetscCallMPI(MPI_Comm_size(subComm,&subCommSize));
10148   PetscCheck(subCommSize <= commsize,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"CommSize %d < SubCommZize %d",commsize,subCommSize);
10149 
10150   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");
10151   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock,mat,0,0,0));
10152   PetscCall((*mat->ops->getmultiprocblock)(mat,subComm,scall,subMat));
10153   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock,mat,0,0,0));
10154   PetscFunctionReturn(0);
10155 }
10156 
10157 /*@
10158    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10159 
10160    Not Collective
10161 
10162    Input Parameters:
10163 +  mat - matrix to extract local submatrix from
10164 .  isrow - local row indices for submatrix
10165 -  iscol - local column indices for submatrix
10166 
10167    Output Parameter:
10168 .  submat - the submatrix
10169 
10170    Level: intermediate
10171 
10172    Notes:
10173    The submat should be returned with MatRestoreLocalSubMatrix().
10174 
10175    Depending on the format of mat, the returned submat may not implement MatMult().  Its communicator may be
10176    the same as mat, it may be PETSC_COMM_SELF, or some other subcomm of mat's.
10177 
10178    The submat always implements MatSetValuesLocal().  If isrow and iscol have the same block size, then
10179    MatSetValuesBlockedLocal() will also be implemented.
10180 
10181    The mat must have had a ISLocalToGlobalMapping provided to it with MatSetLocalToGlobalMapping(). Note that
10182    matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10183 
10184 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10185 @*/
10186 PetscErrorCode MatGetLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10187 {
10188   PetscFunctionBegin;
10189   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10190   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10191   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10192   PetscCheckSameComm(isrow,2,iscol,3);
10193   PetscValidPointer(submat,4);
10194   PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must have local to global mapping provided before this call");
10195 
10196   if (mat->ops->getlocalsubmatrix) {
10197     PetscCall((*mat->ops->getlocalsubmatrix)(mat,isrow,iscol,submat));
10198   } else {
10199     PetscCall(MatCreateLocalRef(mat,isrow,iscol,submat));
10200   }
10201   PetscFunctionReturn(0);
10202 }
10203 
10204 /*@
10205    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering
10206 
10207    Not Collective
10208 
10209    Input Parameters:
10210 +  mat - matrix to extract local submatrix from
10211 .  isrow - local row indices for submatrix
10212 .  iscol - local column indices for submatrix
10213 -  submat - the submatrix
10214 
10215    Level: intermediate
10216 
10217 .seealso: `MatGetLocalSubMatrix()`
10218 @*/
10219 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10220 {
10221   PetscFunctionBegin;
10222   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10223   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10224   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10225   PetscCheckSameComm(isrow,2,iscol,3);
10226   PetscValidPointer(submat,4);
10227   if (*submat) {
10228     PetscValidHeaderSpecific(*submat,MAT_CLASSID,4);
10229   }
10230 
10231   if (mat->ops->restorelocalsubmatrix) {
10232     PetscCall((*mat->ops->restorelocalsubmatrix)(mat,isrow,iscol,submat));
10233   } else {
10234     PetscCall(MatDestroy(submat));
10235   }
10236   *submat = NULL;
10237   PetscFunctionReturn(0);
10238 }
10239 
10240 /* --------------------------------------------------------*/
10241 /*@
10242    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10243 
10244    Collective on Mat
10245 
10246    Input Parameter:
10247 .  mat - the matrix
10248 
10249    Output Parameter:
10250 .  is - if any rows have zero diagonals this contains the list of them
10251 
10252    Level: developer
10253 
10254 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10255 @*/
10256 PetscErrorCode MatFindZeroDiagonals(Mat mat,IS *is)
10257 {
10258   PetscFunctionBegin;
10259   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10260   PetscValidType(mat,1);
10261   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10262   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10263 
10264   if (!mat->ops->findzerodiagonals) {
10265     Vec                diag;
10266     const PetscScalar *a;
10267     PetscInt          *rows;
10268     PetscInt           rStart, rEnd, r, nrow = 0;
10269 
10270     PetscCall(MatCreateVecs(mat, &diag, NULL));
10271     PetscCall(MatGetDiagonal(mat, diag));
10272     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10273     PetscCall(VecGetArrayRead(diag, &a));
10274     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) ++nrow;
10275     PetscCall(PetscMalloc1(nrow, &rows));
10276     nrow = 0;
10277     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) rows[nrow++] = r+rStart;
10278     PetscCall(VecRestoreArrayRead(diag, &a));
10279     PetscCall(VecDestroy(&diag));
10280     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) mat), nrow, rows, PETSC_OWN_POINTER, is));
10281   } else {
10282     PetscCall((*mat->ops->findzerodiagonals)(mat, is));
10283   }
10284   PetscFunctionReturn(0);
10285 }
10286 
10287 /*@
10288    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10289 
10290    Collective on Mat
10291 
10292    Input Parameter:
10293 .  mat - the matrix
10294 
10295    Output Parameter:
10296 .  is - contains the list of rows with off block diagonal entries
10297 
10298    Level: developer
10299 
10300 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10301 @*/
10302 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat,IS *is)
10303 {
10304   PetscFunctionBegin;
10305   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10306   PetscValidType(mat,1);
10307   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10308   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10309 
10310   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);
10311   PetscCall((*mat->ops->findoffblockdiagonalentries)(mat,is));
10312   PetscFunctionReturn(0);
10313 }
10314 
10315 /*@C
10316   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10317 
10318   Collective on Mat
10319 
10320   Input Parameters:
10321 . mat - the matrix
10322 
10323   Output Parameters:
10324 . values - the block inverses in column major order (FORTRAN-like)
10325 
10326    Note:
10327      The size of the blocks is determined by the block size of the matrix.
10328 
10329    Fortran Note:
10330      This routine is not available from Fortran.
10331 
10332   Level: advanced
10333 
10334 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10335 @*/
10336 PetscErrorCode MatInvertBlockDiagonal(Mat mat,const PetscScalar **values)
10337 {
10338   PetscFunctionBegin;
10339   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10340   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10341   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10342   PetscCheck(mat->ops->invertblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10343   PetscCall((*mat->ops->invertblockdiagonal)(mat,values));
10344   PetscFunctionReturn(0);
10345 }
10346 
10347 /*@C
10348   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10349 
10350   Collective on Mat
10351 
10352   Input Parameters:
10353 + mat - the matrix
10354 . nblocks - the number of blocks on the process, set with MatSetVariableBlockSizes()
10355 - bsizes - the size of each block on the process, set with MatSetVariableBlockSizes()
10356 
10357   Output Parameters:
10358 . values - the block inverses in column major order (FORTRAN-like)
10359 
10360    Note:
10361    This routine is not available from Fortran.
10362 
10363   Level: advanced
10364 
10365 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10366 @*/
10367 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *values)
10368 {
10369   PetscFunctionBegin;
10370   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10371   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10372   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10373   PetscCheck(mat->ops->invertvariableblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10374   PetscCall((*mat->ops->invertvariableblockdiagonal)(mat,nblocks,bsizes,values));
10375   PetscFunctionReturn(0);
10376 }
10377 
10378 /*@
10379   MatInvertBlockDiagonalMat - set matrix C to be the inverted block diagonal of matrix A
10380 
10381   Collective on Mat
10382 
10383   Input Parameters:
10384 . A - the matrix
10385 
10386   Output Parameters:
10387 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10388 
10389   Notes: the blocksize of the matrix is used to determine the blocks on the diagonal of C
10390 
10391   Level: advanced
10392 
10393 .seealso: `MatInvertBlockDiagonal()`
10394 @*/
10395 PetscErrorCode MatInvertBlockDiagonalMat(Mat A,Mat C)
10396 {
10397   const PetscScalar *vals;
10398   PetscInt          *dnnz;
10399   PetscInt           m,rstart,rend,bs,i,j;
10400 
10401   PetscFunctionBegin;
10402   PetscCall(MatInvertBlockDiagonal(A,&vals));
10403   PetscCall(MatGetBlockSize(A,&bs));
10404   PetscCall(MatGetLocalSize(A,&m,NULL));
10405   PetscCall(MatSetLayouts(C,A->rmap,A->cmap));
10406   PetscCall(PetscMalloc1(m/bs,&dnnz));
10407   for (j = 0; j < m/bs; j++) dnnz[j] = 1;
10408   PetscCall(MatXAIJSetPreallocation(C,bs,dnnz,NULL,NULL,NULL));
10409   PetscCall(PetscFree(dnnz));
10410   PetscCall(MatGetOwnershipRange(C,&rstart,&rend));
10411   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_FALSE));
10412   for (i = rstart/bs; i < rend/bs; i++) {
10413     PetscCall(MatSetValuesBlocked(C,1,&i,1,&i,&vals[(i-rstart/bs)*bs*bs],INSERT_VALUES));
10414   }
10415   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
10416   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
10417   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_TRUE));
10418   PetscFunctionReturn(0);
10419 }
10420 
10421 /*@C
10422     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10423     via MatTransposeColoringCreate().
10424 
10425     Collective on MatTransposeColoring
10426 
10427     Input Parameter:
10428 .   c - coloring context
10429 
10430     Level: intermediate
10431 
10432 .seealso: `MatTransposeColoringCreate()`
10433 @*/
10434 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10435 {
10436   MatTransposeColoring matcolor=*c;
10437 
10438   PetscFunctionBegin;
10439   if (!matcolor) PetscFunctionReturn(0);
10440   if (--((PetscObject)matcolor)->refct > 0) {matcolor = NULL; PetscFunctionReturn(0);}
10441 
10442   PetscCall(PetscFree3(matcolor->ncolumns,matcolor->nrows,matcolor->colorforrow));
10443   PetscCall(PetscFree(matcolor->rows));
10444   PetscCall(PetscFree(matcolor->den2sp));
10445   PetscCall(PetscFree(matcolor->colorforcol));
10446   PetscCall(PetscFree(matcolor->columns));
10447   if (matcolor->brows>0) PetscCall(PetscFree(matcolor->lstart));
10448   PetscCall(PetscHeaderDestroy(c));
10449   PetscFunctionReturn(0);
10450 }
10451 
10452 /*@C
10453     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10454     a MatTransposeColoring context has been created, computes a dense B^T by Apply
10455     MatTransposeColoring to sparse B.
10456 
10457     Collective on MatTransposeColoring
10458 
10459     Input Parameters:
10460 +   B - sparse matrix B
10461 .   Btdense - symbolic dense matrix B^T
10462 -   coloring - coloring context created with MatTransposeColoringCreate()
10463 
10464     Output Parameter:
10465 .   Btdense - dense matrix B^T
10466 
10467     Level: advanced
10468 
10469      Notes:
10470     These are used internally for some implementations of MatRARt()
10471 
10472 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10473 
10474 @*/
10475 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring,Mat B,Mat Btdense)
10476 {
10477   PetscFunctionBegin;
10478   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10479   PetscValidHeaderSpecific(Btdense,MAT_CLASSID,3);
10480   PetscValidHeaderSpecific(coloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10481 
10482   PetscCheck(B->ops->transcoloringapplysptoden,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)B)->type_name);
10483   PetscCall((B->ops->transcoloringapplysptoden)(coloring,B,Btdense));
10484   PetscFunctionReturn(0);
10485 }
10486 
10487 /*@C
10488     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10489     a MatTransposeColoring context has been created and a dense matrix Cden=A*Btdense
10490     in which Btdens is obtained from MatTransColoringApplySpToDen(), recover sparse matrix
10491     Csp from Cden.
10492 
10493     Collective on MatTransposeColoring
10494 
10495     Input Parameters:
10496 +   coloring - coloring context created with MatTransposeColoringCreate()
10497 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10498 
10499     Output Parameter:
10500 .   Csp - sparse matrix
10501 
10502     Level: advanced
10503 
10504      Notes:
10505     These are used internally for some implementations of MatRARt()
10506 
10507 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10508 
10509 @*/
10510 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring,Mat Cden,Mat Csp)
10511 {
10512   PetscFunctionBegin;
10513   PetscValidHeaderSpecific(matcoloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10514   PetscValidHeaderSpecific(Cden,MAT_CLASSID,2);
10515   PetscValidHeaderSpecific(Csp,MAT_CLASSID,3);
10516 
10517   PetscCheck(Csp->ops->transcoloringapplydentosp,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)Csp)->type_name);
10518   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring,Cden,Csp));
10519   PetscCall(MatAssemblyBegin(Csp,MAT_FINAL_ASSEMBLY));
10520   PetscCall(MatAssemblyEnd(Csp,MAT_FINAL_ASSEMBLY));
10521   PetscFunctionReturn(0);
10522 }
10523 
10524 /*@C
10525    MatTransposeColoringCreate - Creates a matrix coloring context for matrix product C=A*B^T.
10526 
10527    Collective on Mat
10528 
10529    Input Parameters:
10530 +  mat - the matrix product C
10531 -  iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring()
10532 
10533     Output Parameter:
10534 .   color - the new coloring context
10535 
10536     Level: intermediate
10537 
10538 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10539           `MatTransColoringApplyDenToSp()`
10540 @*/
10541 PetscErrorCode MatTransposeColoringCreate(Mat mat,ISColoring iscoloring,MatTransposeColoring *color)
10542 {
10543   MatTransposeColoring c;
10544   MPI_Comm             comm;
10545 
10546   PetscFunctionBegin;
10547   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate,mat,0,0,0));
10548   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10549   PetscCall(PetscHeaderCreate(c,MAT_TRANSPOSECOLORING_CLASSID,"MatTransposeColoring","Matrix product C=A*B^T via coloring","Mat",comm,MatTransposeColoringDestroy,NULL));
10550 
10551   c->ctype = iscoloring->ctype;
10552   if (mat->ops->transposecoloringcreate) {
10553     PetscCall((*mat->ops->transposecoloringcreate)(mat,iscoloring,c));
10554   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);
10555 
10556   *color = c;
10557   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate,mat,0,0,0));
10558   PetscFunctionReturn(0);
10559 }
10560 
10561 /*@
10562       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10563         matrix has had no new nonzero locations added to the matrix since the previous call then the value will be the
10564         same, otherwise it will be larger
10565 
10566      Not Collective
10567 
10568   Input Parameter:
10569 .    A  - the matrix
10570 
10571   Output Parameter:
10572 .    state - the current state
10573 
10574   Notes:
10575     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10576          different matrices
10577 
10578   Level: intermediate
10579 
10580 @*/
10581 PetscErrorCode MatGetNonzeroState(Mat mat,PetscObjectState *state)
10582 {
10583   PetscFunctionBegin;
10584   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10585   *state = mat->nonzerostate;
10586   PetscFunctionReturn(0);
10587 }
10588 
10589 /*@
10590       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10591                  matrices from each processor
10592 
10593     Collective
10594 
10595    Input Parameters:
10596 +    comm - the communicators the parallel matrix will live on
10597 .    seqmat - the input sequential matrices
10598 .    n - number of local columns (or PETSC_DECIDE)
10599 -    reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10600 
10601    Output Parameter:
10602 .    mpimat - the parallel matrix generated
10603 
10604     Level: advanced
10605 
10606    Notes:
10607     The number of columns of the matrix in EACH processor MUST be the same.
10608 
10609 @*/
10610 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm,Mat seqmat,PetscInt n,MatReuse reuse,Mat *mpimat)
10611 {
10612   PetscFunctionBegin;
10613   PetscCheck(seqmat->ops->creatempimatconcatenateseqmat,PetscObjectComm((PetscObject)seqmat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)seqmat)->type_name);
10614   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");
10615 
10616   PetscCall(PetscLogEventBegin(MAT_Merge,seqmat,0,0,0));
10617   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm,seqmat,n,reuse,mpimat));
10618   PetscCall(PetscLogEventEnd(MAT_Merge,seqmat,0,0,0));
10619   PetscFunctionReturn(0);
10620 }
10621 
10622 /*@
10623      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent
10624                  ranks' ownership ranges.
10625 
10626     Collective on A
10627 
10628    Input Parameters:
10629 +    A   - the matrix to create subdomains from
10630 -    N   - requested number of subdomains
10631 
10632    Output Parameters:
10633 +    n   - number of subdomains resulting on this rank
10634 -    iss - IS list with indices of subdomains on this rank
10635 
10636     Level: advanced
10637 
10638     Notes:
10639     number of subdomains must be smaller than the communicator size
10640 @*/
10641 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A,PetscInt N,PetscInt *n,IS *iss[])
10642 {
10643   MPI_Comm        comm,subcomm;
10644   PetscMPIInt     size,rank,color;
10645   PetscInt        rstart,rend,k;
10646 
10647   PetscFunctionBegin;
10648   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
10649   PetscCallMPI(MPI_Comm_size(comm,&size));
10650   PetscCallMPI(MPI_Comm_rank(comm,&rank));
10651   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);
10652   *n = 1;
10653   k = ((PetscInt)size)/N + ((PetscInt)size%N>0); /* There are up to k ranks to a color */
10654   color = rank/k;
10655   PetscCallMPI(MPI_Comm_split(comm,color,rank,&subcomm));
10656   PetscCall(PetscMalloc1(1,iss));
10657   PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
10658   PetscCall(ISCreateStride(subcomm,rend-rstart,rstart,1,iss[0]));
10659   PetscCallMPI(MPI_Comm_free(&subcomm));
10660   PetscFunctionReturn(0);
10661 }
10662 
10663 /*@
10664    MatGalerkin - Constructs the coarse grid problem via Galerkin projection.
10665 
10666    If the interpolation and restriction operators are the same, uses MatPtAP.
10667    If they are not the same, use MatMatMatMult.
10668 
10669    Once the coarse grid problem is constructed, correct for interpolation operators
10670    that are not of full rank, which can legitimately happen in the case of non-nested
10671    geometric multigrid.
10672 
10673    Input Parameters:
10674 +  restrct - restriction operator
10675 .  dA - fine grid matrix
10676 .  interpolate - interpolation operator
10677 .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10678 -  fill - expected fill, use PETSC_DEFAULT if you do not have a good estimate
10679 
10680    Output Parameters:
10681 .  A - the Galerkin coarse matrix
10682 
10683    Options Database Key:
10684 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10685 
10686    Level: developer
10687 
10688 .seealso: `MatPtAP()`, `MatMatMatMult()`
10689 @*/
10690 PetscErrorCode  MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10691 {
10692   IS             zerorows;
10693   Vec            diag;
10694 
10695   PetscFunctionBegin;
10696   PetscCheck(reuse != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
10697   /* Construct the coarse grid matrix */
10698   if (interpolate == restrct) {
10699     PetscCall(MatPtAP(dA,interpolate,reuse,fill,A));
10700   } else {
10701     PetscCall(MatMatMatMult(restrct,dA,interpolate,reuse,fill,A));
10702   }
10703 
10704   /* If the interpolation matrix is not of full rank, A will have zero rows.
10705      This can legitimately happen in the case of non-nested geometric multigrid.
10706      In that event, we set the rows of the matrix to the rows of the identity,
10707      ignoring the equations (as the RHS will also be zero). */
10708 
10709   PetscCall(MatFindZeroRows(*A, &zerorows));
10710 
10711   if (zerorows != NULL) { /* if there are any zero rows */
10712     PetscCall(MatCreateVecs(*A, &diag, NULL));
10713     PetscCall(MatGetDiagonal(*A, diag));
10714     PetscCall(VecISSet(diag, zerorows, 1.0));
10715     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10716     PetscCall(VecDestroy(&diag));
10717     PetscCall(ISDestroy(&zerorows));
10718   }
10719   PetscFunctionReturn(0);
10720 }
10721 
10722 /*@C
10723     MatSetOperation - Allows user to set a matrix operation for any matrix type
10724 
10725    Logically Collective on Mat
10726 
10727     Input Parameters:
10728 +   mat - the matrix
10729 .   op - the name of the operation
10730 -   f - the function that provides the operation
10731 
10732    Level: developer
10733 
10734     Usage:
10735 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10736 $      PetscCall(MatCreateXXX(comm,...&A);
10737 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10738 
10739     Notes:
10740     See the file include/petscmat.h for a complete list of matrix
10741     operations, which all have the form MATOP_<OPERATION>, where
10742     <OPERATION> is the name (in all capital letters) of the
10743     user interface routine (e.g., MatMult() -> MATOP_MULT).
10744 
10745     All user-provided functions (except for MATOP_DESTROY) should have the same calling
10746     sequence as the usual matrix interface routines, since they
10747     are intended to be accessed via the usual matrix interface
10748     routines, e.g.,
10749 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10750 
10751     In particular each function MUST return an error code of 0 on success and
10752     nonzero on failure.
10753 
10754     This routine is distinct from MatShellSetOperation() in that it can be called on any matrix type.
10755 
10756 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10757 @*/
10758 PetscErrorCode MatSetOperation(Mat mat,MatOperation op,void (*f)(void))
10759 {
10760   PetscFunctionBegin;
10761   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10762   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) {
10763     mat->ops->viewnative = mat->ops->view;
10764   }
10765   (((void(**)(void))mat->ops)[op]) = f;
10766   PetscFunctionReturn(0);
10767 }
10768 
10769 /*@C
10770     MatGetOperation - Gets a matrix operation for any matrix type.
10771 
10772     Not Collective
10773 
10774     Input Parameters:
10775 +   mat - the matrix
10776 -   op - the name of the operation
10777 
10778     Output Parameter:
10779 .   f - the function that provides the operation
10780 
10781     Level: developer
10782 
10783     Usage:
10784 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10785 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10786 
10787     Notes:
10788     See the file include/petscmat.h for a complete list of matrix
10789     operations, which all have the form MATOP_<OPERATION>, where
10790     <OPERATION> is the name (in all capital letters) of the
10791     user interface routine (e.g., MatMult() -> MATOP_MULT).
10792 
10793     This routine is distinct from MatShellGetOperation() in that it can be called on any matrix type.
10794 
10795 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10796 @*/
10797 PetscErrorCode MatGetOperation(Mat mat,MatOperation op,void(**f)(void))
10798 {
10799   PetscFunctionBegin;
10800   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10801   *f = (((void (**)(void))mat->ops)[op]);
10802   PetscFunctionReturn(0);
10803 }
10804 
10805 /*@
10806     MatHasOperation - Determines whether the given matrix supports the particular
10807     operation.
10808 
10809    Not Collective
10810 
10811    Input Parameters:
10812 +  mat - the matrix
10813 -  op - the operation, for example, MATOP_GET_DIAGONAL
10814 
10815    Output Parameter:
10816 .  has - either PETSC_TRUE or PETSC_FALSE
10817 
10818    Level: advanced
10819 
10820    Notes:
10821    See the file include/petscmat.h for a complete list of matrix
10822    operations, which all have the form MATOP_<OPERATION>, where
10823    <OPERATION> is the name (in all capital letters) of the
10824    user-level routine.  E.g., MatNorm() -> MATOP_NORM.
10825 
10826 .seealso: `MatCreateShell()`
10827 @*/
10828 PetscErrorCode MatHasOperation(Mat mat,MatOperation op,PetscBool *has)
10829 {
10830   PetscFunctionBegin;
10831   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10832   PetscValidBoolPointer(has,3);
10833   if (mat->ops->hasoperation) {
10834     PetscCall((*mat->ops->hasoperation)(mat,op,has));
10835   } else {
10836     if (((void**)mat->ops)[op]) *has = PETSC_TRUE;
10837     else {
10838       *has = PETSC_FALSE;
10839       if (op == MATOP_CREATE_SUBMATRIX) {
10840         PetscMPIInt size;
10841 
10842         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10843         if (size == 1) {
10844           PetscCall(MatHasOperation(mat,MATOP_CREATE_SUBMATRICES,has));
10845         }
10846       }
10847     }
10848   }
10849   PetscFunctionReturn(0);
10850 }
10851 
10852 /*@
10853     MatHasCongruentLayouts - Determines whether the rows and columns layouts
10854     of the matrix are congruent
10855 
10856    Collective on mat
10857 
10858    Input Parameters:
10859 .  mat - the matrix
10860 
10861    Output Parameter:
10862 .  cong - either PETSC_TRUE or PETSC_FALSE
10863 
10864    Level: beginner
10865 
10866    Notes:
10867 
10868 .seealso: `MatCreate()`, `MatSetSizes()`
10869 @*/
10870 PetscErrorCode MatHasCongruentLayouts(Mat mat,PetscBool *cong)
10871 {
10872   PetscFunctionBegin;
10873   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10874   PetscValidType(mat,1);
10875   PetscValidBoolPointer(cong,2);
10876   if (!mat->rmap || !mat->cmap) {
10877     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10878     PetscFunctionReturn(0);
10879   }
10880   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10881     PetscCall(PetscLayoutSetUp(mat->rmap));
10882     PetscCall(PetscLayoutSetUp(mat->cmap));
10883     PetscCall(PetscLayoutCompare(mat->rmap,mat->cmap,cong));
10884     if (*cong) mat->congruentlayouts = 1;
10885     else       mat->congruentlayouts = 0;
10886   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10887   PetscFunctionReturn(0);
10888 }
10889 
10890 PetscErrorCode MatSetInf(Mat A)
10891 {
10892   PetscFunctionBegin;
10893   PetscCheck(A->ops->setinf,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10894   PetscCall((*A->ops->setinf)(A));
10895   PetscFunctionReturn(0);
10896 }
10897