xref: /petsc/src/mat/interface/matrix.c (revision 06fd0f16f1a0daed2c46bc75d930f96890b54fe9)
1 /*
2    This is where the abstract matrix operations are defined
3 */
4 
5 #include <petsc/private/matimpl.h>        /*I "petscmat.h" I*/
6 #include <petsc/private/isimpl.h>
7 #include <petsc/private/vecimpl.h>
8 
9 /* Logging support */
10 PetscClassId MAT_CLASSID;
11 PetscClassId MAT_COLORING_CLASSID;
12 PetscClassId MAT_FDCOLORING_CLASSID;
13 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
14 
15 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
16 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve,MAT_MatTrSolve;
17 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
18 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
19 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
20 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
21 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
22 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
23 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply,MAT_Transpose,MAT_FDColoringFunction, MAT_CreateSubMat;
24 PetscLogEvent MAT_TransposeColoringCreate;
25 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
26 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric,MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
27 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
28 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
29 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
30 PetscLogEvent MAT_MultHermitianTranspose,MAT_MultHermitianTransposeAdd;
31 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
32 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
33 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
34 PetscLogEvent MAT_GetMultiProcBlock;
35 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
36 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
37 PetscLogEvent MAT_SetValuesBatch;
38 PetscLogEvent MAT_ViennaCLCopyToGPU;
39 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
40 PetscLogEvent MAT_Merge,MAT_Residual,MAT_SetRandom;
41 PetscLogEvent MAT_FactorFactS,MAT_FactorInvS;
42 PetscLogEvent MATCOLORING_Apply,MATCOLORING_Comm,MATCOLORING_Local,MATCOLORING_ISCreate,MATCOLORING_SetUp,MATCOLORING_Weights;
43 PetscLogEvent MAT_H2Opus_Build,MAT_H2Opus_Compress,MAT_H2Opus_Orthog,MAT_H2Opus_LR;
44 
45 const char *const MatFactorTypes[] = {"NONE","LU","CHOLESKY","ILU","ICC","ILUDT","QR","MatFactorType","MAT_FACTOR_",NULL};
46 
47 /*@
48    MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
49                   for sparse matrices that already have locations it fills the locations with random numbers
50 
51    Logically Collective on Mat
52 
53    Input Parameters:
54 +  x  - the matrix
55 -  rctx - the random number context, formed by PetscRandomCreate(), or NULL and
56           it will create one internally.
57 
58    Output Parameter:
59 .  x  - the matrix
60 
61    Example of Usage:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68    Level: intermediate
69 
70 .seealso: `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
71 @*/
72 PetscErrorCode MatSetRandom(Mat x,PetscRandom rctx)
73 {
74   PetscRandom    randObj = NULL;
75 
76   PetscFunctionBegin;
77   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
78   if (rctx) PetscValidHeaderSpecific(rctx,PETSC_RANDOM_CLASSID,2);
79   PetscValidType(x,1);
80   MatCheckPreallocated(x,1);
81 
82   PetscCheck(x->ops->setrandom,PetscObjectComm((PetscObject)x),PETSC_ERR_SUP,"Mat type %s",((PetscObject)x)->type_name);
83 
84   if (!rctx) {
85     MPI_Comm comm;
86     PetscCall(PetscObjectGetComm((PetscObject)x,&comm));
87     PetscCall(PetscRandomCreate(comm,&randObj));
88     PetscCall(PetscRandomSetFromOptions(randObj));
89     rctx = randObj;
90   }
91   PetscCall(PetscLogEventBegin(MAT_SetRandom,x,rctx,0,0));
92   PetscCall((*x->ops->setrandom)(x,rctx));
93   PetscCall(PetscLogEventEnd(MAT_SetRandom,x,rctx,0,0));
94 
95   PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY));
96   PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY));
97   PetscCall(PetscRandomDestroy(&randObj));
98   PetscFunctionReturn(0);
99 }
100 
101 /*@
102    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
103 
104    Logically Collective on Mat
105 
106    Input Parameter:
107 .  mat - the factored matrix
108 
109    Output Parameters:
110 +  pivot - the pivot value computed
111 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
112          the share the matrix
113 
114    Level: advanced
115 
116    Notes:
117     This routine does not work for factorizations done with external packages.
118 
119     This routine should only be called if MatGetFactorError() returns a value of MAT_FACTOR_NUMERIC_ZEROPIVOT
120 
121     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
122 
123 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`
124 @*/
125 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat,PetscReal *pivot,PetscInt *row)
126 {
127   PetscFunctionBegin;
128   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
129   PetscValidRealPointer(pivot,2);
130   PetscValidIntPointer(row,3);
131   *pivot = mat->factorerror_zeropivot_value;
132   *row   = mat->factorerror_zeropivot_row;
133   PetscFunctionReturn(0);
134 }
135 
136 /*@
137    MatFactorGetError - gets the error code from a factorization
138 
139    Logically Collective on Mat
140 
141    Input Parameters:
142 .  mat - the factored matrix
143 
144    Output Parameter:
145 .  err  - the error code
146 
147    Level: advanced
148 
149    Notes:
150     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
151 
152 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`
153 @*/
154 PetscErrorCode MatFactorGetError(Mat mat,MatFactorError *err)
155 {
156   PetscFunctionBegin;
157   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
158   PetscValidPointer(err,2);
159   *err = mat->factorerrortype;
160   PetscFunctionReturn(0);
161 }
162 
163 /*@
164    MatFactorClearError - clears the error code in a factorization
165 
166    Logically Collective on Mat
167 
168    Input Parameter:
169 .  mat - the factored matrix
170 
171    Level: developer
172 
173    Notes:
174     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
175 
176 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`
177 @*/
178 PetscErrorCode MatFactorClearError(Mat mat)
179 {
180   PetscFunctionBegin;
181   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
182   mat->factorerrortype             = MAT_FACTOR_NOERROR;
183   mat->factorerror_zeropivot_value = 0.0;
184   mat->factorerror_zeropivot_row   = 0;
185   PetscFunctionReturn(0);
186 }
187 
188 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat,PetscBool cols,PetscReal tol,IS *nonzero)
189 {
190   Vec               r,l;
191   const PetscScalar *al;
192   PetscInt          i,nz,gnz,N,n;
193 
194   PetscFunctionBegin;
195   PetscCall(MatCreateVecs(mat,&r,&l));
196   if (!cols) { /* nonzero rows */
197     PetscCall(MatGetSize(mat,&N,NULL));
198     PetscCall(MatGetLocalSize(mat,&n,NULL));
199     PetscCall(VecSet(l,0.0));
200     PetscCall(VecSetRandom(r,NULL));
201     PetscCall(MatMult(mat,r,l));
202     PetscCall(VecGetArrayRead(l,&al));
203   } else { /* nonzero columns */
204     PetscCall(MatGetSize(mat,NULL,&N));
205     PetscCall(MatGetLocalSize(mat,NULL,&n));
206     PetscCall(VecSet(r,0.0));
207     PetscCall(VecSetRandom(l,NULL));
208     PetscCall(MatMultTranspose(mat,l,r));
209     PetscCall(VecGetArrayRead(r,&al));
210   }
211   if (tol <= 0.0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nz++; }
212   else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nz++; }
213   PetscCall(MPIU_Allreduce(&nz,&gnz,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
214   if (gnz != N) {
215     PetscInt *nzr;
216     PetscCall(PetscMalloc1(nz,&nzr));
217     if (nz) {
218       if (tol < 0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nzr[nz++] = i; }
219       else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; }
220     }
221     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat),nz,nzr,PETSC_OWN_POINTER,nonzero));
222   } else *nonzero = NULL;
223   if (!cols) { /* nonzero rows */
224     PetscCall(VecRestoreArrayRead(l,&al));
225   } else {
226     PetscCall(VecRestoreArrayRead(r,&al));
227   }
228   PetscCall(VecDestroy(&l));
229   PetscCall(VecDestroy(&r));
230   PetscFunctionReturn(0);
231 }
232 
233 /*@
234       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
235 
236   Input Parameter:
237 .    A  - the matrix
238 
239   Output Parameter:
240 .    keptrows - the rows that are not completely zero
241 
242   Notes:
243     keptrows is set to NULL if all rows are nonzero.
244 
245   Level: intermediate
246 
247  @*/
248 PetscErrorCode MatFindNonzeroRows(Mat mat,IS *keptrows)
249 {
250   PetscFunctionBegin;
251   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
252   PetscValidType(mat,1);
253   PetscValidPointer(keptrows,2);
254   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
255   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
256   if (mat->ops->findnonzerorows) {
257     PetscCall((*mat->ops->findnonzerorows)(mat,keptrows));
258   } else {
259     PetscCall(MatFindNonzeroRowsOrCols_Basic(mat,PETSC_FALSE,0.0,keptrows));
260   }
261   PetscFunctionReturn(0);
262 }
263 
264 /*@
265       MatFindZeroRows - Locate all rows that are completely zero in the matrix
266 
267   Input Parameter:
268 .    A  - the matrix
269 
270   Output Parameter:
271 .    zerorows - the rows that are completely zero
272 
273   Notes:
274     zerorows is set to NULL if no rows are zero.
275 
276   Level: intermediate
277 
278  @*/
279 PetscErrorCode MatFindZeroRows(Mat mat,IS *zerorows)
280 {
281   IS       keptrows;
282   PetscInt m, n;
283 
284   PetscFunctionBegin;
285   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
286   PetscValidType(mat,1);
287   PetscValidPointer(zerorows,2);
288   PetscCall(MatFindNonzeroRows(mat, &keptrows));
289   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
290      In keeping with this convention, we set zerorows to NULL if there are no zero
291      rows. */
292   if (keptrows == NULL) {
293     *zerorows = NULL;
294   } else {
295     PetscCall(MatGetOwnershipRange(mat,&m,&n));
296     PetscCall(ISComplement(keptrows,m,n,zerorows));
297     PetscCall(ISDestroy(&keptrows));
298   }
299   PetscFunctionReturn(0);
300 }
301 
302 /*@
303    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
304 
305    Not Collective
306 
307    Input Parameters:
308 .   A - the matrix
309 
310    Output Parameters:
311 .   a - the diagonal part (which is a SEQUENTIAL matrix)
312 
313    Notes:
314     see the manual page for MatCreateAIJ() for more information on the "diagonal part" of the matrix.
315           Use caution, as the reference count on the returned matrix is not incremented and it is used as
316           part of the containing MPI Mat's normal operation.
317 
318    Level: advanced
319 
320 @*/
321 PetscErrorCode MatGetDiagonalBlock(Mat A,Mat *a)
322 {
323   PetscFunctionBegin;
324   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
325   PetscValidType(A,1);
326   PetscValidPointer(a,2);
327   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
328   if (A->ops->getdiagonalblock) {
329     PetscCall((*A->ops->getdiagonalblock)(A,a));
330   } else {
331     PetscMPIInt size;
332 
333     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
334     PetscCheck(size == 1,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not for parallel matrix type %s",((PetscObject)A)->type_name);
335     *a = A;
336   }
337   PetscFunctionReturn(0);
338 }
339 
340 /*@
341    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
342 
343    Collective on Mat
344 
345    Input Parameters:
346 .  mat - the matrix
347 
348    Output Parameter:
349 .   trace - the sum of the diagonal entries
350 
351    Level: advanced
352 
353 @*/
354 PetscErrorCode MatGetTrace(Mat mat,PetscScalar *trace)
355 {
356   Vec diag;
357 
358   PetscFunctionBegin;
359   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
360   PetscValidScalarPointer(trace,2);
361   PetscCall(MatCreateVecs(mat,&diag,NULL));
362   PetscCall(MatGetDiagonal(mat,diag));
363   PetscCall(VecSum(diag,trace));
364   PetscCall(VecDestroy(&diag));
365   PetscFunctionReturn(0);
366 }
367 
368 /*@
369    MatRealPart - Zeros out the imaginary part of the matrix
370 
371    Logically Collective on Mat
372 
373    Input Parameters:
374 .  mat - the matrix
375 
376    Level: advanced
377 
378 .seealso: `MatImaginaryPart()`
379 @*/
380 PetscErrorCode MatRealPart(Mat mat)
381 {
382   PetscFunctionBegin;
383   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
384   PetscValidType(mat,1);
385   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
386   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
387   PetscCheck(mat->ops->realpart,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
388   MatCheckPreallocated(mat,1);
389   PetscCall((*mat->ops->realpart)(mat));
390   PetscFunctionReturn(0);
391 }
392 
393 /*@C
394    MatGetGhosts - Get the global index of all ghost nodes defined by the sparse matrix
395 
396    Collective on Mat
397 
398    Input Parameter:
399 .  mat - the matrix
400 
401    Output Parameters:
402 +   nghosts - number of ghosts (note for BAIJ matrices there is one ghost for each block)
403 -   ghosts - the global indices of the ghost points
404 
405    Notes:
406     the nghosts and ghosts are suitable to pass into VecCreateGhost()
407 
408    Level: advanced
409 
410 @*/
411 PetscErrorCode MatGetGhosts(Mat mat,PetscInt *nghosts,const PetscInt *ghosts[])
412 {
413   PetscFunctionBegin;
414   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
415   PetscValidType(mat,1);
416   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
417   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
418   if (mat->ops->getghosts) {
419     PetscCall((*mat->ops->getghosts)(mat,nghosts,ghosts));
420   } else {
421     if (nghosts) *nghosts = 0;
422     if (ghosts)  *ghosts  = NULL;
423   }
424   PetscFunctionReturn(0);
425 }
426 
427 /*@
428    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
429 
430    Logically Collective on Mat
431 
432    Input Parameters:
433 .  mat - the matrix
434 
435    Level: advanced
436 
437 .seealso: `MatRealPart()`
438 @*/
439 PetscErrorCode MatImaginaryPart(Mat mat)
440 {
441   PetscFunctionBegin;
442   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
443   PetscValidType(mat,1);
444   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
445   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
446   PetscCheck(mat->ops->imaginarypart,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
447   MatCheckPreallocated(mat,1);
448   PetscCall((*mat->ops->imaginarypart)(mat));
449   PetscFunctionReturn(0);
450 }
451 
452 /*@
453    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for BAIJ matrices)
454 
455    Not Collective
456 
457    Input Parameter:
458 .  mat - the matrix
459 
460    Output Parameters:
461 +  missing - is any diagonal missing
462 -  dd - first diagonal entry that is missing (optional) on this process
463 
464    Level: advanced
465 
466 .seealso: `MatRealPart()`
467 @*/
468 PetscErrorCode MatMissingDiagonal(Mat mat,PetscBool *missing,PetscInt *dd)
469 {
470   PetscFunctionBegin;
471   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
472   PetscValidType(mat,1);
473   PetscValidBoolPointer(missing,2);
474   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix %s",((PetscObject)mat)->type_name);
475   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
476   PetscCheck(mat->ops->missingdiagonal,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
477   PetscCall((*mat->ops->missingdiagonal)(mat,missing,dd));
478   PetscFunctionReturn(0);
479 }
480 
481 /*@C
482    MatGetRow - Gets a row of a matrix.  You MUST call MatRestoreRow()
483    for each row that you get to ensure that your application does
484    not bleed memory.
485 
486    Not Collective
487 
488    Input Parameters:
489 +  mat - the matrix
490 -  row - the row to get
491 
492    Output Parameters:
493 +  ncols -  if not NULL, the number of nonzeros in the row
494 .  cols - if not NULL, the column numbers
495 -  vals - if not NULL, the values
496 
497    Notes:
498    This routine is provided for people who need to have direct access
499    to the structure of a matrix.  We hope that we provide enough
500    high-level matrix routines that few users will need it.
501 
502    MatGetRow() always returns 0-based column indices, regardless of
503    whether the internal representation is 0-based (default) or 1-based.
504 
505    For better efficiency, set cols and/or vals to NULL if you do
506    not wish to extract these quantities.
507 
508    The user can only examine the values extracted with MatGetRow();
509    the values cannot be altered.  To change the matrix entries, one
510    must use MatSetValues().
511 
512    You can only have one call to MatGetRow() outstanding for a particular
513    matrix at a time, per processor. MatGetRow() can only obtain rows
514    associated with the given processor, it cannot get rows from the
515    other processors; for that we suggest using MatCreateSubMatrices(), then
516    MatGetRow() on the submatrix. The row index passed to MatGetRow()
517    is in the global number of rows.
518 
519    Fortran Notes:
520    The calling sequence from Fortran is
521 .vb
522    MatGetRow(matrix,row,ncols,cols,values,ierr)
523          Mat     matrix (input)
524          integer row    (input)
525          integer ncols  (output)
526          integer cols(maxcols) (output)
527          double precision (or double complex) values(maxcols) output
528 .ve
529    where maxcols >= maximum nonzeros in any row of the matrix.
530 
531    Caution:
532    Do not try to change the contents of the output arrays (cols and vals).
533    In some cases, this may corrupt the matrix.
534 
535    Level: advanced
536 
537 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`
538 @*/
539 PetscErrorCode MatGetRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
540 {
541   PetscInt incols;
542 
543   PetscFunctionBegin;
544   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
545   PetscValidType(mat,1);
546   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
547   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
548   PetscCheck(mat->ops->getrow,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
549   MatCheckPreallocated(mat,1);
550   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")",row,mat->rmap->rstart,mat->rmap->rend);
551   PetscCall(PetscLogEventBegin(MAT_GetRow,mat,0,0,0));
552   PetscCall((*mat->ops->getrow)(mat,row,&incols,(PetscInt**)cols,(PetscScalar**)vals));
553   if (ncols) *ncols = incols;
554   PetscCall(PetscLogEventEnd(MAT_GetRow,mat,0,0,0));
555   PetscFunctionReturn(0);
556 }
557 
558 /*@
559    MatConjugate - replaces the matrix values with their complex conjugates
560 
561    Logically Collective on Mat
562 
563    Input Parameters:
564 .  mat - the matrix
565 
566    Level: advanced
567 
568 .seealso: `VecConjugate()`
569 @*/
570 PetscErrorCode MatConjugate(Mat mat)
571 {
572   PetscFunctionBegin;
573   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
574   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
575   if (PetscDefined(USE_COMPLEX)) {
576     PetscCheck(mat->ops->conjugate,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not provided for matrix type %s, send email to petsc-maint@mcs.anl.gov",((PetscObject)mat)->type_name);
577     PetscCall((*mat->ops->conjugate)(mat));
578   }
579   PetscFunctionReturn(0);
580 }
581 
582 /*@C
583    MatRestoreRow - Frees any temporary space allocated by MatGetRow().
584 
585    Not Collective
586 
587    Input Parameters:
588 +  mat - the matrix
589 .  row - the row to get
590 .  ncols, cols - the number of nonzeros and their columns
591 -  vals - if nonzero the column values
592 
593    Notes:
594    This routine should be called after you have finished examining the entries.
595 
596    This routine zeros out ncols, cols, and vals. This is to prevent accidental
597    us of the array after it has been restored. If you pass NULL, it will
598    not zero the pointers.  Use of cols or vals after MatRestoreRow is invalid.
599 
600    Fortran Notes:
601    The calling sequence from Fortran is
602 .vb
603    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
604       Mat     matrix (input)
605       integer row    (input)
606       integer ncols  (output)
607       integer cols(maxcols) (output)
608       double precision (or double complex) values(maxcols) output
609 .ve
610    Where maxcols >= maximum nonzeros in any row of the matrix.
611 
612    In Fortran MatRestoreRow() MUST be called after MatGetRow()
613    before another call to MatGetRow() can be made.
614 
615    Level: advanced
616 
617 .seealso: `MatGetRow()`
618 @*/
619 PetscErrorCode MatRestoreRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
620 {
621   PetscFunctionBegin;
622   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
623   if (ncols) PetscValidIntPointer(ncols,3);
624   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
625   if (!mat->ops->restorerow) PetscFunctionReturn(0);
626   PetscCall((*mat->ops->restorerow)(mat,row,ncols,(PetscInt **)cols,(PetscScalar **)vals));
627   if (ncols) *ncols = 0;
628   if (cols)  *cols = NULL;
629   if (vals)  *vals = NULL;
630   PetscFunctionReturn(0);
631 }
632 
633 /*@
634    MatGetRowUpperTriangular - Sets a flag to enable calls to MatGetRow() for matrix in MATSBAIJ format.
635    You should call MatRestoreRowUpperTriangular() after calling MatGetRow/MatRestoreRow() to disable the flag.
636 
637    Not Collective
638 
639    Input Parameters:
640 .  mat - the matrix
641 
642    Notes:
643    The flag is to ensure that users are aware of MatGetRow() only provides the upper triangular part of the row for the matrices in MATSBAIJ format.
644 
645    Level: advanced
646 
647 .seealso: `MatRestoreRowUpperTriangular()`
648 @*/
649 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
650 {
651   PetscFunctionBegin;
652   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
653   PetscValidType(mat,1);
654   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
655   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
656   MatCheckPreallocated(mat,1);
657   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
658   PetscCall((*mat->ops->getrowuppertriangular)(mat));
659   PetscFunctionReturn(0);
660 }
661 
662 /*@
663    MatRestoreRowUpperTriangular - Disable calls to MatGetRow() for matrix in MATSBAIJ format.
664 
665    Not Collective
666 
667    Input Parameters:
668 .  mat - the matrix
669 
670    Notes:
671    This routine should be called after you have finished MatGetRow/MatRestoreRow().
672 
673    Level: advanced
674 
675 .seealso: `MatGetRowUpperTriangular()`
676 @*/
677 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
678 {
679   PetscFunctionBegin;
680   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
681   PetscValidType(mat,1);
682   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
683   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
684   MatCheckPreallocated(mat,1);
685   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
686   PetscCall((*mat->ops->restorerowuppertriangular)(mat));
687   PetscFunctionReturn(0);
688 }
689 
690 /*@C
691    MatSetOptionsPrefix - Sets the prefix used for searching for all
692    Mat options in the database.
693 
694    Logically Collective on Mat
695 
696    Input Parameters:
697 +  A - the Mat context
698 -  prefix - the prefix to prepend to all option names
699 
700    Notes:
701    A hyphen (-) must NOT be given at the beginning of the prefix name.
702    The first character of all runtime options is AUTOMATICALLY the hyphen.
703 
704    This is NOT used for options for the factorization of the matrix. Normally the
705    prefix is automatically passed in from the PC calling the factorization. To set
706    it directly use  `MatSetOptionsPrefixFactor()`
707 
708    Level: advanced
709 
710 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
711 @*/
712 PetscErrorCode MatSetOptionsPrefix(Mat A,const char prefix[])
713 {
714   PetscFunctionBegin;
715   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
716   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A,prefix));
717   PetscFunctionReturn(0);
718 }
719 
720 /*@C
721    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all Mat factor options in the database for
722    for matrices created with `MatGetFactor()`
723 
724    Logically Collective on Mat
725 
726    Input Parameters:
727 +  A - the Mat context
728 -  prefix - the prefix to prepend to all option names for the factored matrix
729 
730    Notes:
731    A hyphen (-) must NOT be given at the beginning of the prefix name.
732    The first character of all runtime options is AUTOMATICALLY the hyphen.
733 
734    Normally the prefix is automatically passed in from the PC calling the factorization. To set
735    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
736 
737    Level: developer
738 
739 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
740 @*/
741 PetscErrorCode MatSetOptionsPrefixFactor(Mat A,const char prefix[])
742 {
743   PetscFunctionBegin;
744   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
745   if (prefix) {
746     PetscValidCharPointer(prefix,2);
747     PetscCheck(prefix[0] != '-',PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
748     if (prefix != A->factorprefix) {
749       PetscCall(PetscFree(A->factorprefix));
750       PetscCall(PetscStrallocpy(prefix,&A->factorprefix));
751     }
752   } else PetscCall(PetscFree(A->factorprefix));
753   PetscFunctionReturn(0);
754 }
755 
756 /*@C
757    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all Mat factor options in the database for
758    for matrices created with `MatGetFactor()`
759 
760    Logically Collective on Mat
761 
762    Input Parameters:
763 +  A - the Mat context
764 -  prefix - the prefix to prepend to all option names for the factored matrix
765 
766    Notes:
767    A hyphen (-) must NOT be given at the beginning of the prefix name.
768    The first character of all runtime options is AUTOMATICALLY the hyphen.
769 
770    Normally the prefix is automatically passed in from the PC calling the factorization. To set
771    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
772 
773    Level: developer
774    .seealso: `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
775              `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
776              `MatSetOptionsPrefix()`
777 @*/
778 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A,const char prefix[])
779 {
780   char           *buf = A->factorprefix;
781   size_t         len1,len2;
782 
783   PetscFunctionBegin;
784   PetscValidHeader(A,1);
785   if (!prefix) PetscFunctionReturn(0);
786   if (!buf) {
787     PetscCall(MatSetOptionsPrefixFactor(A,prefix));
788     PetscFunctionReturn(0);
789   }
790   PetscCheck(prefix[0] != '-',PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
791 
792   PetscCall(PetscStrlen(prefix,&len1));
793   PetscCall(PetscStrlen(buf,&len2));
794   PetscCall(PetscMalloc1(1+len1+len2,&A->factorprefix));
795   PetscCall(PetscStrcpy(A->factorprefix,buf));
796   PetscCall(PetscStrcat(A->factorprefix,prefix));
797   PetscCall(PetscFree(buf));
798   PetscFunctionReturn(0);
799 }
800 
801 /*@C
802    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
803    Mat options in the database.
804 
805    Logically Collective on Mat
806 
807    Input Parameters:
808 +  A - the Mat context
809 -  prefix - the prefix to prepend to all option names
810 
811    Notes:
812    A hyphen (-) must NOT be given at the beginning of the prefix name.
813    The first character of all runtime options is AUTOMATICALLY the hyphen.
814 
815    Level: advanced
816 
817 .seealso: `MatGetOptionsPrefix()`
818 @*/
819 PetscErrorCode MatAppendOptionsPrefix(Mat A,const char prefix[])
820 {
821   PetscFunctionBegin;
822   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
823   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A,prefix));
824   PetscFunctionReturn(0);
825 }
826 
827 /*@C
828    MatGetOptionsPrefix - Gets the prefix used for searching for all
829    Mat options in the database.
830 
831    Not Collective
832 
833    Input Parameter:
834 .  A - the Mat context
835 
836    Output Parameter:
837 .  prefix - pointer to the prefix string used
838 
839    Notes:
840     On the fortran side, the user should pass in a string 'prefix' of
841    sufficient length to hold the prefix.
842 
843    Level: advanced
844 
845 .seealso: `MatAppendOptionsPrefix()`
846 @*/
847 PetscErrorCode MatGetOptionsPrefix(Mat A,const char *prefix[])
848 {
849   PetscFunctionBegin;
850   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
851   PetscValidPointer(prefix,2);
852   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A,prefix));
853   PetscFunctionReturn(0);
854 }
855 
856 /*@
857    MatResetPreallocation - Reset mat to use the original nonzero pattern provided by users.
858 
859    Collective on Mat
860 
861    Input Parameters:
862 .  A - the Mat context
863 
864    Notes:
865    The allocated memory will be shrunk after calling MatAssembly with MAT_FINAL_ASSEMBLY. Users can reset the preallocation to access the original memory.
866    Currently support MPIAIJ and SEQAIJ.
867 
868    Level: beginner
869 
870 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
871 @*/
872 PetscErrorCode MatResetPreallocation(Mat A)
873 {
874   PetscFunctionBegin;
875   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
876   PetscValidType(A,1);
877   PetscUseMethod(A,"MatResetPreallocation_C",(Mat),(A));
878   PetscFunctionReturn(0);
879 }
880 
881 /*@
882    MatSetUp - Sets up the internal matrix data structures for later use.
883 
884    Collective on Mat
885 
886    Input Parameters:
887 .  A - the Mat context
888 
889    Notes:
890    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
891 
892    If a suitable preallocation routine is used, this function does not need to be called.
893 
894    See the Performance chapter of the PETSc users manual for how to preallocate matrices
895 
896    Level: beginner
897 
898 .seealso: `MatCreate()`, `MatDestroy()`
899 @*/
900 PetscErrorCode MatSetUp(Mat A)
901 {
902   PetscFunctionBegin;
903   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
904   if (!((PetscObject)A)->type_name) {
905     PetscMPIInt size;
906 
907     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
908     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
909   }
910   if (!A->preallocated && A->ops->setup) {
911     PetscCall(PetscInfo(A,"Warning not preallocating matrix storage\n"));
912     PetscCall((*A->ops->setup)(A));
913   }
914   PetscCall(PetscLayoutSetUp(A->rmap));
915   PetscCall(PetscLayoutSetUp(A->cmap));
916   A->preallocated = PETSC_TRUE;
917   PetscFunctionReturn(0);
918 }
919 
920 #if defined(PETSC_HAVE_SAWS)
921 #include <petscviewersaws.h>
922 #endif
923 
924 /*@C
925    MatViewFromOptions - View from Options
926 
927    Collective on Mat
928 
929    Input Parameters:
930 +  A - the Mat context
931 .  obj - Optional object
932 -  name - command line option
933 
934    Level: intermediate
935 .seealso: `Mat`, `MatView`, `PetscObjectViewFromOptions()`, `MatCreate()`
936 @*/
937 PetscErrorCode  MatViewFromOptions(Mat A,PetscObject obj,const char name[])
938 {
939   PetscFunctionBegin;
940   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
941   PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name));
942   PetscFunctionReturn(0);
943 }
944 
945 /*@C
946    MatView - Visualizes a matrix object.
947 
948    Collective on Mat
949 
950    Input Parameters:
951 +  mat - the matrix
952 -  viewer - visualization context
953 
954   Notes:
955   The available visualization contexts include
956 +    PETSC_VIEWER_STDOUT_SELF - for sequential matrices
957 .    PETSC_VIEWER_STDOUT_WORLD - for parallel matrices created on PETSC_COMM_WORLD
958 .    PETSC_VIEWER_STDOUT_(comm) - for matrices created on MPI communicator comm
959 -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
960 
961    The user can open alternative visualization contexts with
962 +    PetscViewerASCIIOpen() - Outputs matrix to a specified file
963 .    PetscViewerBinaryOpen() - Outputs matrix in binary to a
964          specified file; corresponding input uses MatLoad()
965 .    PetscViewerDrawOpen() - Outputs nonzero matrix structure to
966          an X window display
967 -    PetscViewerSocketOpen() - Outputs matrix to Socket viewer.
968          Currently only the sequential dense and AIJ
969          matrix types support the Socket viewer.
970 
971    The user can call PetscViewerPushFormat() to specify the output
972    format of ASCII printed objects (when using PETSC_VIEWER_STDOUT_SELF,
973    PETSC_VIEWER_STDOUT_WORLD and PetscViewerASCIIOpen).  Available formats include
974 +    PETSC_VIEWER_DEFAULT - default, prints matrix contents
975 .    PETSC_VIEWER_ASCII_MATLAB - prints matrix contents in Matlab format
976 .    PETSC_VIEWER_ASCII_DENSE - prints entire matrix including zeros
977 .    PETSC_VIEWER_ASCII_COMMON - prints matrix contents, using a sparse
978          format common among all matrix types
979 .    PETSC_VIEWER_ASCII_IMPL - prints matrix contents, using an implementation-specific
980          format (which is in many cases the same as the default)
981 .    PETSC_VIEWER_ASCII_INFO - prints basic information about the matrix
982          size and structure (not the matrix entries)
983 -    PETSC_VIEWER_ASCII_INFO_DETAIL - prints more detailed information about
984          the matrix structure
985 
986    Options Database Keys:
987 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatAssemblyEnd()
988 .  -mat_view ::ascii_info_detail - Prints more detailed info
989 .  -mat_view - Prints matrix in ASCII format
990 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
991 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
992 .  -display <name> - Sets display name (default is host)
993 .  -draw_pause <sec> - Sets number of seconds to pause after display
994 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
995 .  -viewer_socket_machine <machine> -
996 .  -viewer_socket_port <port> -
997 .  -mat_view binary - save matrix to file in binary format
998 -  -viewer_binary_filename <name> -
999 
1000    Level: beginner
1001 
1002    Notes:
1003     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1004     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1005 
1006     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1007 
1008     See the manual page for MatLoad() for the exact format of the binary file when the binary
1009       viewer is used.
1010 
1011       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1012       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1013 
1014       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1015       and then use the following mouse functions.
1016 .vb
1017   left mouse: zoom in
1018   middle mouse: zoom out
1019   right mouse: continue with the simulation
1020 .ve
1021 
1022 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`,
1023           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`
1024 @*/
1025 PetscErrorCode MatView(Mat mat,PetscViewer viewer)
1026 {
1027   PetscInt          rows,cols,rbs,cbs;
1028   PetscBool         isascii,isstring,issaws;
1029   PetscViewerFormat format;
1030   PetscMPIInt       size;
1031 
1032   PetscFunctionBegin;
1033   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1034   PetscValidType(mat,1);
1035   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat),&viewer));
1036   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1037   PetscCheckSameComm(mat,1,viewer,2);
1038   MatCheckPreallocated(mat,1);
1039 
1040   PetscCall(PetscViewerGetFormat(viewer,&format));
1041   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
1042   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1043 
1044   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring));
1045   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
1046   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws));
1047   if ((!isascii || (format != PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) && mat->factortype) {
1048     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"No viewers for factored matrix except ASCII info or info_detail");
1049   }
1050 
1051   PetscCall(PetscLogEventBegin(MAT_View,mat,viewer,0,0));
1052   if (isascii) {
1053     PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Must call MatAssemblyBegin/End() before viewing matrix");
1054     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat,viewer));
1055     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1056       MatNullSpace nullsp,transnullsp;
1057 
1058       PetscCall(PetscViewerASCIIPushTab(viewer));
1059       PetscCall(MatGetSize(mat,&rows,&cols));
1060       PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
1061       if (rbs != 1 || cbs != 1) {
1062         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n",rows,cols,rbs,cbs));
1063         else            PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n",rows,cols,rbs));
1064       } else PetscCall(PetscViewerASCIIPrintf(viewer,"rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n",rows,cols));
1065       if (mat->factortype) {
1066         MatSolverType solver;
1067         PetscCall(MatFactorGetSolverType(mat,&solver));
1068         PetscCall(PetscViewerASCIIPrintf(viewer,"package used to perform factorization: %s\n",solver));
1069       }
1070       if (mat->ops->getinfo) {
1071         MatInfo info;
1072         PetscCall(MatGetInfo(mat,MAT_GLOBAL_SUM,&info));
1073         PetscCall(PetscViewerASCIIPrintf(viewer,"total: nonzeros=%.f, allocated nonzeros=%.f\n",info.nz_used,info.nz_allocated));
1074         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer,"total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n",(PetscInt)info.mallocs));
1075       }
1076       PetscCall(MatGetNullSpace(mat,&nullsp));
1077       PetscCall(MatGetTransposeNullSpace(mat,&transnullsp));
1078       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached null space\n"));
1079       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached transposed null space\n"));
1080       PetscCall(MatGetNearNullSpace(mat,&nullsp));
1081       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer,"  has attached near null space\n"));
1082       PetscCall(PetscViewerASCIIPushTab(viewer));
1083       PetscCall(MatProductView(mat,viewer));
1084       PetscCall(PetscViewerASCIIPopTab(viewer));
1085     }
1086   } else if (issaws) {
1087 #if defined(PETSC_HAVE_SAWS)
1088     PetscMPIInt rank;
1089 
1090     PetscCall(PetscObjectName((PetscObject)mat));
1091     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
1092     if (!((PetscObject)mat)->amsmem && rank == 0) {
1093       PetscCall(PetscObjectViewSAWs((PetscObject)mat,viewer));
1094     }
1095 #endif
1096   } else if (isstring) {
1097     const char *type;
1098     PetscCall(MatGetType(mat,&type));
1099     PetscCall(PetscViewerStringSPrintf(viewer," MatType: %-7.7s",type));
1100     if (mat->ops->view) PetscCall((*mat->ops->view)(mat,viewer));
1101   }
1102   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1103     PetscCall(PetscViewerASCIIPushTab(viewer));
1104     PetscCall((*mat->ops->viewnative)(mat,viewer));
1105     PetscCall(PetscViewerASCIIPopTab(viewer));
1106   } else if (mat->ops->view) {
1107     PetscCall(PetscViewerASCIIPushTab(viewer));
1108     PetscCall((*mat->ops->view)(mat,viewer));
1109     PetscCall(PetscViewerASCIIPopTab(viewer));
1110   }
1111   if (isascii) {
1112     PetscCall(PetscViewerGetFormat(viewer,&format));
1113     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1114       PetscCall(PetscViewerASCIIPopTab(viewer));
1115     }
1116   }
1117   PetscCall(PetscLogEventEnd(MAT_View,mat,viewer,0,0));
1118   PetscFunctionReturn(0);
1119 }
1120 
1121 #if defined(PETSC_USE_DEBUG)
1122 #include <../src/sys/totalview/tv_data_display.h>
1123 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1124 {
1125   TV_add_row("Local rows", "int", &mat->rmap->n);
1126   TV_add_row("Local columns", "int", &mat->cmap->n);
1127   TV_add_row("Global rows", "int", &mat->rmap->N);
1128   TV_add_row("Global columns", "int", &mat->cmap->N);
1129   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1130   return TV_format_OK;
1131 }
1132 #endif
1133 
1134 /*@C
1135    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1136    with MatView().  The matrix format is determined from the options database.
1137    Generates a parallel MPI matrix if the communicator has more than one
1138    processor.  The default matrix type is AIJ.
1139 
1140    Collective on PetscViewer
1141 
1142    Input Parameters:
1143 +  mat - the newly loaded matrix, this needs to have been created with MatCreate()
1144             or some related function before a call to MatLoad()
1145 -  viewer - binary/HDF5 file viewer
1146 
1147    Options Database Keys:
1148    Used with block matrix formats (MATSEQBAIJ,  ...) to specify
1149    block size
1150 .    -matload_block_size <bs> - set block size
1151 
1152    Level: beginner
1153 
1154    Notes:
1155    If the Mat type has not yet been given then MATAIJ is used, call MatSetFromOptions() on the
1156    Mat before calling this routine if you wish to set it from the options database.
1157 
1158    MatLoad() automatically loads into the options database any options
1159    given in the file filename.info where filename is the name of the file
1160    that was passed to the PetscViewerBinaryOpen(). The options in the info
1161    file will be ignored if you use the -viewer_binary_skip_info option.
1162 
1163    If the type or size of mat is not set before a call to MatLoad, PETSc
1164    sets the default matrix type AIJ and sets the local and global sizes.
1165    If type and/or size is already set, then the same are used.
1166 
1167    In parallel, each processor can load a subset of rows (or the
1168    entire matrix).  This routine is especially useful when a large
1169    matrix is stored on disk and only part of it is desired on each
1170    processor.  For example, a parallel solver may access only some of
1171    the rows from each processor.  The algorithm used here reads
1172    relatively small blocks of data rather than reading the entire
1173    matrix and then subsetting it.
1174 
1175    Viewer's PetscViewerType must be either PETSCVIEWERBINARY or PETSCVIEWERHDF5.
1176    Such viewer can be created using PetscViewerBinaryOpen()/PetscViewerHDF5Open(),
1177    or the sequence like
1178 $    PetscViewer v;
1179 $    PetscViewerCreate(PETSC_COMM_WORLD,&v);
1180 $    PetscViewerSetType(v,PETSCVIEWERBINARY);
1181 $    PetscViewerSetFromOptions(v);
1182 $    PetscViewerFileSetMode(v,FILE_MODE_READ);
1183 $    PetscViewerFileSetName(v,"datafile");
1184    The optional PetscViewerSetFromOptions() call allows to override PetscViewerSetType() using option
1185 $ -viewer_type {binary,hdf5}
1186 
1187    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1188    and src/mat/tutorials/ex10.c with the second approach.
1189 
1190    Notes about the PETSc binary format:
1191    In case of PETSCVIEWERBINARY, a native PETSc binary format is used. Each of the blocks
1192    is read onto rank 0 and then shipped to its destination rank, one after another.
1193    Multiple objects, both matrices and vectors, can be stored within the same file.
1194    Their PetscObject name is ignored; they are loaded in the order of their storage.
1195 
1196    Most users should not need to know the details of the binary storage
1197    format, since MatLoad() and MatView() completely hide these details.
1198    But for anyone who's interested, the standard binary matrix storage
1199    format is
1200 
1201 $    PetscInt    MAT_FILE_CLASSID
1202 $    PetscInt    number of rows
1203 $    PetscInt    number of columns
1204 $    PetscInt    total number of nonzeros
1205 $    PetscInt    *number nonzeros in each row
1206 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1207 $    PetscScalar *values of all nonzeros
1208 
1209    PETSc automatically does the byte swapping for
1210 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1211 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1212 read/write routines you have to swap the bytes; see PetscBinaryRead()
1213 and PetscBinaryWrite() to see how this may be done.
1214 
1215    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1216    In case of PETSCVIEWERHDF5, a parallel HDF5 reader is used.
1217    Each processor's chunk is loaded independently by its owning rank.
1218    Multiple objects, both matrices and vectors, can be stored within the same file.
1219    They are looked up by their PetscObject name.
1220 
1221    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1222    by default the same structure and naming of the AIJ arrays and column count
1223    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1224 $    save example.mat A b -v7.3
1225    can be directly read by this routine (see Reference 1 for details).
1226    Note that depending on your MATLAB version, this format might be a default,
1227    otherwise you can set it as default in Preferences.
1228 
1229    Unless -nocompression flag is used to save the file in MATLAB,
1230    PETSc must be configured with ZLIB package.
1231 
1232    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1233 
1234    Current HDF5 (MAT-File) limitations:
1235    This reader currently supports only real MATSEQAIJ, MATMPIAIJ, MATSEQDENSE and MATMPIDENSE matrices.
1236 
1237    Corresponding MatView() is not yet implemented.
1238 
1239    The loaded matrix is actually a transpose of the original one in MATLAB,
1240    unless you push PETSC_VIEWER_HDF5_MAT format (see examples above).
1241    With this format, matrix is automatically transposed by PETSc,
1242    unless the matrix is marked as SPD or symmetric
1243    (see MatSetOption(), MAT_SPD, MAT_SYMMETRIC).
1244 
1245    References:
1246 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1247 
1248 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1249 
1250  @*/
1251 PetscErrorCode MatLoad(Mat mat,PetscViewer viewer)
1252 {
1253   PetscBool flg;
1254 
1255   PetscFunctionBegin;
1256   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1257   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1258 
1259   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat,MATAIJ));
1260 
1261   flg  = PETSC_FALSE;
1262   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matload_symmetric",&flg,NULL));
1263   if (flg) {
1264     PetscCall(MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE));
1265     PetscCall(MatSetOption(mat,MAT_SYMMETRY_ETERNAL,PETSC_TRUE));
1266   }
1267   flg  = PETSC_FALSE;
1268   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matload_spd",&flg,NULL));
1269   if (flg) PetscCall(MatSetOption(mat,MAT_SPD,PETSC_TRUE));
1270 
1271   PetscCheck(mat->ops->load,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatLoad is not supported for type %s",((PetscObject)mat)->type_name);
1272   PetscCall(PetscLogEventBegin(MAT_Load,mat,viewer,0,0));
1273   PetscCall((*mat->ops->load)(mat,viewer));
1274   PetscCall(PetscLogEventEnd(MAT_Load,mat,viewer,0,0));
1275   PetscFunctionReturn(0);
1276 }
1277 
1278 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1279 {
1280   Mat_Redundant *redund = *redundant;
1281 
1282   PetscFunctionBegin;
1283   if (redund) {
1284     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1285       PetscCall(ISDestroy(&redund->isrow));
1286       PetscCall(ISDestroy(&redund->iscol));
1287       PetscCall(MatDestroySubMatrices(1,&redund->matseq));
1288     } else {
1289       PetscCall(PetscFree2(redund->send_rank,redund->recv_rank));
1290       PetscCall(PetscFree(redund->sbuf_j));
1291       PetscCall(PetscFree(redund->sbuf_a));
1292       for (PetscInt i=0; i<redund->nrecvs; i++) {
1293         PetscCall(PetscFree(redund->rbuf_j[i]));
1294         PetscCall(PetscFree(redund->rbuf_a[i]));
1295       }
1296       PetscCall(PetscFree4(redund->sbuf_nz,redund->rbuf_nz,redund->rbuf_j,redund->rbuf_a));
1297     }
1298 
1299     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1300     PetscCall(PetscFree(redund));
1301   }
1302   PetscFunctionReturn(0);
1303 }
1304 
1305 /*@C
1306    MatDestroy - Frees space taken by a matrix.
1307 
1308    Collective on Mat
1309 
1310    Input Parameter:
1311 .  A - the matrix
1312 
1313    Level: beginner
1314 
1315    Developer Notes:
1316    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1317    MatDestroySubMatrices(). Thus one must be sure that any changes here must also be made in those routines.
1318    MatHeaderMerge() and MatHeaderReplace() also manipulate the data in the Mat object and likely need changes
1319    if changes are needed here.
1320 @*/
1321 PetscErrorCode MatDestroy(Mat *A)
1322 {
1323   PetscFunctionBegin;
1324   if (!*A) PetscFunctionReturn(0);
1325   PetscValidHeaderSpecific(*A,MAT_CLASSID,1);
1326   if (--((PetscObject)(*A))->refct > 0) {*A = NULL; PetscFunctionReturn(0);}
1327 
1328   /* if memory was published with SAWs then destroy it */
1329   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1330   if ((*A)->ops->destroy) PetscCall((*(*A)->ops->destroy)(*A));
1331 
1332   PetscCall(PetscFree((*A)->factorprefix));
1333   PetscCall(PetscFree((*A)->defaultvectype));
1334   PetscCall(PetscFree((*A)->bsizes));
1335   PetscCall(PetscFree((*A)->solvertype));
1336   for (PetscInt i=0; i<MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1337   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1338   PetscCall(MatProductClear(*A));
1339   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1340   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1341   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1342   PetscCall(MatDestroy(&(*A)->schur));
1343   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1344   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1345   PetscCall(PetscHeaderDestroy(A));
1346   PetscFunctionReturn(0);
1347 }
1348 
1349 /*@C
1350    MatSetValues - Inserts or adds a block of values into a matrix.
1351    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
1352    MUST be called after all calls to MatSetValues() have been completed.
1353 
1354    Not Collective
1355 
1356    Input Parameters:
1357 +  mat - the matrix
1358 .  v - a logically two-dimensional array of values
1359 .  m, idxm - the number of rows and their global indices
1360 .  n, idxn - the number of columns and their global indices
1361 -  addv - either ADD_VALUES or INSERT_VALUES, where
1362    ADD_VALUES adds values to any existing entries, and
1363    INSERT_VALUES replaces existing entries with new values
1364 
1365    Notes:
1366    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
1367       MatSetUp() before using this routine
1368 
1369    By default the values, v, are row-oriented. See MatSetOption() for other options.
1370 
1371    Calls to MatSetValues() with the INSERT_VALUES and ADD_VALUES
1372    options cannot be mixed without intervening calls to the assembly
1373    routines.
1374 
1375    MatSetValues() uses 0-based row and column numbers in Fortran
1376    as well as in C.
1377 
1378    Negative indices may be passed in idxm and idxn, these rows and columns are
1379    simply ignored. This allows easily inserting element stiffness matrices
1380    with homogeneous Dirchlet boundary conditions that you don't want represented
1381    in the matrix.
1382 
1383    Efficiency Alert:
1384    The routine MatSetValuesBlocked() may offer much better efficiency
1385    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1386 
1387    Level: beginner
1388 
1389    Developer Notes:
1390     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1391                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1392 
1393 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1394           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1395 @*/
1396 PetscErrorCode MatSetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1397 {
1398   PetscFunctionBeginHot;
1399   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1400   PetscValidType(mat,1);
1401   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1402   PetscValidIntPointer(idxm,3);
1403   PetscValidIntPointer(idxn,5);
1404   MatCheckPreallocated(mat,1);
1405 
1406   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1407   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1408 
1409   if (PetscDefined(USE_DEBUG)) {
1410     PetscInt       i,j;
1411 
1412     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1413     PetscCheck(mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1414 
1415     for (i=0; i<m; i++) {
1416       for (j=0; j<n; j++) {
1417         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i*n+j]))
1418 #if defined(PETSC_USE_COMPLEX)
1419           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")",(double)PetscRealPart(v[i*n+j]),(double)PetscImaginaryPart(v[i*n+j]),idxm[i],idxn[j]);
1420 #else
1421           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")",(double)v[i*n+j],idxm[i],idxn[j]);
1422 #endif
1423       }
1424     }
1425     for (i=0; i<m; i++) PetscCheck(idxm[i] < mat->rmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT,idxm[i],mat->rmap->N-1);
1426     for (i=0; i<n; i++) PetscCheck(idxn[i] < mat->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT,idxn[i],mat->cmap->N-1);
1427   }
1428 
1429   if (mat->assembled) {
1430     mat->was_assembled = PETSC_TRUE;
1431     mat->assembled     = PETSC_FALSE;
1432   }
1433   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1434   PetscCall((*mat->ops->setvalues)(mat,m,idxm,n,idxn,v,addv));
1435   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1436   PetscFunctionReturn(0);
1437 }
1438 
1439 /*@C
1440    MatSetValuesIS - Inserts or adds a block of values into a matrix using IS to indicate the rows and columns
1441    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
1442    MUST be called after all calls to MatSetValues() have been completed.
1443 
1444    Not Collective
1445 
1446    Input Parameters:
1447 +  mat - the matrix
1448 .  v - a logically two-dimensional array of values
1449 .  ism - the rows to provide
1450 .  isn - the columns to provide
1451 -  addv - either ADD_VALUES or INSERT_VALUES, where
1452    ADD_VALUES adds values to any existing entries, and
1453    INSERT_VALUES replaces existing entries with new values
1454 
1455    Notes:
1456    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
1457       MatSetUp() before using this routine
1458 
1459    By default the values, v, are row-oriented. See MatSetOption() for other options.
1460 
1461    Calls to MatSetValues() with the INSERT_VALUES and ADD_VALUES
1462    options cannot be mixed without intervening calls to the assembly
1463    routines.
1464 
1465    MatSetValues() uses 0-based row and column numbers in Fortran
1466    as well as in C.
1467 
1468    Negative indices may be passed in ism and isn, these rows and columns are
1469    simply ignored. This allows easily inserting element stiffness matrices
1470    with homogeneous Dirchlet boundary conditions that you don't want represented
1471    in the matrix.
1472 
1473    Efficiency Alert:
1474    The routine MatSetValuesBlocked() may offer much better efficiency
1475    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1476 
1477    Level: beginner
1478 
1479    Developer Notes:
1480     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1481                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1482 
1483     This is currently not optimized for any particular IS type
1484 
1485 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal(),
1486           InsertMode, INSERT_VALUES, ADD_VALUES, MatSetValues()
1487 @*/
1488 PetscErrorCode MatSetValuesIS(Mat mat,IS ism,IS isn,const PetscScalar v[],InsertMode addv)
1489 {
1490   PetscInt       m,n;
1491   const PetscInt *rows,*cols;
1492 
1493   PetscFunctionBeginHot;
1494   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1495   PetscCall(ISGetIndices(ism,&rows));
1496   PetscCall(ISGetIndices(isn,&cols));
1497   PetscCall(ISGetLocalSize(ism,&m));
1498   PetscCall(ISGetLocalSize(isn,&n));
1499   PetscCall(MatSetValues(mat,m,rows,n,cols,v,addv));
1500   PetscCall(ISRestoreIndices(ism,&rows));
1501   PetscCall(ISRestoreIndices(isn,&cols));
1502   PetscFunctionReturn(0);
1503 }
1504 
1505 /*@
1506    MatSetValuesRowLocal - Inserts a row (block row for BAIJ matrices) of nonzero
1507         values into a matrix
1508 
1509    Not Collective
1510 
1511    Input Parameters:
1512 +  mat - the matrix
1513 .  row - the (block) row to set
1514 -  v - a logically two-dimensional array of values
1515 
1516    Notes:
1517    By the values, v, are column-oriented (for the block version) and sorted
1518 
1519    All the nonzeros in the row must be provided
1520 
1521    The matrix must have previously had its column indices set
1522 
1523    The row must belong to this process
1524 
1525    Level: intermediate
1526 
1527 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1528           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1529 @*/
1530 PetscErrorCode MatSetValuesRowLocal(Mat mat,PetscInt row,const PetscScalar v[])
1531 {
1532   PetscInt globalrow;
1533 
1534   PetscFunctionBegin;
1535   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1536   PetscValidType(mat,1);
1537   PetscValidScalarPointer(v,3);
1538   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,1,&row,&globalrow));
1539   PetscCall(MatSetValuesRow(mat,globalrow,v));
1540   PetscFunctionReturn(0);
1541 }
1542 
1543 /*@
1544    MatSetValuesRow - Inserts a row (block row for BAIJ matrices) of nonzero
1545         values into a matrix
1546 
1547    Not Collective
1548 
1549    Input Parameters:
1550 +  mat - the matrix
1551 .  row - the (block) row to set
1552 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1553 
1554    Notes:
1555    The values, v, are column-oriented for the block version.
1556 
1557    All the nonzeros in the row must be provided
1558 
1559    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually MatSetValues() is used.
1560 
1561    The row must belong to this process
1562 
1563    Level: advanced
1564 
1565 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1566           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1567 @*/
1568 PetscErrorCode MatSetValuesRow(Mat mat,PetscInt row,const PetscScalar v[])
1569 {
1570   PetscFunctionBeginHot;
1571   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1572   PetscValidType(mat,1);
1573   MatCheckPreallocated(mat,1);
1574   PetscValidScalarPointer(v,3);
1575   PetscCheck(mat->insertmode != ADD_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add and insert values");
1576   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1577   mat->insertmode = INSERT_VALUES;
1578 
1579   if (mat->assembled) {
1580     mat->was_assembled = PETSC_TRUE;
1581     mat->assembled     = PETSC_FALSE;
1582   }
1583   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1584   PetscCheck(mat->ops->setvaluesrow,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1585   PetscCall((*mat->ops->setvaluesrow)(mat,row,v));
1586   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1587   PetscFunctionReturn(0);
1588 }
1589 
1590 /*@
1591    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1592      Using structured grid indexing
1593 
1594    Not Collective
1595 
1596    Input Parameters:
1597 +  mat - the matrix
1598 .  m - number of rows being entered
1599 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1600 .  n - number of columns being entered
1601 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1602 .  v - a logically two-dimensional array of values
1603 -  addv - either ADD_VALUES or INSERT_VALUES, where
1604    ADD_VALUES adds values to any existing entries, and
1605    INSERT_VALUES replaces existing entries with new values
1606 
1607    Notes:
1608    By default the values, v, are row-oriented.  See MatSetOption() for other options.
1609 
1610    Calls to MatSetValuesStencil() with the INSERT_VALUES and ADD_VALUES
1611    options cannot be mixed without intervening calls to the assembly
1612    routines.
1613 
1614    The grid coordinates are across the entire grid, not just the local portion
1615 
1616    MatSetValuesStencil() uses 0-based row and column numbers in Fortran
1617    as well as in C.
1618 
1619    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1620 
1621    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1622    or call MatSetLocalToGlobalMapping() and MatSetStencil() first.
1623 
1624    The columns and rows in the stencil passed in MUST be contained within the
1625    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1626    if you create a DMDA with an overlap of one grid level and on a particular process its first
1627    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1628    first i index you can use in your column and row indices in MatSetStencil() is 5.
1629 
1630    In Fortran idxm and idxn should be declared as
1631 $     MatStencil idxm(4,m),idxn(4,n)
1632    and the values inserted using
1633 $    idxm(MatStencil_i,1) = i
1634 $    idxm(MatStencil_j,1) = j
1635 $    idxm(MatStencil_k,1) = k
1636 $    idxm(MatStencil_c,1) = c
1637    etc
1638 
1639    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1640    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1641    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1642    DM_BOUNDARY_PERIODIC boundary type.
1643 
1644    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1645    a single value per point) you can skip filling those indices.
1646 
1647    Inspired by the structured grid interface to the HYPRE package
1648    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1649 
1650    Efficiency Alert:
1651    The routine MatSetValuesBlockedStencil() may offer much better efficiency
1652    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1653 
1654    Level: beginner
1655 
1656 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1657           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1658 @*/
1659 PetscErrorCode MatSetValuesStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1660 {
1661   PetscInt       buf[8192],*bufm=NULL,*bufn=NULL,*jdxm,*jdxn;
1662   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1663   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1664 
1665   PetscFunctionBegin;
1666   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1667   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1668   PetscValidType(mat,1);
1669   PetscValidPointer(idxm,3);
1670   PetscValidPointer(idxn,5);
1671 
1672   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1673     jdxm = buf; jdxn = buf+m;
1674   } else {
1675     PetscCall(PetscMalloc2(m,&bufm,n,&bufn));
1676     jdxm = bufm; jdxn = bufn;
1677   }
1678   for (i=0; i<m; i++) {
1679     for (j=0; j<3-sdim; j++) dxm++;
1680     tmp = *dxm++ - starts[0];
1681     for (j=0; j<dim-1; j++) {
1682       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1683       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1684     }
1685     if (mat->stencil.noc) dxm++;
1686     jdxm[i] = tmp;
1687   }
1688   for (i=0; i<n; i++) {
1689     for (j=0; j<3-sdim; j++) dxn++;
1690     tmp = *dxn++ - starts[0];
1691     for (j=0; j<dim-1; j++) {
1692       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1693       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1694     }
1695     if (mat->stencil.noc) dxn++;
1696     jdxn[i] = tmp;
1697   }
1698   PetscCall(MatSetValuesLocal(mat,m,jdxm,n,jdxn,v,addv));
1699   PetscCall(PetscFree2(bufm,bufn));
1700   PetscFunctionReturn(0);
1701 }
1702 
1703 /*@
1704    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1705      Using structured grid indexing
1706 
1707    Not Collective
1708 
1709    Input Parameters:
1710 +  mat - the matrix
1711 .  m - number of rows being entered
1712 .  idxm - grid coordinates for matrix rows being entered
1713 .  n - number of columns being entered
1714 .  idxn - grid coordinates for matrix columns being entered
1715 .  v - a logically two-dimensional array of values
1716 -  addv - either ADD_VALUES or INSERT_VALUES, where
1717    ADD_VALUES adds values to any existing entries, and
1718    INSERT_VALUES replaces existing entries with new values
1719 
1720    Notes:
1721    By default the values, v, are row-oriented and unsorted.
1722    See MatSetOption() for other options.
1723 
1724    Calls to MatSetValuesBlockedStencil() with the INSERT_VALUES and ADD_VALUES
1725    options cannot be mixed without intervening calls to the assembly
1726    routines.
1727 
1728    The grid coordinates are across the entire grid, not just the local portion
1729 
1730    MatSetValuesBlockedStencil() uses 0-based row and column numbers in Fortran
1731    as well as in C.
1732 
1733    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1734 
1735    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1736    or call MatSetBlockSize(), MatSetLocalToGlobalMapping() and MatSetStencil() first.
1737 
1738    The columns and rows in the stencil passed in MUST be contained within the
1739    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1740    if you create a DMDA with an overlap of one grid level and on a particular process its first
1741    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1742    first i index you can use in your column and row indices in MatSetStencil() is 5.
1743 
1744    In Fortran idxm and idxn should be declared as
1745 $     MatStencil idxm(4,m),idxn(4,n)
1746    and the values inserted using
1747 $    idxm(MatStencil_i,1) = i
1748 $    idxm(MatStencil_j,1) = j
1749 $    idxm(MatStencil_k,1) = k
1750    etc
1751 
1752    Negative indices may be passed in idxm and idxn, these rows and columns are
1753    simply ignored. This allows easily inserting element stiffness matrices
1754    with homogeneous Dirchlet boundary conditions that you don't want represented
1755    in the matrix.
1756 
1757    Inspired by the structured grid interface to the HYPRE package
1758    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1759 
1760    Level: beginner
1761 
1762 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1763           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1764           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1765 @*/
1766 PetscErrorCode MatSetValuesBlockedStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1767 {
1768   PetscInt       buf[8192],*bufm=NULL,*bufn=NULL,*jdxm,*jdxn;
1769   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1770   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1771 
1772   PetscFunctionBegin;
1773   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1774   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1775   PetscValidType(mat,1);
1776   PetscValidPointer(idxm,3);
1777   PetscValidPointer(idxn,5);
1778   PetscValidScalarPointer(v,6);
1779 
1780   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1781     jdxm = buf; jdxn = buf+m;
1782   } else {
1783     PetscCall(PetscMalloc2(m,&bufm,n,&bufn));
1784     jdxm = bufm; jdxn = bufn;
1785   }
1786   for (i=0; i<m; i++) {
1787     for (j=0; j<3-sdim; j++) dxm++;
1788     tmp = *dxm++ - starts[0];
1789     for (j=0; j<sdim-1; j++) {
1790       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1791       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1792     }
1793     dxm++;
1794     jdxm[i] = tmp;
1795   }
1796   for (i=0; i<n; i++) {
1797     for (j=0; j<3-sdim; j++) dxn++;
1798     tmp = *dxn++ - starts[0];
1799     for (j=0; j<sdim-1; j++) {
1800       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1801       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1802     }
1803     dxn++;
1804     jdxn[i] = tmp;
1805   }
1806   PetscCall(MatSetValuesBlockedLocal(mat,m,jdxm,n,jdxn,v,addv));
1807   PetscCall(PetscFree2(bufm,bufn));
1808   PetscFunctionReturn(0);
1809 }
1810 
1811 /*@
1812    MatSetStencil - Sets the grid information for setting values into a matrix via
1813         MatSetValuesStencil()
1814 
1815    Not Collective
1816 
1817    Input Parameters:
1818 +  mat - the matrix
1819 .  dim - dimension of the grid 1, 2, or 3
1820 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1821 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1822 -  dof - number of degrees of freedom per node
1823 
1824    Inspired by the structured grid interface to the HYPRE package
1825    (www.llnl.gov/CASC/hyper)
1826 
1827    For matrices generated with DMCreateMatrix() this routine is automatically called and so not needed by the
1828    user.
1829 
1830    Level: beginner
1831 
1832 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1833           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1834 @*/
1835 PetscErrorCode MatSetStencil(Mat mat,PetscInt dim,const PetscInt dims[],const PetscInt starts[],PetscInt dof)
1836 {
1837   PetscFunctionBegin;
1838   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1839   PetscValidIntPointer(dims,3);
1840   PetscValidIntPointer(starts,4);
1841 
1842   mat->stencil.dim = dim + (dof > 1);
1843   for (PetscInt i=0; i<dim; i++) {
1844     mat->stencil.dims[i]   = dims[dim-i-1];      /* copy the values in backwards */
1845     mat->stencil.starts[i] = starts[dim-i-1];
1846   }
1847   mat->stencil.dims[dim]   = dof;
1848   mat->stencil.starts[dim] = 0;
1849   mat->stencil.noc         = (PetscBool)(dof == 1);
1850   PetscFunctionReturn(0);
1851 }
1852 
1853 /*@C
1854    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1855 
1856    Not Collective
1857 
1858    Input Parameters:
1859 +  mat - the matrix
1860 .  v - a logically two-dimensional array of values
1861 .  m, idxm - the number of block rows and their global block indices
1862 .  n, idxn - the number of block columns and their global block indices
1863 -  addv - either ADD_VALUES or INSERT_VALUES, where
1864    ADD_VALUES adds values to any existing entries, and
1865    INSERT_VALUES replaces existing entries with new values
1866 
1867    Notes:
1868    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call
1869    MatXXXXSetPreallocation() or MatSetUp() before using this routine.
1870 
1871    The m and n count the NUMBER of blocks in the row direction and column direction,
1872    NOT the total number of rows/columns; for example, if the block size is 2 and
1873    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1874    The values in idxm would be 1 2; that is the first index for each block divided by
1875    the block size.
1876 
1877    Note that you must call MatSetBlockSize() when constructing this matrix (before
1878    preallocating it).
1879 
1880    By default the values, v, are row-oriented, so the layout of
1881    v is the same as for MatSetValues(). See MatSetOption() for other options.
1882 
1883    Calls to MatSetValuesBlocked() with the INSERT_VALUES and ADD_VALUES
1884    options cannot be mixed without intervening calls to the assembly
1885    routines.
1886 
1887    MatSetValuesBlocked() uses 0-based row and column numbers in Fortran
1888    as well as in C.
1889 
1890    Negative indices may be passed in idxm and idxn, these rows and columns are
1891    simply ignored. This allows easily inserting element stiffness matrices
1892    with homogeneous Dirchlet boundary conditions that you don't want represented
1893    in the matrix.
1894 
1895    Each time an entry is set within a sparse matrix via MatSetValues(),
1896    internal searching must be done to determine where to place the
1897    data in the matrix storage space.  By instead inserting blocks of
1898    entries via MatSetValuesBlocked(), the overhead of matrix assembly is
1899    reduced.
1900 
1901    Example:
1902 $   Suppose m=n=2 and block size(bs) = 2 The array is
1903 $
1904 $   1  2  | 3  4
1905 $   5  6  | 7  8
1906 $   - - - | - - -
1907 $   9  10 | 11 12
1908 $   13 14 | 15 16
1909 $
1910 $   v[] should be passed in like
1911 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1912 $
1913 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1914 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1915 
1916    Level: intermediate
1917 
1918 .seealso: `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1919 @*/
1920 PetscErrorCode MatSetValuesBlocked(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1921 {
1922   PetscFunctionBeginHot;
1923   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1924   PetscValidType(mat,1);
1925   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1926   PetscValidIntPointer(idxm,3);
1927   PetscValidIntPointer(idxn,5);
1928   MatCheckPreallocated(mat,1);
1929   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1930   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1931   if (PetscDefined(USE_DEBUG)) {
1932     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1933     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1934   }
1935   if (PetscDefined(USE_DEBUG)) {
1936     PetscInt rbs,cbs,M,N,i;
1937     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
1938     PetscCall(MatGetSize(mat,&M,&N));
1939     for (i=0; i<m; i++) PetscCheck(idxm[i]*rbs < M,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT,i,idxm[i],M);
1940     for (i=0; i<n; i++) PetscCheck(idxn[i]*cbs < N,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT,i,idxn[i],N);
1941   }
1942   if (mat->assembled) {
1943     mat->was_assembled = PETSC_TRUE;
1944     mat->assembled     = PETSC_FALSE;
1945   }
1946   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
1947   if (mat->ops->setvaluesblocked) {
1948     PetscCall((*mat->ops->setvaluesblocked)(mat,m,idxm,n,idxn,v,addv));
1949   } else {
1950     PetscInt buf[8192],*bufr=NULL,*bufc=NULL,*iidxm,*iidxn;
1951     PetscInt i,j,bs,cbs;
1952 
1953     PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
1954     if (m*bs+n*cbs <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1955       iidxm = buf;
1956       iidxn = buf + m*bs;
1957     } else {
1958       PetscCall(PetscMalloc2(m*bs,&bufr,n*cbs,&bufc));
1959       iidxm = bufr;
1960       iidxn = bufc;
1961     }
1962     for (i=0; i<m; i++) {
1963       for (j=0; j<bs; j++) {
1964         iidxm[i*bs+j] = bs*idxm[i] + j;
1965       }
1966     }
1967     if (m != n || bs != cbs || idxm != idxn) {
1968       for (i=0; i<n; i++) {
1969         for (j=0; j<cbs; j++) {
1970           iidxn[i*cbs+j] = cbs*idxn[i] + j;
1971         }
1972       }
1973     } else iidxn = iidxm;
1974     PetscCall(MatSetValues(mat,m*bs,iidxm,n*cbs,iidxn,v,addv));
1975     PetscCall(PetscFree2(bufr,bufc));
1976   }
1977   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
1978   PetscFunctionReturn(0);
1979 }
1980 
1981 /*@C
1982    MatGetValues - Gets a block of values from a matrix.
1983 
1984    Not Collective; can only return values that are owned by the give process
1985 
1986    Input Parameters:
1987 +  mat - the matrix
1988 .  v - a logically two-dimensional array for storing the values
1989 .  m, idxm - the number of rows and their global indices
1990 -  n, idxn - the number of columns and their global indices
1991 
1992    Notes:
1993      The user must allocate space (m*n PetscScalars) for the values, v.
1994      The values, v, are then returned in a row-oriented format,
1995      analogous to that used by default in MatSetValues().
1996 
1997      MatGetValues() uses 0-based row and column numbers in
1998      Fortran as well as in C.
1999 
2000      MatGetValues() requires that the matrix has been assembled
2001      with MatAssemblyBegin()/MatAssemblyEnd().  Thus, calls to
2002      MatSetValues() and MatGetValues() CANNOT be made in succession
2003      without intermediate matrix assembly.
2004 
2005      Negative row or column indices will be ignored and those locations in v[] will be
2006      left unchanged.
2007 
2008      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2009      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2010      from MatGetOwnershipRange(mat,&rstart,&rend).
2011 
2012    Level: advanced
2013 
2014 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2015 @*/
2016 PetscErrorCode MatGetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
2017 {
2018   PetscFunctionBegin;
2019   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2020   PetscValidType(mat,1);
2021   if (!m || !n) PetscFunctionReturn(0);
2022   PetscValidIntPointer(idxm,3);
2023   PetscValidIntPointer(idxn,5);
2024   PetscValidScalarPointer(v,6);
2025   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2026   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2027   PetscCheck(mat->ops->getvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2028   MatCheckPreallocated(mat,1);
2029 
2030   PetscCall(PetscLogEventBegin(MAT_GetValues,mat,0,0,0));
2031   PetscCall((*mat->ops->getvalues)(mat,m,idxm,n,idxn,v));
2032   PetscCall(PetscLogEventEnd(MAT_GetValues,mat,0,0,0));
2033   PetscFunctionReturn(0);
2034 }
2035 
2036 /*@C
2037    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2038      defined previously by MatSetLocalToGlobalMapping()
2039 
2040    Not Collective
2041 
2042    Input Parameters:
2043 +  mat - the matrix
2044 .  nrow, irow - number of rows and their local indices
2045 -  ncol, icol - number of columns and their local indices
2046 
2047    Output Parameter:
2048 .  y -  a logically two-dimensional array of values
2049 
2050    Notes:
2051      If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine.
2052 
2053      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2054      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from MatGetOwnershipRange(mat,&rstart,&rend). One can
2055      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the ISLocalToGlobalMapping set
2056      with MatSetLocalToGlobalMapping().
2057 
2058    Developer Notes:
2059       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2060       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2061 
2062    Level: advanced
2063 
2064 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2065           `MatSetValuesLocal()`, `MatGetValues()`
2066 @*/
2067 PetscErrorCode MatGetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],PetscScalar y[])
2068 {
2069   PetscFunctionBeginHot;
2070   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2071   PetscValidType(mat,1);
2072   MatCheckPreallocated(mat,1);
2073   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2074   PetscValidIntPointer(irow,3);
2075   PetscValidIntPointer(icol,5);
2076   if (PetscDefined(USE_DEBUG)) {
2077     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2078     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2079   }
2080   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2081   PetscCall(PetscLogEventBegin(MAT_GetValues,mat,0,0,0));
2082   if (mat->ops->getvalueslocal) {
2083     PetscCall((*mat->ops->getvalueslocal)(mat,nrow,irow,ncol,icol,y));
2084   } else {
2085     PetscInt buf[8192],*bufr=NULL,*bufc=NULL,*irowm,*icolm;
2086     if ((nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2087       irowm = buf; icolm = buf+nrow;
2088     } else {
2089       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2090       irowm = bufr; icolm = bufc;
2091     }
2092     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2093     PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2094     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,irowm));
2095     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,icolm));
2096     PetscCall(MatGetValues(mat,nrow,irowm,ncol,icolm,y));
2097     PetscCall(PetscFree2(bufr,bufc));
2098   }
2099   PetscCall(PetscLogEventEnd(MAT_GetValues,mat,0,0,0));
2100   PetscFunctionReturn(0);
2101 }
2102 
2103 /*@
2104   MatSetValuesBatch - Adds (ADD_VALUES) many blocks of values into a matrix at once. The blocks must all be square and
2105   the same size. Currently, this can only be called once and creates the given matrix.
2106 
2107   Not Collective
2108 
2109   Input Parameters:
2110 + mat - the matrix
2111 . nb - the number of blocks
2112 . bs - the number of rows (and columns) in each block
2113 . rows - a concatenation of the rows for each block
2114 - v - a concatenation of logically two-dimensional arrays of values
2115 
2116   Notes:
2117   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2118 
2119   Level: advanced
2120 
2121 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2122           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
2123 @*/
2124 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2125 {
2126   PetscFunctionBegin;
2127   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2128   PetscValidType(mat,1);
2129   PetscValidIntPointer(rows,4);
2130   PetscValidScalarPointer(v,5);
2131   PetscAssert(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2132 
2133   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch,mat,0,0,0));
2134   if (mat->ops->setvaluesbatch) {
2135     PetscCall((*mat->ops->setvaluesbatch)(mat,nb,bs,rows,v));
2136   } else {
2137     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b*bs], bs, &rows[b*bs], &v[b*bs*bs], ADD_VALUES));
2138   }
2139   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch,mat,0,0,0));
2140   PetscFunctionReturn(0);
2141 }
2142 
2143 /*@
2144    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2145    the routine MatSetValuesLocal() to allow users to insert matrix entries
2146    using a local (per-processor) numbering.
2147 
2148    Not Collective
2149 
2150    Input Parameters:
2151 +  x - the matrix
2152 .  rmapping - row mapping created with ISLocalToGlobalMappingCreate() or ISLocalToGlobalMappingCreateIS()
2153 -  cmapping - column mapping
2154 
2155    Level: intermediate
2156 
2157 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2158 @*/
2159 PetscErrorCode MatSetLocalToGlobalMapping(Mat x,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
2160 {
2161   PetscFunctionBegin;
2162   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
2163   PetscValidType(x,1);
2164   if (rmapping) PetscValidHeaderSpecific(rmapping,IS_LTOGM_CLASSID,2);
2165   if (cmapping) PetscValidHeaderSpecific(cmapping,IS_LTOGM_CLASSID,3);
2166   if (x->ops->setlocaltoglobalmapping) {
2167     PetscCall((*x->ops->setlocaltoglobalmapping)(x,rmapping,cmapping));
2168   } else {
2169     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap,rmapping));
2170     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap,cmapping));
2171   }
2172   PetscFunctionReturn(0);
2173 }
2174 
2175 /*@
2176    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by MatSetLocalToGlobalMapping()
2177 
2178    Not Collective
2179 
2180    Input Parameter:
2181 .  A - the matrix
2182 
2183    Output Parameters:
2184 + rmapping - row mapping
2185 - cmapping - column mapping
2186 
2187    Level: advanced
2188 
2189 .seealso: `MatSetValuesLocal()`
2190 @*/
2191 PetscErrorCode MatGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping)
2192 {
2193   PetscFunctionBegin;
2194   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2195   PetscValidType(A,1);
2196   if (rmapping) {
2197     PetscValidPointer(rmapping,2);
2198     *rmapping = A->rmap->mapping;
2199   }
2200   if (cmapping) {
2201     PetscValidPointer(cmapping,3);
2202     *cmapping = A->cmap->mapping;
2203   }
2204   PetscFunctionReturn(0);
2205 }
2206 
2207 /*@
2208    MatSetLayouts - Sets the PetscLayout objects for rows and columns of a matrix
2209 
2210    Logically Collective on A
2211 
2212    Input Parameters:
2213 +  A - the matrix
2214 . rmap - row layout
2215 - cmap - column layout
2216 
2217    Level: advanced
2218 
2219 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2220 @*/
2221 PetscErrorCode MatSetLayouts(Mat A,PetscLayout rmap,PetscLayout cmap)
2222 {
2223   PetscFunctionBegin;
2224   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2225   PetscCall(PetscLayoutReference(rmap,&A->rmap));
2226   PetscCall(PetscLayoutReference(cmap,&A->cmap));
2227   PetscFunctionReturn(0);
2228 }
2229 
2230 /*@
2231    MatGetLayouts - Gets the PetscLayout objects for rows and columns
2232 
2233    Not Collective
2234 
2235    Input Parameter:
2236 .  A - the matrix
2237 
2238    Output Parameters:
2239 + rmap - row layout
2240 - cmap - column layout
2241 
2242    Level: advanced
2243 
2244 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2245 @*/
2246 PetscErrorCode MatGetLayouts(Mat A,PetscLayout *rmap,PetscLayout *cmap)
2247 {
2248   PetscFunctionBegin;
2249   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2250   PetscValidType(A,1);
2251   if (rmap) {
2252     PetscValidPointer(rmap,2);
2253     *rmap = A->rmap;
2254   }
2255   if (cmap) {
2256     PetscValidPointer(cmap,3);
2257     *cmap = A->cmap;
2258   }
2259   PetscFunctionReturn(0);
2260 }
2261 
2262 /*@C
2263    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2264    using a local numbering of the nodes.
2265 
2266    Not Collective
2267 
2268    Input Parameters:
2269 +  mat - the matrix
2270 .  nrow, irow - number of rows and their local indices
2271 .  ncol, icol - number of columns and their local indices
2272 .  y -  a logically two-dimensional array of values
2273 -  addv - either INSERT_VALUES or ADD_VALUES, where
2274    ADD_VALUES adds values to any existing entries, and
2275    INSERT_VALUES replaces existing entries with new values
2276 
2277    Notes:
2278    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2279       MatSetUp() before using this routine
2280 
2281    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine
2282 
2283    Calls to MatSetValuesLocal() with the INSERT_VALUES and ADD_VALUES
2284    options cannot be mixed without intervening calls to the assembly
2285    routines.
2286 
2287    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2288    MUST be called after all calls to MatSetValuesLocal() have been completed.
2289 
2290    Level: intermediate
2291 
2292    Developer Notes:
2293     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2294                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2295 
2296 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2297           `MatSetValueLocal()`, `MatGetValuesLocal()`
2298 @*/
2299 PetscErrorCode MatSetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2300 {
2301   PetscFunctionBeginHot;
2302   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2303   PetscValidType(mat,1);
2304   MatCheckPreallocated(mat,1);
2305   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2306   PetscValidIntPointer(irow,3);
2307   PetscValidIntPointer(icol,5);
2308   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2309   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2310   if (PetscDefined(USE_DEBUG)) {
2311     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2312     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2313   }
2314 
2315   if (mat->assembled) {
2316     mat->was_assembled = PETSC_TRUE;
2317     mat->assembled     = PETSC_FALSE;
2318   }
2319   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
2320   if (mat->ops->setvalueslocal) {
2321     PetscCall((*mat->ops->setvalueslocal)(mat,nrow,irow,ncol,icol,y,addv));
2322   } else {
2323     PetscInt       buf[8192],*bufr=NULL,*bufc=NULL;
2324     const PetscInt *irowm,*icolm;
2325 
2326     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2327       bufr  = buf;
2328       bufc  = buf + nrow;
2329       irowm = bufr;
2330       icolm = bufc;
2331     } else {
2332       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2333       irowm = bufr;
2334       icolm = bufc;
2335     }
2336     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,bufr));
2337     else irowm = irow;
2338     if (mat->cmap->mapping) {
2339       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2340         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,bufc));
2341       } else icolm = irowm;
2342     } else icolm = icol;
2343     PetscCall(MatSetValues(mat,nrow,irowm,ncol,icolm,y,addv));
2344     if (bufr != buf) PetscCall(PetscFree2(bufr,bufc));
2345   }
2346   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
2347   PetscFunctionReturn(0);
2348 }
2349 
2350 /*@C
2351    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2352    using a local ordering of the nodes a block at a time.
2353 
2354    Not Collective
2355 
2356    Input Parameters:
2357 +  x - the matrix
2358 .  nrow, irow - number of rows and their local indices
2359 .  ncol, icol - number of columns and their local indices
2360 .  y -  a logically two-dimensional array of values
2361 -  addv - either INSERT_VALUES or ADD_VALUES, where
2362    ADD_VALUES adds values to any existing entries, and
2363    INSERT_VALUES replaces existing entries with new values
2364 
2365    Notes:
2366    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2367       MatSetUp() before using this routine
2368 
2369    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetBlockSize() and MatSetLocalToGlobalMapping()
2370       before using this routineBefore calling MatSetValuesLocal(), the user must first set the
2371 
2372    Calls to MatSetValuesBlockedLocal() with the INSERT_VALUES and ADD_VALUES
2373    options cannot be mixed without intervening calls to the assembly
2374    routines.
2375 
2376    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2377    MUST be called after all calls to MatSetValuesBlockedLocal() have been completed.
2378 
2379    Level: intermediate
2380 
2381    Developer Notes:
2382     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2383                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2384 
2385 .seealso: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2386           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2387 @*/
2388 PetscErrorCode MatSetValuesBlockedLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2389 {
2390   PetscFunctionBeginHot;
2391   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2392   PetscValidType(mat,1);
2393   MatCheckPreallocated(mat,1);
2394   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2395   PetscValidIntPointer(irow,3);
2396   PetscValidIntPointer(icol,5);
2397   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2398   else PetscCheck(mat->insertmode == addv,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2399   if (PetscDefined(USE_DEBUG)) {
2400     PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2401     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2402   }
2403 
2404   if (mat->assembled) {
2405     mat->was_assembled = PETSC_TRUE;
2406     mat->assembled     = PETSC_FALSE;
2407   }
2408   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2409     PetscInt irbs, rbs;
2410     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2411     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&irbs));
2412     PetscCheck(rbs == irbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT,rbs,irbs);
2413   }
2414   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2415     PetscInt icbs, cbs;
2416     PetscCall(MatGetBlockSizes(mat,NULL,&cbs));
2417     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&icbs));
2418     PetscCheck(cbs == icbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT,cbs,icbs);
2419   }
2420   PetscCall(PetscLogEventBegin(MAT_SetValues,mat,0,0,0));
2421   if (mat->ops->setvaluesblockedlocal) {
2422     PetscCall((*mat->ops->setvaluesblockedlocal)(mat,nrow,irow,ncol,icol,y,addv));
2423   } else {
2424     PetscInt       buf[8192],*bufr=NULL,*bufc=NULL;
2425     const PetscInt *irowm,*icolm;
2426 
2427     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2428       bufr  = buf;
2429       bufc  = buf + nrow;
2430       irowm = bufr;
2431       icolm = bufc;
2432     } else {
2433       PetscCall(PetscMalloc2(nrow,&bufr,ncol,&bufc));
2434       irowm = bufr;
2435       icolm = bufc;
2436     }
2437     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping,nrow,irow,bufr));
2438     else irowm = irow;
2439     if (mat->cmap->mapping) {
2440       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2441         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping,ncol,icol,bufc));
2442       } else icolm = irowm;
2443     } else icolm = icol;
2444     PetscCall(MatSetValuesBlocked(mat,nrow,irowm,ncol,icolm,y,addv));
2445     if (bufr != buf) PetscCall(PetscFree2(bufr,bufc));
2446   }
2447   PetscCall(PetscLogEventEnd(MAT_SetValues,mat,0,0,0));
2448   PetscFunctionReturn(0);
2449 }
2450 
2451 /*@
2452    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2453 
2454    Collective on Mat
2455 
2456    Input Parameters:
2457 +  mat - the matrix
2458 -  x   - the vector to be multiplied
2459 
2460    Output Parameters:
2461 .  y - the result
2462 
2463    Notes:
2464    The vectors x and y cannot be the same.  I.e., one cannot
2465    call MatMult(A,y,y).
2466 
2467    Level: developer
2468 
2469 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2470 @*/
2471 PetscErrorCode MatMultDiagonalBlock(Mat mat,Vec x,Vec y)
2472 {
2473   PetscFunctionBegin;
2474   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2475   PetscValidType(mat,1);
2476   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2477   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2478 
2479   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2480   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2481   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2482   MatCheckPreallocated(mat,1);
2483 
2484   PetscCheck(mat->ops->multdiagonalblock,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply defined",((PetscObject)mat)->type_name);
2485   PetscCall((*mat->ops->multdiagonalblock)(mat,x,y));
2486   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2487   PetscFunctionReturn(0);
2488 }
2489 
2490 /* --------------------------------------------------------*/
2491 /*@
2492    MatMult - Computes the matrix-vector product, y = Ax.
2493 
2494    Neighbor-wise Collective on Mat
2495 
2496    Input Parameters:
2497 +  mat - the matrix
2498 -  x   - the vector to be multiplied
2499 
2500    Output Parameters:
2501 .  y - the result
2502 
2503    Notes:
2504    The vectors x and y cannot be the same.  I.e., one cannot
2505    call MatMult(A,y,y).
2506 
2507    Level: beginner
2508 
2509 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2510 @*/
2511 PetscErrorCode MatMult(Mat mat,Vec x,Vec y)
2512 {
2513   PetscFunctionBegin;
2514   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2515   PetscValidType(mat,1);
2516   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2517   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2518   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2519   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2520   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2521   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
2522   PetscCheck(mat->rmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,y->map->N);
2523   PetscCheck(mat->cmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,x->map->n);
2524   PetscCheck(mat->rmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,y->map->n);
2525   PetscCall(VecSetErrorIfLocked(y,3));
2526   if (mat->erroriffailure) PetscCall(VecValidValues(x,2,PETSC_TRUE));
2527   MatCheckPreallocated(mat,1);
2528 
2529   PetscCall(VecLockReadPush(x));
2530   PetscCheck(mat->ops->mult,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply defined",((PetscObject)mat)->type_name);
2531   PetscCall(PetscLogEventBegin(MAT_Mult,mat,x,y,0));
2532   PetscCall((*mat->ops->mult)(mat,x,y));
2533   PetscCall(PetscLogEventEnd(MAT_Mult,mat,x,y,0));
2534   if (mat->erroriffailure) PetscCall(VecValidValues(y,3,PETSC_FALSE));
2535   PetscCall(VecLockReadPop(x));
2536   PetscFunctionReturn(0);
2537 }
2538 
2539 /*@
2540    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2541 
2542    Neighbor-wise Collective on Mat
2543 
2544    Input Parameters:
2545 +  mat - the matrix
2546 -  x   - the vector to be multiplied
2547 
2548    Output Parameters:
2549 .  y - the result
2550 
2551    Notes:
2552    The vectors x and y cannot be the same.  I.e., one cannot
2553    call MatMultTranspose(A,y,y).
2554 
2555    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2556    use MatMultHermitianTranspose()
2557 
2558    Level: beginner
2559 
2560 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2561 @*/
2562 PetscErrorCode MatMultTranspose(Mat mat,Vec x,Vec y)
2563 {
2564   PetscErrorCode (*op)(Mat,Vec,Vec) = NULL;
2565 
2566   PetscFunctionBegin;
2567   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2568   PetscValidType(mat,1);
2569   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2570   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2571 
2572   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2573   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2574   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2575   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
2576   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
2577   PetscCheck(mat->cmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,y->map->n);
2578   PetscCheck(mat->rmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,x->map->n);
2579   if (mat->erroriffailure) PetscCall(VecValidValues(x,2,PETSC_TRUE));
2580   MatCheckPreallocated(mat,1);
2581 
2582   if (!mat->ops->multtranspose) {
2583     if (mat->symmetric && mat->ops->mult) op = mat->ops->mult;
2584     PetscCheck(op,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined",((PetscObject)mat)->type_name);
2585   } else op = mat->ops->multtranspose;
2586   PetscCall(PetscLogEventBegin(MAT_MultTranspose,mat,x,y,0));
2587   PetscCall(VecLockReadPush(x));
2588   PetscCall((*op)(mat,x,y));
2589   PetscCall(VecLockReadPop(x));
2590   PetscCall(PetscLogEventEnd(MAT_MultTranspose,mat,x,y,0));
2591   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2592   if (mat->erroriffailure) PetscCall(VecValidValues(y,3,PETSC_FALSE));
2593   PetscFunctionReturn(0);
2594 }
2595 
2596 /*@
2597    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2598 
2599    Neighbor-wise Collective on Mat
2600 
2601    Input Parameters:
2602 +  mat - the matrix
2603 -  x   - the vector to be multilplied
2604 
2605    Output Parameters:
2606 .  y - the result
2607 
2608    Notes:
2609    The vectors x and y cannot be the same.  I.e., one cannot
2610    call MatMultHermitianTranspose(A,y,y).
2611 
2612    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2613 
2614    For real numbers MatMultTranspose() and MatMultHermitianTranspose() are identical.
2615 
2616    Level: beginner
2617 
2618 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2619 @*/
2620 PetscErrorCode MatMultHermitianTranspose(Mat mat,Vec x,Vec y)
2621 {
2622   PetscFunctionBegin;
2623   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2624   PetscValidType(mat,1);
2625   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2626   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2627 
2628   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2629   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2630   PetscCheck(x != y,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2631   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
2632   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
2633   PetscCheck(mat->cmap->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->n,y->map->n);
2634   PetscCheck(mat->rmap->n == x->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,x->map->n);
2635   MatCheckPreallocated(mat,1);
2636 
2637   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose,mat,x,y,0));
2638 #if defined(PETSC_USE_COMPLEX)
2639   if (mat->ops->multhermitiantranspose || (mat->hermitian && mat->ops->mult)) {
2640     PetscCall(VecLockReadPush(x));
2641     if (mat->ops->multhermitiantranspose) {
2642       PetscCall((*mat->ops->multhermitiantranspose)(mat,x,y));
2643     } else {
2644       PetscCall((*mat->ops->mult)(mat,x,y));
2645     }
2646     PetscCall(VecLockReadPop(x));
2647   } else {
2648     Vec w;
2649     PetscCall(VecDuplicate(x,&w));
2650     PetscCall(VecCopy(x,w));
2651     PetscCall(VecConjugate(w));
2652     PetscCall(MatMultTranspose(mat,w,y));
2653     PetscCall(VecDestroy(&w));
2654     PetscCall(VecConjugate(y));
2655   }
2656   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2657 #else
2658   PetscCall(MatMultTranspose(mat,x,y));
2659 #endif
2660   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose,mat,x,y,0));
2661   PetscFunctionReturn(0);
2662 }
2663 
2664 /*@
2665     MatMultAdd -  Computes v3 = v2 + A * v1.
2666 
2667     Neighbor-wise Collective on Mat
2668 
2669     Input Parameters:
2670 +   mat - the matrix
2671 -   v1, v2 - the vectors
2672 
2673     Output Parameters:
2674 .   v3 - the result
2675 
2676     Notes:
2677     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2678     call MatMultAdd(A,v1,v2,v1).
2679 
2680     Level: beginner
2681 
2682 .seealso: `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2683 @*/
2684 PetscErrorCode MatMultAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2685 {
2686   PetscFunctionBegin;
2687   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2688   PetscValidType(mat,1);
2689   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2690   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2691   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2692 
2693   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2694   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2695   PetscCheck(mat->cmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v1->map->N);
2696   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2697      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2698   PetscCheck(mat->rmap->n == v3->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,v3->map->n);
2699   PetscCheck(mat->rmap->n == v2->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,v2->map->n);
2700   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2701   MatCheckPreallocated(mat,1);
2702 
2703   PetscCheck(mat->ops->multadd,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No MatMultAdd() for matrix type %s",((PetscObject)mat)->type_name);
2704   PetscCall(PetscLogEventBegin(MAT_MultAdd,mat,v1,v2,v3));
2705   PetscCall(VecLockReadPush(v1));
2706   PetscCall((*mat->ops->multadd)(mat,v1,v2,v3));
2707   PetscCall(VecLockReadPop(v1));
2708   PetscCall(PetscLogEventEnd(MAT_MultAdd,mat,v1,v2,v3));
2709   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2710   PetscFunctionReturn(0);
2711 }
2712 
2713 /*@
2714    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2715 
2716    Neighbor-wise Collective on Mat
2717 
2718    Input Parameters:
2719 +  mat - the matrix
2720 -  v1, v2 - the vectors
2721 
2722    Output Parameters:
2723 .  v3 - the result
2724 
2725    Notes:
2726    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2727    call MatMultTransposeAdd(A,v1,v2,v1).
2728 
2729    Level: beginner
2730 
2731 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2732 @*/
2733 PetscErrorCode MatMultTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2734 {
2735   PetscErrorCode (*op)(Mat,Vec,Vec,Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2736 
2737   PetscFunctionBegin;
2738   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2739   PetscValidType(mat,1);
2740   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2741   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2742   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2743 
2744   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2745   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2746   PetscCheck(mat->rmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v1->map->N);
2747   PetscCheck(mat->cmap->N == v2->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v2->map->N);
2748   PetscCheck(mat->cmap->N == v3->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v3->map->N);
2749   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2750   PetscCheck(op,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2751   MatCheckPreallocated(mat,1);
2752 
2753   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd,mat,v1,v2,v3));
2754   PetscCall(VecLockReadPush(v1));
2755   PetscCall((*op)(mat,v1,v2,v3));
2756   PetscCall(VecLockReadPop(v1));
2757   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd,mat,v1,v2,v3));
2758   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2759   PetscFunctionReturn(0);
2760 }
2761 
2762 /*@
2763    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2764 
2765    Neighbor-wise Collective on Mat
2766 
2767    Input Parameters:
2768 +  mat - the matrix
2769 -  v1, v2 - the vectors
2770 
2771    Output Parameters:
2772 .  v3 - the result
2773 
2774    Notes:
2775    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2776    call MatMultHermitianTransposeAdd(A,v1,v2,v1).
2777 
2778    Level: beginner
2779 
2780 .seealso: `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2781 @*/
2782 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2783 {
2784   PetscFunctionBegin;
2785   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2786   PetscValidType(mat,1);
2787   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2788   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2789   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2790 
2791   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2792   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2793   PetscCheck(v1 != v3,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2794   PetscCheck(mat->rmap->N == v1->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v1->map->N);
2795   PetscCheck(mat->cmap->N == v2->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v2->map->N);
2796   PetscCheck(mat->cmap->N == v3->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,v3->map->N);
2797   MatCheckPreallocated(mat,1);
2798 
2799   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3));
2800   PetscCall(VecLockReadPush(v1));
2801   if (mat->ops->multhermitiantransposeadd) {
2802     PetscCall((*mat->ops->multhermitiantransposeadd)(mat,v1,v2,v3));
2803   } else {
2804     Vec w,z;
2805     PetscCall(VecDuplicate(v1,&w));
2806     PetscCall(VecCopy(v1,w));
2807     PetscCall(VecConjugate(w));
2808     PetscCall(VecDuplicate(v3,&z));
2809     PetscCall(MatMultTranspose(mat,w,z));
2810     PetscCall(VecDestroy(&w));
2811     PetscCall(VecConjugate(z));
2812     if (v2 != v3) {
2813       PetscCall(VecWAXPY(v3,1.0,v2,z));
2814     } else {
2815       PetscCall(VecAXPY(v3,1.0,z));
2816     }
2817     PetscCall(VecDestroy(&z));
2818   }
2819   PetscCall(VecLockReadPop(v1));
2820   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3));
2821   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2822   PetscFunctionReturn(0);
2823 }
2824 
2825 /*@C
2826    MatGetFactorType - gets the type of factorization it is
2827 
2828    Not Collective
2829 
2830    Input Parameters:
2831 .  mat - the matrix
2832 
2833    Output Parameters:
2834 .  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2835 
2836    Level: intermediate
2837 
2838 .seealso: `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`
2839 @*/
2840 PetscErrorCode MatGetFactorType(Mat mat,MatFactorType *t)
2841 {
2842   PetscFunctionBegin;
2843   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2844   PetscValidType(mat,1);
2845   PetscValidPointer(t,2);
2846   *t = mat->factortype;
2847   PetscFunctionReturn(0);
2848 }
2849 
2850 /*@C
2851    MatSetFactorType - sets the type of factorization it is
2852 
2853    Logically Collective on Mat
2854 
2855    Input Parameters:
2856 +  mat - the matrix
2857 -  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2858 
2859    Level: intermediate
2860 
2861 .seealso: `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`
2862 @*/
2863 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2864 {
2865   PetscFunctionBegin;
2866   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2867   PetscValidType(mat,1);
2868   mat->factortype = t;
2869   PetscFunctionReturn(0);
2870 }
2871 
2872 /* ------------------------------------------------------------*/
2873 /*@C
2874    MatGetInfo - Returns information about matrix storage (number of
2875    nonzeros, memory, etc.).
2876 
2877    Collective on Mat if MAT_GLOBAL_MAX or MAT_GLOBAL_SUM is used as the flag
2878 
2879    Input Parameter:
2880 .  mat - the matrix
2881 
2882    Output Parameters:
2883 +  flag - flag indicating the type of parameters to be returned
2884    (MAT_LOCAL - local matrix, MAT_GLOBAL_MAX - maximum over all processors,
2885    MAT_GLOBAL_SUM - sum over all processors)
2886 -  info - matrix information context
2887 
2888    Notes:
2889    The MatInfo context contains a variety of matrix data, including
2890    number of nonzeros allocated and used, number of mallocs during
2891    matrix assembly, etc.  Additional information for factored matrices
2892    is provided (such as the fill ratio, number of mallocs during
2893    factorization, etc.).  Much of this info is printed to PETSC_STDOUT
2894    when using the runtime options
2895 $       -info -mat_view ::ascii_info
2896 
2897    Example for C/C++ Users:
2898    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2899    data within the MatInfo context.  For example,
2900 .vb
2901       MatInfo info;
2902       Mat     A;
2903       double  mal, nz_a, nz_u;
2904 
2905       MatGetInfo(A,MAT_LOCAL,&info);
2906       mal  = info.mallocs;
2907       nz_a = info.nz_allocated;
2908 .ve
2909 
2910    Example for Fortran Users:
2911    Fortran users should declare info as a double precision
2912    array of dimension MAT_INFO_SIZE, and then extract the parameters
2913    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2914    a complete list of parameter names.
2915 .vb
2916       double  precision info(MAT_INFO_SIZE)
2917       double  precision mal, nz_a
2918       Mat     A
2919       integer ierr
2920 
2921       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2922       mal = info(MAT_INFO_MALLOCS)
2923       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2924 .ve
2925 
2926     Level: intermediate
2927 
2928     Developer Note: fortran interface is not autogenerated as the f90
2929     interface definition cannot be generated correctly [due to MatInfo]
2930 
2931 .seealso: `MatStashGetInfo()`
2932 
2933 @*/
2934 PetscErrorCode MatGetInfo(Mat mat,MatInfoType flag,MatInfo *info)
2935 {
2936   PetscFunctionBegin;
2937   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2938   PetscValidType(mat,1);
2939   PetscValidPointer(info,3);
2940   PetscCheck(mat->ops->getinfo,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2941   MatCheckPreallocated(mat,1);
2942   PetscCall((*mat->ops->getinfo)(mat,flag,info));
2943   PetscFunctionReturn(0);
2944 }
2945 
2946 /*
2947    This is used by external packages where it is not easy to get the info from the actual
2948    matrix factorization.
2949 */
2950 PetscErrorCode MatGetInfo_External(Mat A,MatInfoType flag,MatInfo *info)
2951 {
2952   PetscFunctionBegin;
2953   PetscCall(PetscMemzero(info,sizeof(MatInfo)));
2954   PetscFunctionReturn(0);
2955 }
2956 
2957 /* ----------------------------------------------------------*/
2958 
2959 /*@C
2960    MatLUFactor - Performs in-place LU factorization of matrix.
2961 
2962    Collective on Mat
2963 
2964    Input Parameters:
2965 +  mat - the matrix
2966 .  row - row permutation
2967 .  col - column permutation
2968 -  info - options for factorization, includes
2969 $          fill - expected fill as ratio of original fill.
2970 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2971 $                   Run with the option -info to determine an optimal value to use
2972 
2973    Notes:
2974    Most users should employ the simplified KSP interface for linear solvers
2975    instead of working directly with matrix algebra routines such as this.
2976    See, e.g., KSPCreate().
2977 
2978    This changes the state of the matrix to a factored matrix; it cannot be used
2979    for example with MatSetValues() unless one first calls MatSetUnfactored().
2980 
2981    Level: developer
2982 
2983 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2984           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2985 
2986     Developer Note: fortran interface is not autogenerated as the f90
2987     interface definition cannot be generated correctly [due to MatFactorInfo]
2988 
2989 @*/
2990 PetscErrorCode MatLUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
2991 {
2992   MatFactorInfo  tinfo;
2993 
2994   PetscFunctionBegin;
2995   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2996   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
2997   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
2998   if (info) PetscValidPointer(info,4);
2999   PetscValidType(mat,1);
3000   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3001   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3002   PetscCheck(mat->ops->lufactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3003   MatCheckPreallocated(mat,1);
3004   if (!info) {
3005     PetscCall(MatFactorInfoInitialize(&tinfo));
3006     info = &tinfo;
3007   }
3008 
3009   PetscCall(PetscLogEventBegin(MAT_LUFactor,mat,row,col,0));
3010   PetscCall((*mat->ops->lufactor)(mat,row,col,info));
3011   PetscCall(PetscLogEventEnd(MAT_LUFactor,mat,row,col,0));
3012   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3013   PetscFunctionReturn(0);
3014 }
3015 
3016 /*@C
3017    MatILUFactor - Performs in-place ILU factorization of matrix.
3018 
3019    Collective on Mat
3020 
3021    Input Parameters:
3022 +  mat - the matrix
3023 .  row - row permutation
3024 .  col - column permutation
3025 -  info - structure containing
3026 $      levels - number of levels of fill.
3027 $      expected fill - as ratio of original fill.
3028 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3029                 missing diagonal entries)
3030 
3031    Notes:
3032    Probably really in-place only when level of fill is zero, otherwise allocates
3033    new space to store factored matrix and deletes previous memory.
3034 
3035    Most users should employ the simplified KSP interface for linear solvers
3036    instead of working directly with matrix algebra routines such as this.
3037    See, e.g., KSPCreate().
3038 
3039    Level: developer
3040 
3041 .seealso: `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3042 
3043     Developer Note: fortran interface is not autogenerated as the f90
3044     interface definition cannot be generated correctly [due to MatFactorInfo]
3045 
3046 @*/
3047 PetscErrorCode MatILUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
3048 {
3049   PetscFunctionBegin;
3050   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3051   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
3052   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3053   PetscValidPointer(info,4);
3054   PetscValidType(mat,1);
3055   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
3056   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3057   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3058   PetscCheck(mat->ops->ilufactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3059   MatCheckPreallocated(mat,1);
3060 
3061   PetscCall(PetscLogEventBegin(MAT_ILUFactor,mat,row,col,0));
3062   PetscCall((*mat->ops->ilufactor)(mat,row,col,info));
3063   PetscCall(PetscLogEventEnd(MAT_ILUFactor,mat,row,col,0));
3064   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3065   PetscFunctionReturn(0);
3066 }
3067 
3068 /*@C
3069    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3070    Call this routine before calling MatLUFactorNumeric().
3071 
3072    Collective on Mat
3073 
3074    Input Parameters:
3075 +  fact - the factor matrix obtained with MatGetFactor()
3076 .  mat - the matrix
3077 .  row, col - row and column permutations
3078 -  info - options for factorization, includes
3079 $          fill - expected fill as ratio of original fill.
3080 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3081 $                   Run with the option -info to determine an optimal value to use
3082 
3083    Notes:
3084     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
3085 
3086    Most users should employ the simplified KSP interface for linear solvers
3087    instead of working directly with matrix algebra routines such as this.
3088    See, e.g., KSPCreate().
3089 
3090    Level: developer
3091 
3092 .seealso: `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3093 
3094     Developer Note: fortran interface is not autogenerated as the f90
3095     interface definition cannot be generated correctly [due to MatFactorInfo]
3096 
3097 @*/
3098 PetscErrorCode MatLUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
3099 {
3100   MatFactorInfo  tinfo;
3101 
3102   PetscFunctionBegin;
3103   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3104   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
3105   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
3106   if (info) PetscValidPointer(info,5);
3107   PetscValidType(mat,2);
3108   PetscValidPointer(fact,1);
3109   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3110   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3111   if (!(fact)->ops->lufactorsymbolic) {
3112     MatSolverType stype;
3113     PetscCall(MatFactorGetSolverType(fact,&stype));
3114     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic LU using solver package %s",((PetscObject)mat)->type_name,stype);
3115   }
3116   MatCheckPreallocated(mat,2);
3117   if (!info) {
3118     PetscCall(MatFactorInfoInitialize(&tinfo));
3119     info = &tinfo;
3120   }
3121 
3122   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic,mat,row,col,0));
3123   PetscCall((fact->ops->lufactorsymbolic)(fact,mat,row,col,info));
3124   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic,mat,row,col,0));
3125   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3126   PetscFunctionReturn(0);
3127 }
3128 
3129 /*@C
3130    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3131    Call this routine after first calling MatLUFactorSymbolic().
3132 
3133    Collective on Mat
3134 
3135    Input Parameters:
3136 +  fact - the factor matrix obtained with MatGetFactor()
3137 .  mat - the matrix
3138 -  info - options for factorization
3139 
3140    Notes:
3141    See MatLUFactor() for in-place factorization.  See
3142    MatCholeskyFactorNumeric() for the symmetric, positive definite case.
3143 
3144    Most users should employ the simplified KSP interface for linear solvers
3145    instead of working directly with matrix algebra routines such as this.
3146    See, e.g., KSPCreate().
3147 
3148    Level: developer
3149 
3150 .seealso: `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3151 
3152     Developer Note: fortran interface is not autogenerated as the f90
3153     interface definition cannot be generated correctly [due to MatFactorInfo]
3154 
3155 @*/
3156 PetscErrorCode MatLUFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3157 {
3158   MatFactorInfo  tinfo;
3159 
3160   PetscFunctionBegin;
3161   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3162   PetscValidType(mat,2);
3163   PetscValidPointer(fact,1);
3164   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3165   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3166   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3167 
3168   PetscCheck((fact)->ops->lufactornumeric,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric LU",((PetscObject)mat)->type_name);
3169   MatCheckPreallocated(mat,2);
3170   if (!info) {
3171     PetscCall(MatFactorInfoInitialize(&tinfo));
3172     info = &tinfo;
3173   }
3174 
3175   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric,mat,fact,0,0));
3176   else PetscCall(PetscLogEventBegin(MAT_LUFactor,mat,fact,0,0));
3177   PetscCall((fact->ops->lufactornumeric)(fact,mat,info));
3178   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric,mat,fact,0,0));
3179   else PetscCall(PetscLogEventEnd(MAT_LUFactor,mat,fact,0,0));
3180   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3181   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3182   PetscFunctionReturn(0);
3183 }
3184 
3185 /*@C
3186    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3187    symmetric matrix.
3188 
3189    Collective on Mat
3190 
3191    Input Parameters:
3192 +  mat - the matrix
3193 .  perm - row and column permutations
3194 -  f - expected fill as ratio of original fill
3195 
3196    Notes:
3197    See MatLUFactor() for the nonsymmetric case.  See also
3198    MatCholeskyFactorSymbolic(), and MatCholeskyFactorNumeric().
3199 
3200    Most users should employ the simplified KSP interface for linear solvers
3201    instead of working directly with matrix algebra routines such as this.
3202    See, e.g., KSPCreate().
3203 
3204    Level: developer
3205 
3206 .seealso: `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3207           `MatGetOrdering()`
3208 
3209     Developer Note: fortran interface is not autogenerated as the f90
3210     interface definition cannot be generated correctly [due to MatFactorInfo]
3211 
3212 @*/
3213 PetscErrorCode MatCholeskyFactor(Mat mat,IS perm,const MatFactorInfo *info)
3214 {
3215   MatFactorInfo  tinfo;
3216 
3217   PetscFunctionBegin;
3218   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3219   PetscValidType(mat,1);
3220   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,2);
3221   if (info) PetscValidPointer(info,3);
3222   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3223   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3224   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3225   PetscCheck(mat->ops->choleskyfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"In-place factorization for Mat type %s is not supported, try out-of-place factorization. See MatCholeskyFactorSymbolic/Numeric",((PetscObject)mat)->type_name);
3226   MatCheckPreallocated(mat,1);
3227   if (!info) {
3228     PetscCall(MatFactorInfoInitialize(&tinfo));
3229     info = &tinfo;
3230   }
3231 
3232   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor,mat,perm,0,0));
3233   PetscCall((*mat->ops->choleskyfactor)(mat,perm,info));
3234   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor,mat,perm,0,0));
3235   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3236   PetscFunctionReturn(0);
3237 }
3238 
3239 /*@C
3240    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3241    of a symmetric matrix.
3242 
3243    Collective on Mat
3244 
3245    Input Parameters:
3246 +  fact - the factor matrix obtained with MatGetFactor()
3247 .  mat - the matrix
3248 .  perm - row and column permutations
3249 -  info - options for factorization, includes
3250 $          fill - expected fill as ratio of original fill.
3251 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3252 $                   Run with the option -info to determine an optimal value to use
3253 
3254    Notes:
3255    See MatLUFactorSymbolic() for the nonsymmetric case.  See also
3256    MatCholeskyFactor() and MatCholeskyFactorNumeric().
3257 
3258    Most users should employ the simplified KSP interface for linear solvers
3259    instead of working directly with matrix algebra routines such as this.
3260    See, e.g., KSPCreate().
3261 
3262    Level: developer
3263 
3264 .seealso: `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3265           `MatGetOrdering()`
3266 
3267     Developer Note: fortran interface is not autogenerated as the f90
3268     interface definition cannot be generated correctly [due to MatFactorInfo]
3269 
3270 @*/
3271 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
3272 {
3273   MatFactorInfo  tinfo;
3274 
3275   PetscFunctionBegin;
3276   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3277   PetscValidType(mat,2);
3278   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
3279   if (info) PetscValidPointer(info,4);
3280   PetscValidPointer(fact,1);
3281   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3282   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3283   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3284   if (!(fact)->ops->choleskyfactorsymbolic) {
3285     MatSolverType stype;
3286     PetscCall(MatFactorGetSolverType(fact,&stype));
3287     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s symbolic factor Cholesky using solver package %s",((PetscObject)mat)->type_name,stype);
3288   }
3289   MatCheckPreallocated(mat,2);
3290   if (!info) {
3291     PetscCall(MatFactorInfoInitialize(&tinfo));
3292     info = &tinfo;
3293   }
3294 
3295   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic,mat,perm,0,0));
3296   PetscCall((fact->ops->choleskyfactorsymbolic)(fact,mat,perm,info));
3297   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic,mat,perm,0,0));
3298   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3299   PetscFunctionReturn(0);
3300 }
3301 
3302 /*@C
3303    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3304    of a symmetric matrix. Call this routine after first calling
3305    MatCholeskyFactorSymbolic().
3306 
3307    Collective on Mat
3308 
3309    Input Parameters:
3310 +  fact - the factor matrix obtained with MatGetFactor()
3311 .  mat - the initial matrix
3312 .  info - options for factorization
3313 -  fact - the symbolic factor of mat
3314 
3315    Notes:
3316    Most users should employ the simplified KSP interface for linear solvers
3317    instead of working directly with matrix algebra routines such as this.
3318    See, e.g., KSPCreate().
3319 
3320    Level: developer
3321 
3322 .seealso: `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3323 
3324     Developer Note: fortran interface is not autogenerated as the f90
3325     interface definition cannot be generated correctly [due to MatFactorInfo]
3326 
3327 @*/
3328 PetscErrorCode MatCholeskyFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3329 {
3330   MatFactorInfo  tinfo;
3331 
3332   PetscFunctionBegin;
3333   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3334   PetscValidType(mat,2);
3335   PetscValidPointer(fact,1);
3336   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3337   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3338   PetscCheck((fact)->ops->choleskyfactornumeric,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric factor Cholesky",((PetscObject)mat)->type_name);
3339   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3340   MatCheckPreallocated(mat,2);
3341   if (!info) {
3342     PetscCall(MatFactorInfoInitialize(&tinfo));
3343     info = &tinfo;
3344   }
3345 
3346   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric,mat,fact,0,0));
3347   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor,mat,fact,0,0));
3348   PetscCall((fact->ops->choleskyfactornumeric)(fact,mat,info));
3349   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric,mat,fact,0,0));
3350   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor,mat,fact,0,0));
3351   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3352   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3353   PetscFunctionReturn(0);
3354 }
3355 
3356 /*@
3357    MatQRFactor - Performs in-place QR factorization of matrix.
3358 
3359    Collective on Mat
3360 
3361    Input Parameters:
3362 +  mat - the matrix
3363 .  col - column permutation
3364 -  info - options for factorization, includes
3365 $          fill - expected fill as ratio of original fill.
3366 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3367 $                   Run with the option -info to determine an optimal value to use
3368 
3369    Notes:
3370    Most users should employ the simplified KSP interface for linear solvers
3371    instead of working directly with matrix algebra routines such as this.
3372    See, e.g., KSPCreate().
3373 
3374    This changes the state of the matrix to a factored matrix; it cannot be used
3375    for example with MatSetValues() unless one first calls MatSetUnfactored().
3376 
3377    Level: developer
3378 
3379 .seealso: `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3380           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3381 
3382     Developer Note: fortran interface is not autogenerated as the f90
3383     interface definition cannot be generated correctly [due to MatFactorInfo]
3384 
3385 @*/
3386 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3387 {
3388   PetscFunctionBegin;
3389   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3390   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,2);
3391   if (info) PetscValidPointer(info,3);
3392   PetscValidType(mat,1);
3393   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3394   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3395   MatCheckPreallocated(mat,1);
3396   PetscCall(PetscLogEventBegin(MAT_QRFactor,mat,col,0,0));
3397   PetscUseMethod(mat,"MatQRFactor_C", (Mat,IS,const MatFactorInfo*), (mat, col, info));
3398   PetscCall(PetscLogEventEnd(MAT_QRFactor,mat,col,0,0));
3399   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3400   PetscFunctionReturn(0);
3401 }
3402 
3403 /*@
3404    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3405    Call this routine before calling MatQRFactorNumeric().
3406 
3407    Collective on Mat
3408 
3409    Input Parameters:
3410 +  fact - the factor matrix obtained with MatGetFactor()
3411 .  mat - the matrix
3412 .  col - column permutation
3413 -  info - options for factorization, includes
3414 $          fill - expected fill as ratio of original fill.
3415 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3416 $                   Run with the option -info to determine an optimal value to use
3417 
3418    Most users should employ the simplified KSP interface for linear solvers
3419    instead of working directly with matrix algebra routines such as this.
3420    See, e.g., KSPCreate().
3421 
3422    Level: developer
3423 
3424 .seealso: `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3425 
3426     Developer Note: fortran interface is not autogenerated as the f90
3427     interface definition cannot be generated correctly [due to MatFactorInfo]
3428 
3429 @*/
3430 PetscErrorCode MatQRFactorSymbolic(Mat fact,Mat mat,IS col,const MatFactorInfo *info)
3431 {
3432   MatFactorInfo  tinfo;
3433 
3434   PetscFunctionBegin;
3435   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3436   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
3437   if (info) PetscValidPointer(info,4);
3438   PetscValidType(mat,2);
3439   PetscValidPointer(fact,1);
3440   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3441   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3442   MatCheckPreallocated(mat,2);
3443   if (!info) {
3444     PetscCall(MatFactorInfoInitialize(&tinfo));
3445     info = &tinfo;
3446   }
3447 
3448   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic,fact,mat,col,0));
3449   PetscUseMethod(fact,"MatQRFactorSymbolic_C", (Mat,Mat,IS,const MatFactorInfo*), (fact, mat, col, info));
3450   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic,fact,mat,col,0));
3451   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3452   PetscFunctionReturn(0);
3453 }
3454 
3455 /*@
3456    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3457    Call this routine after first calling MatQRFactorSymbolic().
3458 
3459    Collective on Mat
3460 
3461    Input Parameters:
3462 +  fact - the factor matrix obtained with MatGetFactor()
3463 .  mat - the matrix
3464 -  info - options for factorization
3465 
3466    Notes:
3467    See MatQRFactor() for in-place factorization.
3468 
3469    Most users should employ the simplified KSP interface for linear solvers
3470    instead of working directly with matrix algebra routines such as this.
3471    See, e.g., KSPCreate().
3472 
3473    Level: developer
3474 
3475 .seealso: `MatQRFactorSymbolic()`, `MatLUFactor()`
3476 
3477     Developer Note: fortran interface is not autogenerated as the f90
3478     interface definition cannot be generated correctly [due to MatFactorInfo]
3479 
3480 @*/
3481 PetscErrorCode MatQRFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3482 {
3483   MatFactorInfo  tinfo;
3484 
3485   PetscFunctionBegin;
3486   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3487   PetscValidType(mat,2);
3488   PetscValidPointer(fact,1);
3489   PetscValidHeaderSpecific(fact,MAT_CLASSID,1);
3490   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3491   PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3492 
3493   MatCheckPreallocated(mat,2);
3494   if (!info) {
3495     PetscCall(MatFactorInfoInitialize(&tinfo));
3496     info = &tinfo;
3497   }
3498 
3499   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric,mat,fact,0,0));
3500   else  PetscCall(PetscLogEventBegin(MAT_QRFactor,mat,fact,0,0));
3501   PetscUseMethod(fact,"MatQRFactorNumeric_C", (Mat,Mat,const MatFactorInfo*), (fact, mat, info));
3502   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric,mat,fact,0,0));
3503   else PetscCall(PetscLogEventEnd(MAT_QRFactor,mat,fact,0,0));
3504   PetscCall(MatViewFromOptions(fact,NULL,"-mat_factor_view"));
3505   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3506   PetscFunctionReturn(0);
3507 }
3508 
3509 /* ----------------------------------------------------------------*/
3510 /*@
3511    MatSolve - Solves A x = b, given a factored matrix.
3512 
3513    Neighbor-wise Collective on Mat
3514 
3515    Input Parameters:
3516 +  mat - the factored matrix
3517 -  b - the right-hand-side vector
3518 
3519    Output Parameter:
3520 .  x - the result vector
3521 
3522    Notes:
3523    The vectors b and x cannot be the same.  I.e., one cannot
3524    call MatSolve(A,x,x).
3525 
3526    Notes:
3527    Most users should employ the simplified KSP interface for linear solvers
3528    instead of working directly with matrix algebra routines such as this.
3529    See, e.g., KSPCreate().
3530 
3531    Level: developer
3532 
3533 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3534 @*/
3535 PetscErrorCode MatSolve(Mat mat,Vec b,Vec x)
3536 {
3537   PetscFunctionBegin;
3538   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3539   PetscValidType(mat,1);
3540   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3541   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3542   PetscCheckSameComm(mat,1,b,2);
3543   PetscCheckSameComm(mat,1,x,3);
3544   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3545   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3546   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3547   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3548   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3549   MatCheckPreallocated(mat,1);
3550 
3551   PetscCall(PetscLogEventBegin(MAT_Solve,mat,b,x,0));
3552   if (mat->factorerrortype) {
3553     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
3554     PetscCall(VecSetInf(x));
3555   } else {
3556     PetscCheck(mat->ops->solve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3557     PetscCall((*mat->ops->solve)(mat,b,x));
3558   }
3559   PetscCall(PetscLogEventEnd(MAT_Solve,mat,b,x,0));
3560   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3561   PetscFunctionReturn(0);
3562 }
3563 
3564 static PetscErrorCode MatMatSolve_Basic(Mat A,Mat B,Mat X,PetscBool trans)
3565 {
3566   Vec            b,x;
3567   PetscInt       N,i;
3568   PetscErrorCode (*f)(Mat,Vec,Vec);
3569   PetscBool      Abound,Bneedconv = PETSC_FALSE,Xneedconv = PETSC_FALSE;
3570 
3571   PetscFunctionBegin;
3572   if (A->factorerrortype) {
3573     PetscCall(PetscInfo(A,"MatFactorError %d\n",A->factorerrortype));
3574     PetscCall(MatSetInf(X));
3575     PetscFunctionReturn(0);
3576   }
3577   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3578   PetscCheck(f,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
3579   PetscCall(MatBoundToCPU(A,&Abound));
3580   if (!Abound) {
3581     PetscCall(PetscObjectTypeCompareAny((PetscObject)B,&Bneedconv,MATSEQDENSE,MATMPIDENSE,""));
3582     PetscCall(PetscObjectTypeCompareAny((PetscObject)X,&Xneedconv,MATSEQDENSE,MATMPIDENSE,""));
3583   }
3584   if (Bneedconv) {
3585     PetscCall(MatConvert(B,MATDENSECUDA,MAT_INPLACE_MATRIX,&B));
3586   }
3587   if (Xneedconv) {
3588     PetscCall(MatConvert(X,MATDENSECUDA,MAT_INPLACE_MATRIX,&X));
3589   }
3590   PetscCall(MatGetSize(B,NULL,&N));
3591   for (i=0; i<N; i++) {
3592     PetscCall(MatDenseGetColumnVecRead(B,i,&b));
3593     PetscCall(MatDenseGetColumnVecWrite(X,i,&x));
3594     PetscCall((*f)(A,b,x));
3595     PetscCall(MatDenseRestoreColumnVecWrite(X,i,&x));
3596     PetscCall(MatDenseRestoreColumnVecRead(B,i,&b));
3597   }
3598   if (Bneedconv) {
3599     PetscCall(MatConvert(B,MATDENSE,MAT_INPLACE_MATRIX,&B));
3600   }
3601   if (Xneedconv) {
3602     PetscCall(MatConvert(X,MATDENSE,MAT_INPLACE_MATRIX,&X));
3603   }
3604   PetscFunctionReturn(0);
3605 }
3606 
3607 /*@
3608    MatMatSolve - Solves A X = B, given a factored matrix.
3609 
3610    Neighbor-wise Collective on Mat
3611 
3612    Input Parameters:
3613 +  A - the factored matrix
3614 -  B - the right-hand-side matrix MATDENSE (or sparse -- when using MUMPS)
3615 
3616    Output Parameter:
3617 .  X - the result matrix (dense matrix)
3618 
3619    Notes:
3620    If B is a MATDENSE matrix then one can call MatMatSolve(A,B,B) except with MKL_CPARDISO;
3621    otherwise, B and X cannot be the same.
3622 
3623    Notes:
3624    Most users should usually employ the simplified KSP interface for linear solvers
3625    instead of working directly with matrix algebra routines such as this.
3626    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3627    at a time.
3628 
3629    Level: developer
3630 
3631 .seealso: `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3632 @*/
3633 PetscErrorCode MatMatSolve(Mat A,Mat B,Mat X)
3634 {
3635   PetscFunctionBegin;
3636   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3637   PetscValidType(A,1);
3638   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3639   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3640   PetscCheckSameComm(A,1,B,2);
3641   PetscCheckSameComm(A,1,X,3);
3642   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3643   PetscCheck(A->rmap->N == B->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N);
3644   PetscCheck(X->cmap->N == B->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as rhs matrix");
3645   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3646   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3647   MatCheckPreallocated(A,1);
3648 
3649   PetscCall(PetscLogEventBegin(MAT_MatSolve,A,B,X,0));
3650   if (!A->ops->matsolve) {
3651     PetscCall(PetscInfo(A,"Mat type %s using basic MatMatSolve\n",((PetscObject)A)->type_name));
3652     PetscCall(MatMatSolve_Basic(A,B,X,PETSC_FALSE));
3653   } else {
3654     PetscCall((*A->ops->matsolve)(A,B,X));
3655   }
3656   PetscCall(PetscLogEventEnd(MAT_MatSolve,A,B,X,0));
3657   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3658   PetscFunctionReturn(0);
3659 }
3660 
3661 /*@
3662    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3663 
3664    Neighbor-wise Collective on Mat
3665 
3666    Input Parameters:
3667 +  A - the factored matrix
3668 -  B - the right-hand-side matrix  (dense matrix)
3669 
3670    Output Parameter:
3671 .  X - the result matrix (dense matrix)
3672 
3673    Notes:
3674    The matrices B and X cannot be the same.  I.e., one cannot
3675    call MatMatSolveTranspose(A,X,X).
3676 
3677    Notes:
3678    Most users should usually employ the simplified KSP interface for linear solvers
3679    instead of working directly with matrix algebra routines such as this.
3680    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3681    at a time.
3682 
3683    When using SuperLU_Dist or MUMPS as a parallel solver, PETSc will use their functionality to solve multiple right hand sides simultaneously.
3684 
3685    Level: developer
3686 
3687 .seealso: `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3688 @*/
3689 PetscErrorCode MatMatSolveTranspose(Mat A,Mat B,Mat X)
3690 {
3691   PetscFunctionBegin;
3692   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3693   PetscValidType(A,1);
3694   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3695   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3696   PetscCheckSameComm(A,1,B,2);
3697   PetscCheckSameComm(A,1,X,3);
3698   PetscCheck(X != B,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3699   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3700   PetscCheck(A->rmap->N == B->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N);
3701   PetscCheck(A->rmap->n == B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->n,B->rmap->n);
3702   PetscCheck(X->cmap->N >= B->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as rhs matrix");
3703   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3704   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3705   MatCheckPreallocated(A,1);
3706 
3707   PetscCall(PetscLogEventBegin(MAT_MatSolve,A,B,X,0));
3708   if (!A->ops->matsolvetranspose) {
3709     PetscCall(PetscInfo(A,"Mat type %s using basic MatMatSolveTranspose\n",((PetscObject)A)->type_name));
3710     PetscCall(MatMatSolve_Basic(A,B,X,PETSC_TRUE));
3711   } else {
3712     PetscCall((*A->ops->matsolvetranspose)(A,B,X));
3713   }
3714   PetscCall(PetscLogEventEnd(MAT_MatSolve,A,B,X,0));
3715   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3716   PetscFunctionReturn(0);
3717 }
3718 
3719 /*@
3720    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3721 
3722    Neighbor-wise Collective on Mat
3723 
3724    Input Parameters:
3725 +  A - the factored matrix
3726 -  Bt - the transpose of right-hand-side matrix
3727 
3728    Output Parameter:
3729 .  X - the result matrix (dense matrix)
3730 
3731    Notes:
3732    Most users should usually employ the simplified KSP interface for linear solvers
3733    instead of working directly with matrix algebra routines such as this.
3734    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3735    at a time.
3736 
3737    For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row format on the host processor and call MatMatTransposeSolve() to implement MUMPS' MatMatSolve().
3738 
3739    Level: developer
3740 
3741 .seealso: `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3742 @*/
3743 PetscErrorCode MatMatTransposeSolve(Mat A,Mat Bt,Mat X)
3744 {
3745   PetscFunctionBegin;
3746   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3747   PetscValidType(A,1);
3748   PetscValidHeaderSpecific(Bt,MAT_CLASSID,2);
3749   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3750   PetscCheckSameComm(A,1,Bt,2);
3751   PetscCheckSameComm(A,1,X,3);
3752 
3753   PetscCheck(X != Bt,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3754   PetscCheck(A->cmap->N == X->rmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->cmap->N,X->rmap->N);
3755   PetscCheck(A->rmap->N == Bt->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,Bt->cmap->N);
3756   PetscCheck(X->cmap->N >= Bt->rmap->N,PetscObjectComm((PetscObject)X),PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as row number of the rhs matrix");
3757   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3758   PetscCheck(A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3759   MatCheckPreallocated(A,1);
3760 
3761   PetscCheck(A->ops->mattransposesolve,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
3762   PetscCall(PetscLogEventBegin(MAT_MatTrSolve,A,Bt,X,0));
3763   PetscCall((*A->ops->mattransposesolve)(A,Bt,X));
3764   PetscCall(PetscLogEventEnd(MAT_MatTrSolve,A,Bt,X,0));
3765   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3766   PetscFunctionReturn(0);
3767 }
3768 
3769 /*@
3770    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3771                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3772 
3773    Neighbor-wise Collective on Mat
3774 
3775    Input Parameters:
3776 +  mat - the factored matrix
3777 -  b - the right-hand-side vector
3778 
3779    Output Parameter:
3780 .  x - the result vector
3781 
3782    Notes:
3783    MatSolve() should be used for most applications, as it performs
3784    a forward solve followed by a backward solve.
3785 
3786    The vectors b and x cannot be the same,  i.e., one cannot
3787    call MatForwardSolve(A,x,x).
3788 
3789    For matrix in seqsbaij format with block size larger than 1,
3790    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3791    MatForwardSolve() solves U^T*D y = b, and
3792    MatBackwardSolve() solves U x = y.
3793    Thus they do not provide a symmetric preconditioner.
3794 
3795    Most users should employ the simplified KSP interface for linear solvers
3796    instead of working directly with matrix algebra routines such as this.
3797    See, e.g., KSPCreate().
3798 
3799    Level: developer
3800 
3801 .seealso: `MatSolve()`, `MatBackwardSolve()`
3802 @*/
3803 PetscErrorCode MatForwardSolve(Mat mat,Vec b,Vec x)
3804 {
3805   PetscFunctionBegin;
3806   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3807   PetscValidType(mat,1);
3808   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3809   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3810   PetscCheckSameComm(mat,1,b,2);
3811   PetscCheckSameComm(mat,1,x,3);
3812   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3813   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3814   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3815   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3816   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3817   MatCheckPreallocated(mat,1);
3818 
3819   PetscCheck(mat->ops->forwardsolve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3820   PetscCall(PetscLogEventBegin(MAT_ForwardSolve,mat,b,x,0));
3821   PetscCall((*mat->ops->forwardsolve)(mat,b,x));
3822   PetscCall(PetscLogEventEnd(MAT_ForwardSolve,mat,b,x,0));
3823   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3824   PetscFunctionReturn(0);
3825 }
3826 
3827 /*@
3828    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3829                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3830 
3831    Neighbor-wise Collective on Mat
3832 
3833    Input Parameters:
3834 +  mat - the factored matrix
3835 -  b - the right-hand-side vector
3836 
3837    Output Parameter:
3838 .  x - the result vector
3839 
3840    Notes:
3841    MatSolve() should be used for most applications, as it performs
3842    a forward solve followed by a backward solve.
3843 
3844    The vectors b and x cannot be the same.  I.e., one cannot
3845    call MatBackwardSolve(A,x,x).
3846 
3847    For matrix in seqsbaij format with block size larger than 1,
3848    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3849    MatForwardSolve() solves U^T*D y = b, and
3850    MatBackwardSolve() solves U x = y.
3851    Thus they do not provide a symmetric preconditioner.
3852 
3853    Most users should employ the simplified KSP interface for linear solvers
3854    instead of working directly with matrix algebra routines such as this.
3855    See, e.g., KSPCreate().
3856 
3857    Level: developer
3858 
3859 .seealso: `MatSolve()`, `MatForwardSolve()`
3860 @*/
3861 PetscErrorCode MatBackwardSolve(Mat mat,Vec b,Vec x)
3862 {
3863   PetscFunctionBegin;
3864   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3865   PetscValidType(mat,1);
3866   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3867   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3868   PetscCheckSameComm(mat,1,b,2);
3869   PetscCheckSameComm(mat,1,x,3);
3870   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3871   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3872   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3873   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3874   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3875   MatCheckPreallocated(mat,1);
3876 
3877   PetscCheck(mat->ops->backwardsolve,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3878   PetscCall(PetscLogEventBegin(MAT_BackwardSolve,mat,b,x,0));
3879   PetscCall((*mat->ops->backwardsolve)(mat,b,x));
3880   PetscCall(PetscLogEventEnd(MAT_BackwardSolve,mat,b,x,0));
3881   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3882   PetscFunctionReturn(0);
3883 }
3884 
3885 /*@
3886    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3887 
3888    Neighbor-wise Collective on Mat
3889 
3890    Input Parameters:
3891 +  mat - the factored matrix
3892 .  b - the right-hand-side vector
3893 -  y - the vector to be added to
3894 
3895    Output Parameter:
3896 .  x - the result vector
3897 
3898    Notes:
3899    The vectors b and x cannot be the same.  I.e., one cannot
3900    call MatSolveAdd(A,x,y,x).
3901 
3902    Most users should employ the simplified KSP interface for linear solvers
3903    instead of working directly with matrix algebra routines such as this.
3904    See, e.g., KSPCreate().
3905 
3906    Level: developer
3907 
3908 .seealso: `MatSolve()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3909 @*/
3910 PetscErrorCode MatSolveAdd(Mat mat,Vec b,Vec y,Vec x)
3911 {
3912   PetscScalar    one = 1.0;
3913   Vec            tmp;
3914 
3915   PetscFunctionBegin;
3916   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3917   PetscValidType(mat,1);
3918   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3919   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3920   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
3921   PetscCheckSameComm(mat,1,b,2);
3922   PetscCheckSameComm(mat,1,y,3);
3923   PetscCheckSameComm(mat,1,x,4);
3924   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3925   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
3926   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
3927   PetscCheck(mat->rmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,y->map->N);
3928   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
3929   PetscCheck(x->map->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,x->map->n,y->map->n);
3930   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3931    MatCheckPreallocated(mat,1);
3932 
3933   PetscCall(PetscLogEventBegin(MAT_SolveAdd,mat,b,x,y));
3934   if (mat->factorerrortype) {
3935 
3936     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
3937     PetscCall(VecSetInf(x));
3938   } else if (mat->ops->solveadd) {
3939     PetscCall((*mat->ops->solveadd)(mat,b,y,x));
3940   } else {
3941     /* do the solve then the add manually */
3942     if (x != y) {
3943       PetscCall(MatSolve(mat,b,x));
3944       PetscCall(VecAXPY(x,one,y));
3945     } else {
3946       PetscCall(VecDuplicate(x,&tmp));
3947       PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp));
3948       PetscCall(VecCopy(x,tmp));
3949       PetscCall(MatSolve(mat,b,x));
3950       PetscCall(VecAXPY(x,one,tmp));
3951       PetscCall(VecDestroy(&tmp));
3952     }
3953   }
3954   PetscCall(PetscLogEventEnd(MAT_SolveAdd,mat,b,x,y));
3955   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3956   PetscFunctionReturn(0);
3957 }
3958 
3959 /*@
3960    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3961 
3962    Neighbor-wise Collective on Mat
3963 
3964    Input Parameters:
3965 +  mat - the factored matrix
3966 -  b - the right-hand-side vector
3967 
3968    Output Parameter:
3969 .  x - the result vector
3970 
3971    Notes:
3972    The vectors b and x cannot be the same.  I.e., one cannot
3973    call MatSolveTranspose(A,x,x).
3974 
3975    Most users should employ the simplified KSP interface for linear solvers
3976    instead of working directly with matrix algebra routines such as this.
3977    See, e.g., KSPCreate().
3978 
3979    Level: developer
3980 
3981 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3982 @*/
3983 PetscErrorCode MatSolveTranspose(Mat mat,Vec b,Vec x)
3984 {
3985   PetscErrorCode (*f)(Mat,Vec,Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3986 
3987   PetscFunctionBegin;
3988   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3989   PetscValidType(mat,1);
3990   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3991   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3992   PetscCheckSameComm(mat,1,b,2);
3993   PetscCheckSameComm(mat,1,x,3);
3994   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3995   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
3996   PetscCheck(mat->cmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,b->map->N);
3997   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3998   MatCheckPreallocated(mat,1);
3999   PetscCall(PetscLogEventBegin(MAT_SolveTranspose,mat,b,x,0));
4000   if (mat->factorerrortype) {
4001     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
4002     PetscCall(VecSetInf(x));
4003   } else {
4004     PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s",((PetscObject)mat)->type_name);
4005     PetscCall((*f)(mat,b,x));
4006   }
4007   PetscCall(PetscLogEventEnd(MAT_SolveTranspose,mat,b,x,0));
4008   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4009   PetscFunctionReturn(0);
4010 }
4011 
4012 /*@
4013    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4014                       factored matrix.
4015 
4016    Neighbor-wise Collective on Mat
4017 
4018    Input Parameters:
4019 +  mat - the factored matrix
4020 .  b - the right-hand-side vector
4021 -  y - the vector to be added to
4022 
4023    Output Parameter:
4024 .  x - the result vector
4025 
4026    Notes:
4027    The vectors b and x cannot be the same.  I.e., one cannot
4028    call MatSolveTransposeAdd(A,x,y,x).
4029 
4030    Most users should employ the simplified KSP interface for linear solvers
4031    instead of working directly with matrix algebra routines such as this.
4032    See, e.g., KSPCreate().
4033 
4034    Level: developer
4035 
4036 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4037 @*/
4038 PetscErrorCode MatSolveTransposeAdd(Mat mat,Vec b,Vec y,Vec x)
4039 {
4040   PetscScalar    one = 1.0;
4041   Vec            tmp;
4042   PetscErrorCode (*f)(Mat,Vec,Vec,Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4043 
4044   PetscFunctionBegin;
4045   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4046   PetscValidType(mat,1);
4047   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
4048   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4049   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
4050   PetscCheckSameComm(mat,1,b,2);
4051   PetscCheckSameComm(mat,1,y,3);
4052   PetscCheckSameComm(mat,1,x,4);
4053   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
4054   PetscCheck(mat->rmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,x->map->N);
4055   PetscCheck(mat->cmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,b->map->N);
4056   PetscCheck(mat->cmap->N == y->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,y->map->N);
4057   PetscCheck(x->map->n == y->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT,x->map->n,y->map->n);
4058   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4059   MatCheckPreallocated(mat,1);
4060 
4061   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd,mat,b,x,y));
4062   if (mat->factorerrortype) {
4063     PetscCall(PetscInfo(mat,"MatFactorError %d\n",mat->factorerrortype));
4064     PetscCall(VecSetInf(x));
4065   } else if (f) {
4066     PetscCall((*f)(mat,b,y,x));
4067   } else {
4068     /* do the solve then the add manually */
4069     if (x != y) {
4070       PetscCall(MatSolveTranspose(mat,b,x));
4071       PetscCall(VecAXPY(x,one,y));
4072     } else {
4073       PetscCall(VecDuplicate(x,&tmp));
4074       PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp));
4075       PetscCall(VecCopy(x,tmp));
4076       PetscCall(MatSolveTranspose(mat,b,x));
4077       PetscCall(VecAXPY(x,one,tmp));
4078       PetscCall(VecDestroy(&tmp));
4079     }
4080   }
4081   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd,mat,b,x,y));
4082   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4083   PetscFunctionReturn(0);
4084 }
4085 /* ----------------------------------------------------------------*/
4086 
4087 /*@
4088    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4089 
4090    Neighbor-wise Collective on Mat
4091 
4092    Input Parameters:
4093 +  mat - the matrix
4094 .  b - the right hand side
4095 .  omega - the relaxation factor
4096 .  flag - flag indicating the type of SOR (see below)
4097 .  shift -  diagonal shift
4098 .  its - the number of iterations
4099 -  lits - the number of local iterations
4100 
4101    Output Parameter:
4102 .  x - the solution (can contain an initial guess, use option SOR_ZERO_INITIAL_GUESS to indicate no guess)
4103 
4104    SOR Flags:
4105 +     SOR_FORWARD_SWEEP - forward SOR
4106 .     SOR_BACKWARD_SWEEP - backward SOR
4107 .     SOR_SYMMETRIC_SWEEP - SSOR (symmetric SOR)
4108 .     SOR_LOCAL_FORWARD_SWEEP - local forward SOR
4109 .     SOR_LOCAL_BACKWARD_SWEEP - local forward SOR
4110 .     SOR_LOCAL_SYMMETRIC_SWEEP - local SSOR
4111 .     SOR_APPLY_UPPER, SOR_APPLY_LOWER - applies
4112          upper/lower triangular part of matrix to
4113          vector (with omega)
4114 -     SOR_ZERO_INITIAL_GUESS - zero initial guess
4115 
4116    Notes:
4117    SOR_LOCAL_FORWARD_SWEEP, SOR_LOCAL_BACKWARD_SWEEP, and
4118    SOR_LOCAL_SYMMETRIC_SWEEP perform separate independent smoothings
4119    on each processor.
4120 
4121    Application programmers will not generally use MatSOR() directly,
4122    but instead will employ the KSP/PC interface.
4123 
4124    Notes:
4125     for BAIJ, SBAIJ, and AIJ matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4126 
4127    Notes for Advanced Users:
4128    The flags are implemented as bitwise inclusive or operations.
4129    For example, use (SOR_ZERO_INITIAL_GUESS | SOR_SYMMETRIC_SWEEP)
4130    to specify a zero initial guess for SSOR.
4131 
4132    Most users should employ the simplified KSP interface for linear solvers
4133    instead of working directly with matrix algebra routines such as this.
4134    See, e.g., KSPCreate().
4135 
4136    Vectors x and b CANNOT be the same
4137 
4138    Developer Note: We should add block SOR support for AIJ matrices with block size set to great than one and no inodes
4139 
4140    Level: developer
4141 
4142 @*/
4143 PetscErrorCode MatSOR(Mat mat,Vec b,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec x)
4144 {
4145   PetscFunctionBegin;
4146   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4147   PetscValidType(mat,1);
4148   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
4149   PetscValidHeaderSpecific(x,VEC_CLASSID,8);
4150   PetscCheckSameComm(mat,1,b,2);
4151   PetscCheckSameComm(mat,1,x,8);
4152   PetscCheck(mat->ops->sor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4153   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4154   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4155   PetscCheck(mat->cmap->N == x->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->cmap->N,x->map->N);
4156   PetscCheck(mat->rmap->N == b->map->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,b->map->N);
4157   PetscCheck(mat->rmap->n == b->map->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->n,b->map->n);
4158   PetscCheck(its > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %" PetscInt_FMT " positive",its);
4159   PetscCheck(lits > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires local its %" PetscInt_FMT " positive",lits);
4160   PetscCheck(b != x,PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"b and x vector cannot be the same");
4161 
4162   MatCheckPreallocated(mat,1);
4163   PetscCall(PetscLogEventBegin(MAT_SOR,mat,b,x,0));
4164   PetscCall((*mat->ops->sor)(mat,b,omega,flag,shift,its,lits,x));
4165   PetscCall(PetscLogEventEnd(MAT_SOR,mat,b,x,0));
4166   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4167   PetscFunctionReturn(0);
4168 }
4169 
4170 /*
4171       Default matrix copy routine.
4172 */
4173 PetscErrorCode MatCopy_Basic(Mat A,Mat B,MatStructure str)
4174 {
4175   PetscInt          i,rstart = 0,rend = 0,nz;
4176   const PetscInt    *cwork;
4177   const PetscScalar *vwork;
4178 
4179   PetscFunctionBegin;
4180   if (B->assembled) PetscCall(MatZeroEntries(B));
4181   if (str == SAME_NONZERO_PATTERN) {
4182     PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
4183     for (i=rstart; i<rend; i++) {
4184       PetscCall(MatGetRow(A,i,&nz,&cwork,&vwork));
4185       PetscCall(MatSetValues(B,1,&i,nz,cwork,vwork,INSERT_VALUES));
4186       PetscCall(MatRestoreRow(A,i,&nz,&cwork,&vwork));
4187     }
4188   } else {
4189     PetscCall(MatAYPX(B,0.0,A,str));
4190   }
4191   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
4192   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
4193   PetscFunctionReturn(0);
4194 }
4195 
4196 /*@
4197    MatCopy - Copies a matrix to another matrix.
4198 
4199    Collective on Mat
4200 
4201    Input Parameters:
4202 +  A - the matrix
4203 -  str - SAME_NONZERO_PATTERN or DIFFERENT_NONZERO_PATTERN
4204 
4205    Output Parameter:
4206 .  B - where the copy is put
4207 
4208    Notes:
4209    If you use SAME_NONZERO_PATTERN then the two matrices must have the same nonzero pattern or the routine will crash.
4210 
4211    MatCopy() copies the matrix entries of a matrix to another existing
4212    matrix (after first zeroing the second matrix).  A related routine is
4213    MatConvert(), which first creates a new matrix and then copies the data.
4214 
4215    Level: intermediate
4216 
4217 .seealso: `MatConvert()`, `MatDuplicate()`
4218 @*/
4219 PetscErrorCode MatCopy(Mat A,Mat B,MatStructure str)
4220 {
4221   PetscInt       i;
4222 
4223   PetscFunctionBegin;
4224   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4225   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4226   PetscValidType(A,1);
4227   PetscValidType(B,2);
4228   PetscCheckSameComm(A,1,B,2);
4229   MatCheckPreallocated(B,2);
4230   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4231   PetscCheck(!A->factortype,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4232   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")",A->rmap->N,B->rmap->N,A->cmap->N,B->cmap->N);
4233   MatCheckPreallocated(A,1);
4234   if (A == B) PetscFunctionReturn(0);
4235 
4236   PetscCall(PetscLogEventBegin(MAT_Copy,A,B,0,0));
4237   if (A->ops->copy) {
4238     PetscCall((*A->ops->copy)(A,B,str));
4239   } else { /* generic conversion */
4240     PetscCall(MatCopy_Basic(A,B,str));
4241   }
4242 
4243   B->stencil.dim = A->stencil.dim;
4244   B->stencil.noc = A->stencil.noc;
4245   for (i=0; i<=A->stencil.dim; i++) {
4246     B->stencil.dims[i]   = A->stencil.dims[i];
4247     B->stencil.starts[i] = A->stencil.starts[i];
4248   }
4249 
4250   PetscCall(PetscLogEventEnd(MAT_Copy,A,B,0,0));
4251   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4252   PetscFunctionReturn(0);
4253 }
4254 
4255 /*@C
4256    MatConvert - Converts a matrix to another matrix, either of the same
4257    or different type.
4258 
4259    Collective on Mat
4260 
4261    Input Parameters:
4262 +  mat - the matrix
4263 .  newtype - new matrix type.  Use MATSAME to create a new matrix of the
4264    same type as the original matrix.
4265 -  reuse - denotes if the destination matrix is to be created or reused.
4266    Use MAT_INPLACE_MATRIX for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use
4267    MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX (can only be used after the first call was made with MAT_INITIAL_MATRIX, causes the matrix space in M to be reused).
4268 
4269    Output Parameter:
4270 .  M - pointer to place new matrix
4271 
4272    Notes:
4273    MatConvert() first creates a new matrix and then copies the data from
4274    the first matrix.  A related routine is MatCopy(), which copies the matrix
4275    entries of one matrix to another already existing matrix context.
4276 
4277    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4278    the MPI communicator of the generated matrix is always the same as the communicator
4279    of the input matrix.
4280 
4281    Level: intermediate
4282 
4283 .seealso: `MatCopy()`, `MatDuplicate()`
4284 @*/
4285 PetscErrorCode MatConvert(Mat mat,MatType newtype,MatReuse reuse,Mat *M)
4286 {
4287   PetscBool      sametype,issame,flg,issymmetric,ishermitian;
4288   char           convname[256],mtype[256];
4289   Mat            B;
4290 
4291   PetscFunctionBegin;
4292   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4293   PetscValidType(mat,1);
4294   PetscValidPointer(M,4);
4295   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4296   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4297   MatCheckPreallocated(mat,1);
4298 
4299   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matconvert_type",mtype,sizeof(mtype),&flg));
4300   if (flg) newtype = mtype;
4301 
4302   PetscCall(PetscObjectTypeCompare((PetscObject)mat,newtype,&sametype));
4303   PetscCall(PetscStrcmp(newtype,"same",&issame));
4304   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M),PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires same input and output matrix");
4305   PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M),PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4306 
4307   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4308     PetscCall(PetscInfo(mat,"Early return for inplace %s %d %d\n",((PetscObject)mat)->type_name,sametype,issame));
4309     PetscFunctionReturn(0);
4310   }
4311 
4312   /* Cache Mat options because some converter use MatHeaderReplace  */
4313   issymmetric = mat->symmetric;
4314   ishermitian = mat->hermitian;
4315 
4316   if ((sametype || issame) && (reuse==MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4317     PetscCall(PetscInfo(mat,"Calling duplicate for initial matrix %s %d %d\n",((PetscObject)mat)->type_name,sametype,issame));
4318     PetscCall((*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M));
4319   } else {
4320     PetscErrorCode (*conv)(Mat, MatType,MatReuse,Mat*)=NULL;
4321     const char     *prefix[3] = {"seq","mpi",""};
4322     PetscInt       i;
4323     /*
4324        Order of precedence:
4325        0) See if newtype is a superclass of the current matrix.
4326        1) See if a specialized converter is known to the current matrix.
4327        2) See if a specialized converter is known to the desired matrix class.
4328        3) See if a good general converter is registered for the desired class
4329           (as of 6/27/03 only MATMPIADJ falls into this category).
4330        4) See if a good general converter is known for the current matrix.
4331        5) Use a really basic converter.
4332     */
4333 
4334     /* 0) See if newtype is a superclass of the current matrix.
4335           i.e mat is mpiaij and newtype is aij */
4336     for (i=0; i<2; i++) {
4337       PetscCall(PetscStrncpy(convname,prefix[i],sizeof(convname)));
4338       PetscCall(PetscStrlcat(convname,newtype,sizeof(convname)));
4339       PetscCall(PetscStrcmp(convname,((PetscObject)mat)->type_name,&flg));
4340       PetscCall(PetscInfo(mat,"Check superclass %s %s -> %d\n",convname,((PetscObject)mat)->type_name,flg));
4341       if (flg) {
4342         if (reuse == MAT_INPLACE_MATRIX) {
4343           PetscCall(PetscInfo(mat,"Early return\n"));
4344           PetscFunctionReturn(0);
4345         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4346           PetscCall(PetscInfo(mat,"Calling MatDuplicate\n"));
4347           PetscCall((*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M));
4348           PetscFunctionReturn(0);
4349         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4350           PetscCall(PetscInfo(mat,"Calling MatCopy\n"));
4351           PetscCall(MatCopy(mat,*M,SAME_NONZERO_PATTERN));
4352           PetscFunctionReturn(0);
4353         }
4354       }
4355     }
4356     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4357     for (i=0; i<3; i++) {
4358       PetscCall(PetscStrncpy(convname,"MatConvert_",sizeof(convname)));
4359       PetscCall(PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname)));
4360       PetscCall(PetscStrlcat(convname,"_",sizeof(convname)));
4361       PetscCall(PetscStrlcat(convname,prefix[i],sizeof(convname)));
4362       PetscCall(PetscStrlcat(convname,issame ? ((PetscObject)mat)->type_name : newtype,sizeof(convname)));
4363       PetscCall(PetscStrlcat(convname,"_C",sizeof(convname)));
4364       PetscCall(PetscObjectQueryFunction((PetscObject)mat,convname,&conv));
4365       PetscCall(PetscInfo(mat,"Check specialized (1) %s (%s) -> %d\n",convname,((PetscObject)mat)->type_name,!!conv));
4366       if (conv) goto foundconv;
4367     }
4368 
4369     /* 2)  See if a specialized converter is known to the desired matrix class. */
4370     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&B));
4371     PetscCall(MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
4372     PetscCall(MatSetType(B,newtype));
4373     for (i=0; i<3; i++) {
4374       PetscCall(PetscStrncpy(convname,"MatConvert_",sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname,"_",sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname,prefix[i],sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname,newtype,sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname,"_C",sizeof(convname)));
4380       PetscCall(PetscObjectQueryFunction((PetscObject)B,convname,&conv));
4381       PetscCall(PetscInfo(mat,"Check specialized (2) %s (%s) -> %d\n",convname,((PetscObject)B)->type_name,!!conv));
4382       if (conv) {
4383         PetscCall(MatDestroy(&B));
4384         goto foundconv;
4385       }
4386     }
4387 
4388     /* 3) See if a good general converter is registered for the desired class */
4389     conv = B->ops->convertfrom;
4390     PetscCall(PetscInfo(mat,"Check convertfrom (%s) -> %d\n",((PetscObject)B)->type_name,!!conv));
4391     PetscCall(MatDestroy(&B));
4392     if (conv) goto foundconv;
4393 
4394     /* 4) See if a good general converter is known for the current matrix */
4395     if (mat->ops->convert) conv = mat->ops->convert;
4396     PetscCall(PetscInfo(mat,"Check general convert (%s) -> %d\n",((PetscObject)mat)->type_name,!!conv));
4397     if (conv) goto foundconv;
4398 
4399     /* 5) Use a really basic converter. */
4400     PetscCall(PetscInfo(mat,"Using MatConvert_Basic\n"));
4401     conv = MatConvert_Basic;
4402 
4403 foundconv:
4404     PetscCall(PetscLogEventBegin(MAT_Convert,mat,0,0,0));
4405     PetscCall((*conv)(mat,newtype,reuse,M));
4406     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4407       /* the block sizes must be same if the mappings are copied over */
4408       (*M)->rmap->bs = mat->rmap->bs;
4409       (*M)->cmap->bs = mat->cmap->bs;
4410       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4411       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4412       (*M)->rmap->mapping = mat->rmap->mapping;
4413       (*M)->cmap->mapping = mat->cmap->mapping;
4414     }
4415     (*M)->stencil.dim = mat->stencil.dim;
4416     (*M)->stencil.noc = mat->stencil.noc;
4417     for (i=0; i<=mat->stencil.dim; i++) {
4418       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4419       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4420     }
4421     PetscCall(PetscLogEventEnd(MAT_Convert,mat,0,0,0));
4422   }
4423   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4424 
4425   /* Copy Mat options */
4426   if (issymmetric) PetscCall(MatSetOption(*M,MAT_SYMMETRIC,PETSC_TRUE));
4427   if (ishermitian) PetscCall(MatSetOption(*M,MAT_HERMITIAN,PETSC_TRUE));
4428   PetscFunctionReturn(0);
4429 }
4430 
4431 /*@C
4432    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4433 
4434    Not Collective
4435 
4436    Input Parameter:
4437 .  mat - the matrix, must be a factored matrix
4438 
4439    Output Parameter:
4440 .   type - the string name of the package (do not free this string)
4441 
4442    Notes:
4443       In Fortran you pass in a empty string and the package name will be copied into it.
4444     (Make sure the string is long enough)
4445 
4446    Level: intermediate
4447 
4448 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4449 @*/
4450 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4451 {
4452   PetscErrorCode (*conv)(Mat,MatSolverType*);
4453 
4454   PetscFunctionBegin;
4455   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4456   PetscValidType(mat,1);
4457   PetscValidPointer(type,2);
4458   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
4459   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorGetSolverType_C",&conv));
4460   if (conv) PetscCall((*conv)(mat,type));
4461   else *type = MATSOLVERPETSC;
4462   PetscFunctionReturn(0);
4463 }
4464 
4465 typedef struct _MatSolverTypeForSpecifcType* MatSolverTypeForSpecifcType;
4466 struct _MatSolverTypeForSpecifcType {
4467   MatType                        mtype;
4468   /* no entry for MAT_FACTOR_NONE */
4469   PetscErrorCode                 (*createfactor[MAT_FACTOR_NUM_TYPES-1])(Mat,MatFactorType,Mat*);
4470   MatSolverTypeForSpecifcType next;
4471 };
4472 
4473 typedef struct _MatSolverTypeHolder* MatSolverTypeHolder;
4474 struct _MatSolverTypeHolder {
4475   char                        *name;
4476   MatSolverTypeForSpecifcType handlers;
4477   MatSolverTypeHolder         next;
4478 };
4479 
4480 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4481 
4482 /*@C
4483    MatSolverTypeRegister - Registers a MatSolverType that works for a particular matrix type
4484 
4485    Input Parameters:
4486 +    package - name of the package, for example petsc or superlu
4487 .    mtype - the matrix type that works with this package
4488 .    ftype - the type of factorization supported by the package
4489 -    createfactor - routine that will create the factored matrix ready to be used
4490 
4491     Level: intermediate
4492 
4493 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4494 @*/
4495 PetscErrorCode MatSolverTypeRegister(MatSolverType package,MatType mtype,MatFactorType ftype,PetscErrorCode (*createfactor)(Mat,MatFactorType,Mat*))
4496 {
4497   MatSolverTypeHolder         next = MatSolverTypeHolders,prev = NULL;
4498   PetscBool                   flg;
4499   MatSolverTypeForSpecifcType inext,iprev = NULL;
4500 
4501   PetscFunctionBegin;
4502   PetscCall(MatInitializePackage());
4503   if (!next) {
4504     PetscCall(PetscNew(&MatSolverTypeHolders));
4505     PetscCall(PetscStrallocpy(package,&MatSolverTypeHolders->name));
4506     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4507     PetscCall(PetscStrallocpy(mtype,(char **)&MatSolverTypeHolders->handlers->mtype));
4508     MatSolverTypeHolders->handlers->createfactor[(int)ftype-1] = createfactor;
4509     PetscFunctionReturn(0);
4510   }
4511   while (next) {
4512     PetscCall(PetscStrcasecmp(package,next->name,&flg));
4513     if (flg) {
4514       PetscCheck(next->handlers,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatSolverTypeHolder is missing handlers");
4515       inext = next->handlers;
4516       while (inext) {
4517         PetscCall(PetscStrcasecmp(mtype,inext->mtype,&flg));
4518         if (flg) {
4519           inext->createfactor[(int)ftype-1] = createfactor;
4520           PetscFunctionReturn(0);
4521         }
4522         iprev = inext;
4523         inext = inext->next;
4524       }
4525       PetscCall(PetscNew(&iprev->next));
4526       PetscCall(PetscStrallocpy(mtype,(char **)&iprev->next->mtype));
4527       iprev->next->createfactor[(int)ftype-1] = createfactor;
4528       PetscFunctionReturn(0);
4529     }
4530     prev = next;
4531     next = next->next;
4532   }
4533   PetscCall(PetscNew(&prev->next));
4534   PetscCall(PetscStrallocpy(package,&prev->next->name));
4535   PetscCall(PetscNew(&prev->next->handlers));
4536   PetscCall(PetscStrallocpy(mtype,(char **)&prev->next->handlers->mtype));
4537   prev->next->handlers->createfactor[(int)ftype-1] = createfactor;
4538   PetscFunctionReturn(0);
4539 }
4540 
4541 /*@C
4542    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4543 
4544    Input Parameters:
4545 +    type - name of the package, for example petsc or superlu
4546 .    ftype - the type of factorization supported by the type
4547 -    mtype - the matrix type that works with this type
4548 
4549    Output Parameters:
4550 +   foundtype - PETSC_TRUE if the type was registered
4551 .   foundmtype - PETSC_TRUE if the type supports the requested mtype
4552 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4553 
4554     Level: intermediate
4555 
4556 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4557 @*/
4558 PetscErrorCode MatSolverTypeGet(MatSolverType type,MatType mtype,MatFactorType ftype,PetscBool *foundtype,PetscBool *foundmtype,PetscErrorCode (**createfactor)(Mat,MatFactorType,Mat*))
4559 {
4560   MatSolverTypeHolder         next = MatSolverTypeHolders;
4561   PetscBool                   flg;
4562   MatSolverTypeForSpecifcType inext;
4563 
4564   PetscFunctionBegin;
4565   if (foundtype) *foundtype = PETSC_FALSE;
4566   if (foundmtype) *foundmtype = PETSC_FALSE;
4567   if (createfactor) *createfactor = NULL;
4568 
4569   if (type) {
4570     while (next) {
4571       PetscCall(PetscStrcasecmp(type,next->name,&flg));
4572       if (flg) {
4573         if (foundtype) *foundtype = PETSC_TRUE;
4574         inext = next->handlers;
4575         while (inext) {
4576           PetscCall(PetscStrbeginswith(mtype,inext->mtype,&flg));
4577           if (flg) {
4578             if (foundmtype) *foundmtype = PETSC_TRUE;
4579             if (createfactor)  *createfactor  = inext->createfactor[(int)ftype-1];
4580             PetscFunctionReturn(0);
4581           }
4582           inext = inext->next;
4583         }
4584       }
4585       next = next->next;
4586     }
4587   } else {
4588     while (next) {
4589       inext = next->handlers;
4590       while (inext) {
4591         PetscCall(PetscStrcmp(mtype,inext->mtype,&flg));
4592         if (flg && inext->createfactor[(int)ftype-1]) {
4593           if (foundtype) *foundtype = PETSC_TRUE;
4594           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4595           if (createfactor) *createfactor = inext->createfactor[(int)ftype-1];
4596           PetscFunctionReturn(0);
4597         }
4598         inext = inext->next;
4599       }
4600       next = next->next;
4601     }
4602     /* try with base classes inext->mtype */
4603     next = MatSolverTypeHolders;
4604     while (next) {
4605       inext = next->handlers;
4606       while (inext) {
4607         PetscCall(PetscStrbeginswith(mtype,inext->mtype,&flg));
4608         if (flg && inext->createfactor[(int)ftype-1]) {
4609           if (foundtype) *foundtype = PETSC_TRUE;
4610           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4611           if (createfactor) *createfactor = inext->createfactor[(int)ftype-1];
4612           PetscFunctionReturn(0);
4613         }
4614         inext = inext->next;
4615       }
4616       next = next->next;
4617     }
4618   }
4619   PetscFunctionReturn(0);
4620 }
4621 
4622 PetscErrorCode MatSolverTypeDestroy(void)
4623 {
4624   MatSolverTypeHolder         next = MatSolverTypeHolders,prev;
4625   MatSolverTypeForSpecifcType inext,iprev;
4626 
4627   PetscFunctionBegin;
4628   while (next) {
4629     PetscCall(PetscFree(next->name));
4630     inext = next->handlers;
4631     while (inext) {
4632       PetscCall(PetscFree(inext->mtype));
4633       iprev = inext;
4634       inext = inext->next;
4635       PetscCall(PetscFree(iprev));
4636     }
4637     prev = next;
4638     next = next->next;
4639     PetscCall(PetscFree(prev));
4640   }
4641   MatSolverTypeHolders = NULL;
4642   PetscFunctionReturn(0);
4643 }
4644 
4645 /*@C
4646    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in MatLUFactorSymbolic(), MatCholeskyFactorSymbolic()
4647 
4648    Logically Collective on Mat
4649 
4650    Input Parameters:
4651 .  mat - the matrix
4652 
4653    Output Parameters:
4654 .  flg - PETSC_TRUE if uses the ordering
4655 
4656    Notes:
4657       Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4658       packages do not, thus we want to skip generating the ordering when it is not needed or used.
4659 
4660    Level: developer
4661 
4662 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4663 @*/
4664 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4665 {
4666   PetscFunctionBegin;
4667   *flg = mat->canuseordering;
4668   PetscFunctionReturn(0);
4669 }
4670 
4671 /*@C
4672    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4673 
4674    Logically Collective on Mat
4675 
4676    Input Parameters:
4677 .  mat - the matrix
4678 
4679    Output Parameters:
4680 .  otype - the preferred type
4681 
4682    Level: developer
4683 
4684 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4685 @*/
4686 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4687 {
4688   PetscFunctionBegin;
4689   *otype = mat->preferredordering[ftype];
4690   PetscCheck(*otype,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatFactor did not have a preferred ordering");
4691   PetscFunctionReturn(0);
4692 }
4693 
4694 /*@C
4695    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4696 
4697    Collective on Mat
4698 
4699    Input Parameters:
4700 +  mat - the matrix
4701 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4702 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4703 
4704    Output Parameters:
4705 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4706 
4707    Options Database Key:
4708 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4709                                   One can choose host to save device memory). Currently only supported with SEQAIJCUSPARSE matrices.
4710 
4711    Notes:
4712       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4713      such as pastix, superlu, mumps etc.
4714 
4715       PETSc must have been ./configure to use the external solver, using the option --download-package
4716 
4717       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4718       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4719       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4720 
4721    Developer Notes:
4722       This should actually be called MatCreateFactor() since it creates a new factor object
4723 
4724    Level: intermediate
4725 
4726 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`
4727 @*/
4728 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type,MatFactorType ftype,Mat *f)
4729 {
4730   PetscBool      foundtype,foundmtype;
4731   PetscErrorCode (*conv)(Mat,MatFactorType,Mat*);
4732 
4733   PetscFunctionBegin;
4734   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4735   PetscValidType(mat,1);
4736 
4737   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4738   MatCheckPreallocated(mat,1);
4739 
4740   PetscCall(MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,&foundtype,&foundmtype,&conv));
4741   if (!foundtype) {
4742     if (type) {
4743       SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s",type,MatFactorTypes[ftype],((PetscObject)mat)->type_name,type);
4744     } else {
4745       SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"Could not locate a solver type for factorization type %s and matrix type %s.",MatFactorTypes[ftype],((PetscObject)mat)->type_name);
4746     }
4747   }
4748   PetscCheck(foundmtype,PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"MatSolverType %s does not support matrix type %s",type,((PetscObject)mat)->type_name);
4749   PetscCheck(conv,PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"MatSolverType %s does not support factorization type %s for matrix type %s",type,MatFactorTypes[ftype],((PetscObject)mat)->type_name);
4750 
4751   PetscCall((*conv)(mat,ftype,f));
4752   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f,mat->factorprefix));
4753   PetscFunctionReturn(0);
4754 }
4755 
4756 /*@C
4757    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4758 
4759    Not Collective
4760 
4761    Input Parameters:
4762 +  mat - the matrix
4763 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4764 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4765 
4766    Output Parameter:
4767 .    flg - PETSC_TRUE if the factorization is available
4768 
4769    Notes:
4770       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4771      such as pastix, superlu, mumps etc.
4772 
4773       PETSc must have been ./configure to use the external solver, using the option --download-package
4774 
4775    Developer Notes:
4776       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4777 
4778    Level: intermediate
4779 
4780 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`
4781 @*/
4782 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type,MatFactorType ftype,PetscBool  *flg)
4783 {
4784   PetscErrorCode (*gconv)(Mat,MatFactorType,Mat*);
4785 
4786   PetscFunctionBegin;
4787   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4788   PetscValidType(mat,1);
4789   PetscValidBoolPointer(flg,4);
4790 
4791   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4792   MatCheckPreallocated(mat,1);
4793 
4794   PetscCall(MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,NULL,NULL,&gconv));
4795   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4796   PetscFunctionReturn(0);
4797 }
4798 
4799 /*@
4800    MatDuplicate - Duplicates a matrix including the non-zero structure.
4801 
4802    Collective on Mat
4803 
4804    Input Parameters:
4805 +  mat - the matrix
4806 -  op - One of MAT_DO_NOT_COPY_VALUES, MAT_COPY_VALUES, or MAT_SHARE_NONZERO_PATTERN.
4807         See the manual page for MatDuplicateOption for an explanation of these options.
4808 
4809    Output Parameter:
4810 .  M - pointer to place new matrix
4811 
4812    Level: intermediate
4813 
4814    Notes:
4815     You cannot change the nonzero pattern for the parent or child matrix if you use MAT_SHARE_NONZERO_PATTERN.
4816     May be called with an unassembled input Mat if MAT_DO_NOT_COPY_VALUES is used, in which case the output Mat is unassembled as well.
4817     When original mat is a product of matrix operation, e.g., an output of MatMatMult() or MatCreateSubMatrix(), only the simple matrix data structure of mat is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. User should not use MatDuplicate() to create new matrix M if M is intended to be reused as the product of matrix operation.
4818 
4819 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4820 @*/
4821 PetscErrorCode MatDuplicate(Mat mat,MatDuplicateOption op,Mat *M)
4822 {
4823   Mat            B;
4824   VecType        vtype;
4825   PetscInt       i;
4826   PetscObject    dm;
4827   void           (*viewf)(void);
4828 
4829   PetscFunctionBegin;
4830   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4831   PetscValidType(mat,1);
4832   PetscValidPointer(M,3);
4833   PetscCheck(op != MAT_COPY_VALUES || mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MAT_COPY_VALUES not allowed for unassembled matrix");
4834   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4835   MatCheckPreallocated(mat,1);
4836 
4837   *M = NULL;
4838   PetscCheck(mat->ops->duplicate,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not written for matrix type %s",((PetscObject)mat)->type_name);
4839   PetscCall(PetscLogEventBegin(MAT_Convert,mat,0,0,0));
4840   PetscCall((*mat->ops->duplicate)(mat,op,M));
4841   PetscCall(PetscLogEventEnd(MAT_Convert,mat,0,0,0));
4842   B    = *M;
4843 
4844   PetscCall(MatGetOperation(mat,MATOP_VIEW,&viewf));
4845   if (viewf) PetscCall(MatSetOperation(B,MATOP_VIEW,viewf));
4846   PetscCall(MatGetVecType(mat,&vtype));
4847   PetscCall(MatSetVecType(B,vtype));
4848 
4849   B->stencil.dim = mat->stencil.dim;
4850   B->stencil.noc = mat->stencil.noc;
4851   for (i=0; i<=mat->stencil.dim; i++) {
4852     B->stencil.dims[i]   = mat->stencil.dims[i];
4853     B->stencil.starts[i] = mat->stencil.starts[i];
4854   }
4855 
4856   B->nooffproczerorows = mat->nooffproczerorows;
4857   B->nooffprocentries  = mat->nooffprocentries;
4858 
4859   PetscCall(PetscObjectQuery((PetscObject) mat, "__PETSc_dm", &dm));
4860   if (dm) {
4861     PetscCall(PetscObjectCompose((PetscObject) B, "__PETSc_dm", dm));
4862   }
4863   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4864   PetscFunctionReturn(0);
4865 }
4866 
4867 /*@
4868    MatGetDiagonal - Gets the diagonal of a matrix.
4869 
4870    Logically Collective on Mat
4871 
4872    Input Parameters:
4873 +  mat - the matrix
4874 -  v - the vector for storing the diagonal
4875 
4876    Output Parameter:
4877 .  v - the diagonal of the matrix
4878 
4879    Level: intermediate
4880 
4881    Note:
4882    Currently only correct in parallel for square matrices.
4883 
4884 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4885 @*/
4886 PetscErrorCode MatGetDiagonal(Mat mat,Vec v)
4887 {
4888   PetscFunctionBegin;
4889   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4890   PetscValidType(mat,1);
4891   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4892   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4893   PetscCheck(mat->ops->getdiagonal,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4894   MatCheckPreallocated(mat,1);
4895 
4896   PetscCall((*mat->ops->getdiagonal)(mat,v));
4897   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4898   PetscFunctionReturn(0);
4899 }
4900 
4901 /*@C
4902    MatGetRowMin - Gets the minimum value (of the real part) of each
4903         row of the matrix
4904 
4905    Logically Collective on Mat
4906 
4907    Input Parameter:
4908 .  mat - the matrix
4909 
4910    Output Parameters:
4911 +  v - the vector for storing the maximums
4912 -  idx - the indices of the column found for each row (optional)
4913 
4914    Level: intermediate
4915 
4916    Notes:
4917     The result of this call are the same as if one converted the matrix to dense format
4918       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4919 
4920     This code is only implemented for a couple of matrix formats.
4921 
4922 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`,
4923           `MatGetRowMax()`
4924 @*/
4925 PetscErrorCode MatGetRowMin(Mat mat,Vec v,PetscInt idx[])
4926 {
4927   PetscFunctionBegin;
4928   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4929   PetscValidType(mat,1);
4930   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4931   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4932 
4933   if (!mat->cmap->N) {
4934     PetscCall(VecSet(v,PETSC_MAX_REAL));
4935     if (idx) {
4936       PetscInt i,m = mat->rmap->n;
4937       for (i=0; i<m; i++) idx[i] = -1;
4938     }
4939   } else {
4940     PetscCheck(mat->ops->getrowmin,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4941     MatCheckPreallocated(mat,1);
4942   }
4943   PetscCall((*mat->ops->getrowmin)(mat,v,idx));
4944   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4945   PetscFunctionReturn(0);
4946 }
4947 
4948 /*@C
4949    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4950         row of the matrix
4951 
4952    Logically Collective on Mat
4953 
4954    Input Parameter:
4955 .  mat - the matrix
4956 
4957    Output Parameters:
4958 +  v - the vector for storing the minimums
4959 -  idx - the indices of the column found for each row (or NULL if not needed)
4960 
4961    Level: intermediate
4962 
4963    Notes:
4964     if a row is completely empty or has only 0.0 values then the idx[] value for that
4965     row is 0 (the first column).
4966 
4967     This code is only implemented for a couple of matrix formats.
4968 
4969 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4970 @*/
4971 PetscErrorCode MatGetRowMinAbs(Mat mat,Vec v,PetscInt idx[])
4972 {
4973   PetscFunctionBegin;
4974   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4975   PetscValidType(mat,1);
4976   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4977   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4978   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4979 
4980   if (!mat->cmap->N) {
4981     PetscCall(VecSet(v,0.0));
4982     if (idx) {
4983       PetscInt i,m = mat->rmap->n;
4984       for (i=0; i<m; i++) idx[i] = -1;
4985     }
4986   } else {
4987     PetscCheck(mat->ops->getrowminabs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4988     MatCheckPreallocated(mat,1);
4989     if (idx) PetscCall(PetscArrayzero(idx,mat->rmap->n));
4990     PetscCall((*mat->ops->getrowminabs)(mat,v,idx));
4991   }
4992   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4993   PetscFunctionReturn(0);
4994 }
4995 
4996 /*@C
4997    MatGetRowMax - Gets the maximum value (of the real part) of each
4998         row of the matrix
4999 
5000    Logically Collective on Mat
5001 
5002    Input Parameter:
5003 .  mat - the matrix
5004 
5005    Output Parameters:
5006 +  v - the vector for storing the maximums
5007 -  idx - the indices of the column found for each row (optional)
5008 
5009    Level: intermediate
5010 
5011    Notes:
5012     The result of this call are the same as if one converted the matrix to dense format
5013       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5014 
5015     This code is only implemented for a couple of matrix formats.
5016 
5017 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5018 @*/
5019 PetscErrorCode MatGetRowMax(Mat mat,Vec v,PetscInt idx[])
5020 {
5021   PetscFunctionBegin;
5022   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5023   PetscValidType(mat,1);
5024   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5025   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5026 
5027   if (!mat->cmap->N) {
5028     PetscCall(VecSet(v,PETSC_MIN_REAL));
5029     if (idx) {
5030       PetscInt i,m = mat->rmap->n;
5031       for (i=0; i<m; i++) idx[i] = -1;
5032     }
5033   } else {
5034     PetscCheck(mat->ops->getrowmax,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5035     MatCheckPreallocated(mat,1);
5036     PetscCall((*mat->ops->getrowmax)(mat,v,idx));
5037   }
5038   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5039   PetscFunctionReturn(0);
5040 }
5041 
5042 /*@C
5043    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5044         row of the matrix
5045 
5046    Logically Collective on Mat
5047 
5048    Input Parameter:
5049 .  mat - the matrix
5050 
5051    Output Parameters:
5052 +  v - the vector for storing the maximums
5053 -  idx - the indices of the column found for each row (or NULL if not needed)
5054 
5055    Level: intermediate
5056 
5057    Notes:
5058     if a row is completely empty or has only 0.0 values then the idx[] value for that
5059     row is 0 (the first column).
5060 
5061     This code is only implemented for a couple of matrix formats.
5062 
5063 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`
5064 @*/
5065 PetscErrorCode MatGetRowMaxAbs(Mat mat,Vec v,PetscInt idx[])
5066 {
5067   PetscFunctionBegin;
5068   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5069   PetscValidType(mat,1);
5070   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5071   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5072 
5073   if (!mat->cmap->N) {
5074     PetscCall(VecSet(v,0.0));
5075     if (idx) {
5076       PetscInt i,m = mat->rmap->n;
5077       for (i=0; i<m; i++) idx[i] = -1;
5078     }
5079   } else {
5080     PetscCheck(mat->ops->getrowmaxabs,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5081     MatCheckPreallocated(mat,1);
5082     if (idx) PetscCall(PetscArrayzero(idx,mat->rmap->n));
5083     PetscCall((*mat->ops->getrowmaxabs)(mat,v,idx));
5084   }
5085   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5086   PetscFunctionReturn(0);
5087 }
5088 
5089 /*@
5090    MatGetRowSum - Gets the sum of each row of the matrix
5091 
5092    Logically or Neighborhood Collective on Mat
5093 
5094    Input Parameters:
5095 .  mat - the matrix
5096 
5097    Output Parameter:
5098 .  v - the vector for storing the sum of rows
5099 
5100    Level: intermediate
5101 
5102    Notes:
5103     This code is slow since it is not currently specialized for different formats
5104 
5105 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`
5106 @*/
5107 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5108 {
5109   Vec            ones;
5110 
5111   PetscFunctionBegin;
5112   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5113   PetscValidType(mat,1);
5114   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
5115   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5116   MatCheckPreallocated(mat,1);
5117   PetscCall(MatCreateVecs(mat,&ones,NULL));
5118   PetscCall(VecSet(ones,1.));
5119   PetscCall(MatMult(mat,ones,v));
5120   PetscCall(VecDestroy(&ones));
5121   PetscFunctionReturn(0);
5122 }
5123 
5124 /*@
5125    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5126 
5127    Collective on Mat
5128 
5129    Input Parameters:
5130 +  mat - the matrix to transpose
5131 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5132 
5133    Output Parameter:
5134 .  B - the transpose
5135 
5136    Notes:
5137      If you use MAT_INPLACE_MATRIX then you must pass in &mat for B
5138 
5139      MAT_REUSE_MATRIX causes the B matrix from a previous call to this function with MAT_INITIAL_MATRIX to be used
5140 
5141      Consider using MatCreateTranspose() instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5142 
5143    Level: intermediate
5144 
5145 .seealso: `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5146 @*/
5147 PetscErrorCode MatTranspose(Mat mat,MatReuse reuse,Mat *B)
5148 {
5149   PetscFunctionBegin;
5150   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5151   PetscValidType(mat,1);
5152   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5153   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5154   PetscCheck(mat->ops->transpose,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5155   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires last matrix to match first");
5156   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Perhaps you mean MAT_INPLACE_MATRIX");
5157   MatCheckPreallocated(mat,1);
5158 
5159   PetscCall(PetscLogEventBegin(MAT_Transpose,mat,0,0,0));
5160   PetscCall((*mat->ops->transpose)(mat,reuse,B));
5161   PetscCall(PetscLogEventEnd(MAT_Transpose,mat,0,0,0));
5162   if (B) PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5163   PetscFunctionReturn(0);
5164 }
5165 
5166 /*@
5167    MatIsTranspose - Test whether a matrix is another one's transpose,
5168         or its own, in which case it tests symmetry.
5169 
5170    Collective on Mat
5171 
5172    Input Parameters:
5173 +  A - the matrix to test
5174 -  B - the matrix to test against, this can equal the first parameter
5175 
5176    Output Parameters:
5177 .  flg - the result
5178 
5179    Notes:
5180    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5181    has a running time of the order of the number of nonzeros; the parallel
5182    test involves parallel copies of the block-offdiagonal parts of the matrix.
5183 
5184    Level: intermediate
5185 
5186 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5187 @*/
5188 PetscErrorCode MatIsTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5189 {
5190   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5191 
5192   PetscFunctionBegin;
5193   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5194   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5195   PetscValidBoolPointer(flg,4);
5196   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsTranspose_C",&f));
5197   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsTranspose_C",&g));
5198   *flg = PETSC_FALSE;
5199   if (f && g) {
5200     PetscCheck(f == g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for symmetry test");
5201     PetscCall((*f)(A,B,tol,flg));
5202   } else {
5203     MatType mattype;
5204 
5205     PetscCall(MatGetType(f ? B : A,&mattype));
5206     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for transpose",mattype);
5207   }
5208   PetscFunctionReturn(0);
5209 }
5210 
5211 /*@
5212    MatHermitianTranspose - Computes an in-place or out-of-place transpose of a matrix in complex conjugate.
5213 
5214    Collective on Mat
5215 
5216    Input Parameters:
5217 +  mat - the matrix to transpose and complex conjugate
5218 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5219 
5220    Output Parameter:
5221 .  B - the Hermitian
5222 
5223    Level: intermediate
5224 
5225 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5226 @*/
5227 PetscErrorCode MatHermitianTranspose(Mat mat,MatReuse reuse,Mat *B)
5228 {
5229   PetscFunctionBegin;
5230   PetscCall(MatTranspose(mat,reuse,B));
5231 #if defined(PETSC_USE_COMPLEX)
5232   PetscCall(MatConjugate(*B));
5233 #endif
5234   PetscFunctionReturn(0);
5235 }
5236 
5237 /*@
5238    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5239 
5240    Collective on Mat
5241 
5242    Input Parameters:
5243 +  A - the matrix to test
5244 -  B - the matrix to test against, this can equal the first parameter
5245 
5246    Output Parameters:
5247 .  flg - the result
5248 
5249    Notes:
5250    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5251    has a running time of the order of the number of nonzeros; the parallel
5252    test involves parallel copies of the block-offdiagonal parts of the matrix.
5253 
5254    Level: intermediate
5255 
5256 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5257 @*/
5258 PetscErrorCode MatIsHermitianTranspose(Mat A,Mat B,PetscReal tol,PetscBool *flg)
5259 {
5260   PetscErrorCode (*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
5261 
5262   PetscFunctionBegin;
5263   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5264   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5265   PetscValidBoolPointer(flg,4);
5266   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatIsHermitianTranspose_C",&f));
5267   PetscCall(PetscObjectQueryFunction((PetscObject)B,"MatIsHermitianTranspose_C",&g));
5268   if (f && g) {
5269     PetscCheck(f != g,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for Hermitian test");
5270     PetscCall((*f)(A,B,tol,flg));
5271   }
5272   PetscFunctionReturn(0);
5273 }
5274 
5275 /*@
5276    MatPermute - Creates a new matrix with rows and columns permuted from the
5277    original.
5278 
5279    Collective on Mat
5280 
5281    Input Parameters:
5282 +  mat - the matrix to permute
5283 .  row - row permutation, each processor supplies only the permutation for its rows
5284 -  col - column permutation, each processor supplies only the permutation for its columns
5285 
5286    Output Parameters:
5287 .  B - the permuted matrix
5288 
5289    Level: advanced
5290 
5291    Note:
5292    The index sets map from row/col of permuted matrix to row/col of original matrix.
5293    The index sets should be on the same communicator as Mat and have the same local sizes.
5294 
5295    Developer Note:
5296      If you want to implement MatPermute for a matrix type, and your approach doesn't
5297      exploit the fact that row and col are permutations, consider implementing the
5298      more general MatCreateSubMatrix() instead.
5299 
5300 .seealso: `MatGetOrdering()`, `ISAllGather()`
5301 
5302 @*/
5303 PetscErrorCode MatPermute(Mat mat,IS row,IS col,Mat *B)
5304 {
5305   PetscFunctionBegin;
5306   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5307   PetscValidType(mat,1);
5308   PetscValidHeaderSpecific(row,IS_CLASSID,2);
5309   PetscValidHeaderSpecific(col,IS_CLASSID,3);
5310   PetscValidPointer(B,4);
5311   PetscCheckSameComm(mat,1,row,2);
5312   if (row != col) PetscCheckSameComm(row,2,col,3);
5313   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5314   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5315   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatPermute not available for Mat type %s",((PetscObject)mat)->type_name);
5316   MatCheckPreallocated(mat,1);
5317 
5318   if (mat->ops->permute) {
5319     PetscCall((*mat->ops->permute)(mat,row,col,B));
5320     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5321   } else {
5322     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5323   }
5324   PetscFunctionReturn(0);
5325 }
5326 
5327 /*@
5328    MatEqual - Compares two matrices.
5329 
5330    Collective on Mat
5331 
5332    Input Parameters:
5333 +  A - the first matrix
5334 -  B - the second matrix
5335 
5336    Output Parameter:
5337 .  flg - PETSC_TRUE if the matrices are equal; PETSC_FALSE otherwise.
5338 
5339    Level: intermediate
5340 
5341 @*/
5342 PetscErrorCode MatEqual(Mat A,Mat B,PetscBool *flg)
5343 {
5344   PetscFunctionBegin;
5345   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5346   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5347   PetscValidType(A,1);
5348   PetscValidType(B,2);
5349   PetscValidBoolPointer(flg,3);
5350   PetscCheckSameComm(A,1,B,2);
5351   MatCheckPreallocated(A,1);
5352   MatCheckPreallocated(B,2);
5353   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5354   PetscCheck(B->assembled,PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5355   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT,A->rmap->N,B->rmap->N,A->cmap->N,B->cmap->N);
5356   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5357     PetscCall((*A->ops->equal)(A,B,flg));
5358   } else {
5359     PetscCall(MatMultEqual(A,B,10,flg));
5360   }
5361   PetscFunctionReturn(0);
5362 }
5363 
5364 /*@
5365    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5366    matrices that are stored as vectors.  Either of the two scaling
5367    matrices can be NULL.
5368 
5369    Collective on Mat
5370 
5371    Input Parameters:
5372 +  mat - the matrix to be scaled
5373 .  l - the left scaling vector (or NULL)
5374 -  r - the right scaling vector (or NULL)
5375 
5376    Notes:
5377    MatDiagonalScale() computes A = LAR, where
5378    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5379    The L scales the rows of the matrix, the R scales the columns of the matrix.
5380 
5381    Level: intermediate
5382 
5383 .seealso: `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5384 @*/
5385 PetscErrorCode MatDiagonalScale(Mat mat,Vec l,Vec r)
5386 {
5387   PetscFunctionBegin;
5388   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5389   PetscValidType(mat,1);
5390   if (l) {PetscValidHeaderSpecific(l,VEC_CLASSID,2);PetscCheckSameComm(mat,1,l,2);}
5391   if (r) {PetscValidHeaderSpecific(r,VEC_CLASSID,3);PetscCheckSameComm(mat,1,r,3);}
5392   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5393   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5394   MatCheckPreallocated(mat,1);
5395   if (!l && !r) PetscFunctionReturn(0);
5396 
5397   PetscCheck(mat->ops->diagonalscale,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5398   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5399   PetscCall((*mat->ops->diagonalscale)(mat,l,r));
5400   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5401   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5402   if (l != r && mat->symmetric) mat->symmetric = PETSC_FALSE;
5403   PetscFunctionReturn(0);
5404 }
5405 
5406 /*@
5407     MatScale - Scales all elements of a matrix by a given number.
5408 
5409     Logically Collective on Mat
5410 
5411     Input Parameters:
5412 +   mat - the matrix to be scaled
5413 -   a  - the scaling value
5414 
5415     Output Parameter:
5416 .   mat - the scaled matrix
5417 
5418     Level: intermediate
5419 
5420 .seealso: `MatDiagonalScale()`
5421 @*/
5422 PetscErrorCode MatScale(Mat mat,PetscScalar a)
5423 {
5424   PetscFunctionBegin;
5425   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5426   PetscValidType(mat,1);
5427   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5428   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5429   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5430   PetscValidLogicalCollectiveScalar(mat,a,2);
5431   MatCheckPreallocated(mat,1);
5432 
5433   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
5434   if (a != (PetscScalar)1.0) {
5435     PetscCall((*mat->ops->scale)(mat,a));
5436     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5437   }
5438   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
5439   PetscFunctionReturn(0);
5440 }
5441 
5442 /*@
5443    MatNorm - Calculates various norms of a matrix.
5444 
5445    Collective on Mat
5446 
5447    Input Parameters:
5448 +  mat - the matrix
5449 -  type - the type of norm, NORM_1, NORM_FROBENIUS, NORM_INFINITY
5450 
5451    Output Parameter:
5452 .  nrm - the resulting norm
5453 
5454    Level: intermediate
5455 
5456 @*/
5457 PetscErrorCode MatNorm(Mat mat,NormType type,PetscReal *nrm)
5458 {
5459   PetscFunctionBegin;
5460   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5461   PetscValidType(mat,1);
5462   PetscValidRealPointer(nrm,3);
5463 
5464   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5465   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5466   PetscCheck(mat->ops->norm,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5467   MatCheckPreallocated(mat,1);
5468 
5469   PetscCall((*mat->ops->norm)(mat,type,nrm));
5470   PetscFunctionReturn(0);
5471 }
5472 
5473 /*
5474      This variable is used to prevent counting of MatAssemblyBegin() that
5475    are called from within a MatAssemblyEnd().
5476 */
5477 static PetscInt MatAssemblyEnd_InUse = 0;
5478 /*@
5479    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5480    be called after completing all calls to MatSetValues().
5481 
5482    Collective on Mat
5483 
5484    Input Parameters:
5485 +  mat - the matrix
5486 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5487 
5488    Notes:
5489    MatSetValues() generally caches the values.  The matrix is ready to
5490    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5491    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5492    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5493    using the matrix.
5494 
5495    ALL processes that share a matrix MUST call MatAssemblyBegin() and MatAssemblyEnd() the SAME NUMBER of times, and each time with the
5496    same flag of MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY for all processes. Thus you CANNOT locally change from ADD_VALUES to INSERT_VALUES, that is
5497    a global collective operation requring all processes that share the matrix.
5498 
5499    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5500    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5501    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5502 
5503    Level: beginner
5504 
5505 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5506 @*/
5507 PetscErrorCode MatAssemblyBegin(Mat mat,MatAssemblyType type)
5508 {
5509   PetscFunctionBegin;
5510   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5511   PetscValidType(mat,1);
5512   MatCheckPreallocated(mat,1);
5513   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5514   if (mat->assembled) {
5515     mat->was_assembled = PETSC_TRUE;
5516     mat->assembled     = PETSC_FALSE;
5517   }
5518 
5519   if (!MatAssemblyEnd_InUse) {
5520     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin,mat,0,0,0));
5521     if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5522     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin,mat,0,0,0));
5523   } else if (mat->ops->assemblybegin) PetscCall((*mat->ops->assemblybegin)(mat,type));
5524   PetscFunctionReturn(0);
5525 }
5526 
5527 /*@
5528    MatAssembled - Indicates if a matrix has been assembled and is ready for
5529      use; for example, in matrix-vector product.
5530 
5531    Not Collective
5532 
5533    Input Parameter:
5534 .  mat - the matrix
5535 
5536    Output Parameter:
5537 .  assembled - PETSC_TRUE or PETSC_FALSE
5538 
5539    Level: advanced
5540 
5541 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5542 @*/
5543 PetscErrorCode MatAssembled(Mat mat,PetscBool *assembled)
5544 {
5545   PetscFunctionBegin;
5546   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5547   PetscValidBoolPointer(assembled,2);
5548   *assembled = mat->assembled;
5549   PetscFunctionReturn(0);
5550 }
5551 
5552 /*@
5553    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5554    be called after MatAssemblyBegin().
5555 
5556    Collective on Mat
5557 
5558    Input Parameters:
5559 +  mat - the matrix
5560 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5561 
5562    Options Database Keys:
5563 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatEndAssembly()
5564 .  -mat_view ::ascii_info_detail - Prints more detailed info
5565 .  -mat_view - Prints matrix in ASCII format
5566 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5567 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
5568 .  -display <name> - Sets display name (default is host)
5569 .  -draw_pause <sec> - Sets number of seconds to pause after display
5570 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab)
5571 .  -viewer_socket_machine <machine> - Machine to use for socket
5572 .  -viewer_socket_port <port> - Port number to use for socket
5573 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5574 
5575    Notes:
5576    MatSetValues() generally caches the values.  The matrix is ready to
5577    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5578    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5579    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5580    using the matrix.
5581 
5582    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5583    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5584    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5585 
5586    Level: beginner
5587 
5588 .seealso: `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5589 @*/
5590 PetscErrorCode MatAssemblyEnd(Mat mat,MatAssemblyType type)
5591 {
5592   static PetscInt inassm = 0;
5593   PetscBool       flg    = PETSC_FALSE;
5594 
5595   PetscFunctionBegin;
5596   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5597   PetscValidType(mat,1);
5598 
5599   inassm++;
5600   MatAssemblyEnd_InUse++;
5601   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5602     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd,mat,0,0,0));
5603     if (mat->ops->assemblyend) PetscCall((*mat->ops->assemblyend)(mat,type));
5604     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd,mat,0,0,0));
5605   } else if (mat->ops->assemblyend) PetscCall((*mat->ops->assemblyend)(mat,type));
5606 
5607   /* Flush assembly is not a true assembly */
5608   if (type != MAT_FLUSH_ASSEMBLY) {
5609     mat->num_ass++;
5610     mat->assembled        = PETSC_TRUE;
5611     mat->ass_nonzerostate = mat->nonzerostate;
5612   }
5613 
5614   mat->insertmode = NOT_SET_VALUES;
5615   MatAssemblyEnd_InUse--;
5616   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5617   if (!mat->symmetric_eternal) {
5618     mat->symmetric_set              = PETSC_FALSE;
5619     mat->hermitian_set              = PETSC_FALSE;
5620     mat->structurally_symmetric_set = PETSC_FALSE;
5621   }
5622   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5623     PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5624 
5625     if (mat->checksymmetryonassembly) {
5626       PetscCall(MatIsSymmetric(mat,mat->checksymmetrytol,&flg));
5627       if (flg) {
5628         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5629       } else {
5630         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is not symmetric (tolerance %g)\n",(double)mat->checksymmetrytol));
5631       }
5632     }
5633     if (mat->nullsp && mat->checknullspaceonassembly) {
5634       PetscCall(MatNullSpaceTest(mat->nullsp,mat,NULL));
5635     }
5636   }
5637   inassm--;
5638   PetscFunctionReturn(0);
5639 }
5640 
5641 /*@
5642    MatSetOption - Sets a parameter option for a matrix. Some options
5643    may be specific to certain storage formats.  Some options
5644    determine how values will be inserted (or added). Sorted,
5645    row-oriented input will generally assemble the fastest. The default
5646    is row-oriented.
5647 
5648    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5649 
5650    Input Parameters:
5651 +  mat - the matrix
5652 .  option - the option, one of those listed below (and possibly others),
5653 -  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5654 
5655   Options Describing Matrix Structure:
5656 +    MAT_SPD - symmetric positive definite
5657 .    MAT_SYMMETRIC - symmetric in terms of both structure and value
5658 .    MAT_HERMITIAN - transpose is the complex conjugation
5659 .    MAT_STRUCTURALLY_SYMMETRIC - symmetric nonzero structure
5660 -    MAT_SYMMETRY_ETERNAL - if you would like the symmetry/Hermitian flag
5661                             you set to be kept with all future use of the matrix
5662                             including after MatAssemblyBegin/End() which could
5663                             potentially change the symmetry structure, i.e. you
5664                             KNOW the matrix will ALWAYS have the property you set.
5665                             Note that setting this flag alone implies nothing about whether the matrix is symmetric/Hermitian;
5666                             the relevant flags must be set independently.
5667 
5668    Options For Use with MatSetValues():
5669    Insert a logically dense subblock, which can be
5670 .    MAT_ROW_ORIENTED - row-oriented (default)
5671 
5672    Note these options reflect the data you pass in with MatSetValues(); it has
5673    nothing to do with how the data is stored internally in the matrix
5674    data structure.
5675 
5676    When (re)assembling a matrix, we can restrict the input for
5677    efficiency/debugging purposes.  These options include
5678 +    MAT_NEW_NONZERO_LOCATIONS - additional insertions will be allowed if they generate a new nonzero (slow)
5679 .    MAT_FORCE_DIAGONAL_ENTRIES - forces diagonal entries to be allocated
5680 .    MAT_IGNORE_OFF_PROC_ENTRIES - drops off-processor entries
5681 .    MAT_NEW_NONZERO_LOCATION_ERR - generates an error for new matrix entry
5682 .    MAT_USE_HASH_TABLE - uses a hash table to speed up matrix assembly
5683 .    MAT_NO_OFF_PROC_ENTRIES - you know each process will only set values for its own rows, will generate an error if
5684         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5685         performance for very large process counts.
5686 -    MAT_SUBSET_OFF_PROC_ENTRIES - you know that the first assembly after setting this flag will set a superset
5687         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5688         functions, instead sending only neighbor messages.
5689 
5690    Notes:
5691    Except for MAT_UNUSED_NONZERO_LOCATION_ERR and  MAT_ROW_ORIENTED all processes that share the matrix must pass the same value in flg!
5692 
5693    Some options are relevant only for particular matrix types and
5694    are thus ignored by others.  Other options are not supported by
5695    certain matrix types and will generate an error message if set.
5696 
5697    If using a Fortran 77 module to compute a matrix, one may need to
5698    use the column-oriented option (or convert to the row-oriented
5699    format).
5700 
5701    MAT_NEW_NONZERO_LOCATIONS set to PETSC_FALSE indicates that any add or insertion
5702    that would generate a new entry in the nonzero structure is instead
5703    ignored.  Thus, if memory has not alredy been allocated for this particular
5704    data, then the insertion is ignored. For dense matrices, in which
5705    the entire array is allocated, no entries are ever ignored.
5706    Set after the first MatAssemblyEnd(). If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5707 
5708    MAT_NEW_NONZERO_LOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5709    that would generate a new entry in the nonzero structure instead produces
5710    an error. (Currently supported for AIJ and BAIJ formats only.) If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5711 
5712    MAT_NEW_NONZERO_ALLOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5713    that would generate a new entry that has not been preallocated will
5714    instead produce an error. (Currently supported for AIJ and BAIJ formats
5715    only.) This is a useful flag when debugging matrix memory preallocation.
5716    If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5717 
5718    MAT_IGNORE_OFF_PROC_ENTRIES set to PETSC_TRUE indicates entries destined for
5719    other processors should be dropped, rather than stashed.
5720    This is useful if you know that the "owning" processor is also
5721    always generating the correct matrix entries, so that PETSc need
5722    not transfer duplicate entries generated on another processor.
5723 
5724    MAT_USE_HASH_TABLE indicates that a hash table be used to improve the
5725    searches during matrix assembly. When this flag is set, the hash table
5726    is created during the first Matrix Assembly. This hash table is
5727    used the next time through, during MatSetVaules()/MatSetVaulesBlocked()
5728    to improve the searching of indices. MAT_NEW_NONZERO_LOCATIONS flag
5729    should be used with MAT_USE_HASH_TABLE flag. This option is currently
5730    supported by MATMPIBAIJ format only.
5731 
5732    MAT_KEEP_NONZERO_PATTERN indicates when MatZeroRows() is called the zeroed entries
5733    are kept in the nonzero structure
5734 
5735    MAT_IGNORE_ZERO_ENTRIES - for AIJ/IS matrices this will stop zero values from creating
5736    a zero location in the matrix
5737 
5738    MAT_USE_INODES - indicates using inode version of the code - works with AIJ matrix types
5739 
5740    MAT_NO_OFF_PROC_ZERO_ROWS - you know each process will only zero its own rows. This avoids all reductions in the
5741         zero row routines and thus improves performance for very large process counts.
5742 
5743    MAT_IGNORE_LOWER_TRIANGULAR - For SBAIJ matrices will ignore any insertions you make in the lower triangular
5744         part of the matrix (since they should match the upper triangular part).
5745 
5746    MAT_SORTED_FULL - each process provides exactly its local rows; all column indices for a given row are passed in a
5747                      single call to MatSetValues(), preallocation is perfect, row oriented, INSERT_VALUES is used. Common
5748                      with finite difference schemes with non-periodic boundary conditions.
5749 
5750    Level: intermediate
5751 
5752 .seealso: `MatOption`, `Mat`
5753 
5754 @*/
5755 PetscErrorCode MatSetOption(Mat mat,MatOption op,PetscBool flg)
5756 {
5757   PetscFunctionBegin;
5758   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5759   if (op > 0) {
5760     PetscValidLogicalCollectiveEnum(mat,op,2);
5761     PetscValidLogicalCollectiveBool(mat,flg,3);
5762   }
5763 
5764   PetscCheck(((int) op) > MAT_OPTION_MIN && ((int) op) < MAT_OPTION_MAX,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Options %d is out of range",(int)op);
5765 
5766   switch (op) {
5767   case MAT_FORCE_DIAGONAL_ENTRIES:
5768     mat->force_diagonals = flg;
5769     PetscFunctionReturn(0);
5770   case MAT_NO_OFF_PROC_ENTRIES:
5771     mat->nooffprocentries = flg;
5772     PetscFunctionReturn(0);
5773   case MAT_SUBSET_OFF_PROC_ENTRIES:
5774     mat->assembly_subset = flg;
5775     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5776 #if !defined(PETSC_HAVE_MPIUNI)
5777       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5778 #endif
5779       mat->stash.first_assembly_done = PETSC_FALSE;
5780     }
5781     PetscFunctionReturn(0);
5782   case MAT_NO_OFF_PROC_ZERO_ROWS:
5783     mat->nooffproczerorows = flg;
5784     PetscFunctionReturn(0);
5785   case MAT_SPD:
5786     mat->spd_set = PETSC_TRUE;
5787     mat->spd     = flg;
5788     if (flg) {
5789       mat->symmetric                  = PETSC_TRUE;
5790       mat->structurally_symmetric     = PETSC_TRUE;
5791       mat->symmetric_set              = PETSC_TRUE;
5792       mat->structurally_symmetric_set = PETSC_TRUE;
5793     }
5794     break;
5795   case MAT_SYMMETRIC:
5796     mat->symmetric = flg;
5797     if (flg) mat->structurally_symmetric = PETSC_TRUE;
5798     mat->symmetric_set              = PETSC_TRUE;
5799     mat->structurally_symmetric_set = flg;
5800 #if !defined(PETSC_USE_COMPLEX)
5801     mat->hermitian     = flg;
5802     mat->hermitian_set = PETSC_TRUE;
5803 #endif
5804     break;
5805   case MAT_HERMITIAN:
5806     mat->hermitian = flg;
5807     if (flg) mat->structurally_symmetric = PETSC_TRUE;
5808     mat->hermitian_set              = PETSC_TRUE;
5809     mat->structurally_symmetric_set = flg;
5810 #if !defined(PETSC_USE_COMPLEX)
5811     mat->symmetric     = flg;
5812     mat->symmetric_set = PETSC_TRUE;
5813 #endif
5814     break;
5815   case MAT_STRUCTURALLY_SYMMETRIC:
5816     mat->structurally_symmetric     = flg;
5817     mat->structurally_symmetric_set = PETSC_TRUE;
5818     break;
5819   case MAT_SYMMETRY_ETERNAL:
5820     mat->symmetric_eternal = flg;
5821     break;
5822   case MAT_STRUCTURE_ONLY:
5823     mat->structure_only = flg;
5824     break;
5825   case MAT_SORTED_FULL:
5826     mat->sortedfull = flg;
5827     break;
5828   default:
5829     break;
5830   }
5831   if (mat->ops->setoption) PetscCall((*mat->ops->setoption)(mat,op,flg));
5832   PetscFunctionReturn(0);
5833 }
5834 
5835 /*@
5836    MatGetOption - Gets a parameter option that has been set for a matrix.
5837 
5838    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5839 
5840    Input Parameters:
5841 +  mat - the matrix
5842 -  option - the option, this only responds to certain options, check the code for which ones
5843 
5844    Output Parameter:
5845 .  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5846 
5847     Notes:
5848     Can only be called after MatSetSizes() and MatSetType() have been set.
5849 
5850    Level: intermediate
5851 
5852 .seealso: `MatOption`, `MatSetOption()`
5853 
5854 @*/
5855 PetscErrorCode MatGetOption(Mat mat,MatOption op,PetscBool *flg)
5856 {
5857   PetscFunctionBegin;
5858   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5859   PetscValidType(mat,1);
5860 
5861   PetscCheck(((int) op) > MAT_OPTION_MIN && ((int) op) < MAT_OPTION_MAX,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Options %d is out of range",(int)op);
5862   PetscCheck(((PetscObject)mat)->type_name,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_TYPENOTSET,"Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()");
5863 
5864   switch (op) {
5865   case MAT_NO_OFF_PROC_ENTRIES:
5866     *flg = mat->nooffprocentries;
5867     break;
5868   case MAT_NO_OFF_PROC_ZERO_ROWS:
5869     *flg = mat->nooffproczerorows;
5870     break;
5871   case MAT_SYMMETRIC:
5872     *flg = mat->symmetric;
5873     break;
5874   case MAT_HERMITIAN:
5875     *flg = mat->hermitian;
5876     break;
5877   case MAT_STRUCTURALLY_SYMMETRIC:
5878     *flg = mat->structurally_symmetric;
5879     break;
5880   case MAT_SYMMETRY_ETERNAL:
5881     *flg = mat->symmetric_eternal;
5882     break;
5883   case MAT_SPD:
5884     *flg = mat->spd;
5885     break;
5886   default:
5887     break;
5888   }
5889   PetscFunctionReturn(0);
5890 }
5891 
5892 /*@
5893    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5894    this routine retains the old nonzero structure.
5895 
5896    Logically Collective on Mat
5897 
5898    Input Parameters:
5899 .  mat - the matrix
5900 
5901    Level: intermediate
5902 
5903    Notes:
5904     If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase.
5905    See the Performance chapter of the users manual for information on preallocating matrices.
5906 
5907 .seealso: `MatZeroRows()`
5908 @*/
5909 PetscErrorCode MatZeroEntries(Mat mat)
5910 {
5911   PetscFunctionBegin;
5912   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5913   PetscValidType(mat,1);
5914   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5915   PetscCheck(mat->insertmode == NOT_SET_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for matrices where you have set values but not yet assembled");
5916   PetscCheck(mat->ops->zeroentries,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5917   MatCheckPreallocated(mat,1);
5918 
5919   PetscCall(PetscLogEventBegin(MAT_ZeroEntries,mat,0,0,0));
5920   PetscCall((*mat->ops->zeroentries)(mat));
5921   PetscCall(PetscLogEventEnd(MAT_ZeroEntries,mat,0,0,0));
5922   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5923   PetscFunctionReturn(0);
5924 }
5925 
5926 /*@
5927    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5928    of a set of rows and columns of a matrix.
5929 
5930    Collective on Mat
5931 
5932    Input Parameters:
5933 +  mat - the matrix
5934 .  numRows - the number of rows to remove
5935 .  rows - the global row indices
5936 .  diag - value put in the diagonal of the eliminated rows
5937 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5938 -  b - optional vector of right hand side, that will be adjusted by provided solution
5939 
5940    Notes:
5941    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5942 
5943    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5944    The other entries of b will be adjusted by the known values of x times the corresponding matrix entries in the columns that are being eliminated
5945 
5946    If the resulting linear system is to be solved with KSP then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5947    Krylov method to take advantage of the known solution on the zeroed rows.
5948 
5949    For the parallel case, all processes that share the matrix (i.e.,
5950    those in the communicator used for matrix creation) MUST call this
5951    routine, regardless of whether any rows being zeroed are owned by
5952    them.
5953 
5954    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5955 
5956    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5957    list only rows local to itself).
5958 
5959    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
5960 
5961    Level: intermediate
5962 
5963 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5964           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5965 @*/
5966 PetscErrorCode MatZeroRowsColumns(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
5967 {
5968   PetscFunctionBegin;
5969   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5970   PetscValidType(mat,1);
5971   if (numRows) PetscValidIntPointer(rows,3);
5972   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5973   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5974   PetscCheck(mat->ops->zerorowscolumns,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5975   MatCheckPreallocated(mat,1);
5976 
5977   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,rows,diag,x,b));
5978   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
5979   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5980   PetscFunctionReturn(0);
5981 }
5982 
5983 /*@
5984    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5985    of a set of rows and columns of a matrix.
5986 
5987    Collective on Mat
5988 
5989    Input Parameters:
5990 +  mat - the matrix
5991 .  is - the rows to zero
5992 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5993 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5994 -  b - optional vector of right hand side, that will be adjusted by provided solution
5995 
5996    Note:
5997    See `MatZeroRowsColumns()` for details on how this routine operates.
5998 
5999    Level: intermediate
6000 
6001 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6002           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6003 @*/
6004 PetscErrorCode MatZeroRowsColumnsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6005 {
6006   PetscInt       numRows;
6007   const PetscInt *rows;
6008 
6009   PetscFunctionBegin;
6010   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6011   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6012   PetscValidType(mat,1);
6013   PetscValidType(is,2);
6014   PetscCall(ISGetLocalSize(is,&numRows));
6015   PetscCall(ISGetIndices(is,&rows));
6016   PetscCall(MatZeroRowsColumns(mat,numRows,rows,diag,x,b));
6017   PetscCall(ISRestoreIndices(is,&rows));
6018   PetscFunctionReturn(0);
6019 }
6020 
6021 /*@
6022    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6023    of a set of rows of a matrix.
6024 
6025    Collective on Mat
6026 
6027    Input Parameters:
6028 +  mat - the matrix
6029 .  numRows - the number of rows to remove
6030 .  rows - the global row indices
6031 .  diag - value put in the diagonal of the eliminated rows
6032 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6033 -  b - optional vector of right hand side, that will be adjusted by provided solution
6034 
6035    Notes:
6036    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6037 
6038    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6039 
6040    If the resulting linear system is to be solved with KSP then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6041    Krylov method to take advantage of the known solution on the zeroed rows.
6042 
6043    Unlike `MatZeroRowsColumns()` for the AIJ and BAIJ matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6044    but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal
6045    formats this does not alter the nonzero structure.
6046 
6047    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6048    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6049    merely zeroed.
6050 
6051    The user can set a value in the diagonal entry (or for the AIJ and
6052    row formats can optionally remove the main diagonal entry from the
6053    nonzero structure as well, by passing 0.0 as the final argument).
6054 
6055    For the parallel case, all processes that share the matrix (i.e.,
6056    those in the communicator used for matrix creation) MUST call this
6057    routine, regardless of whether any rows being zeroed are owned by
6058    them.
6059 
6060    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6061    list only rows local to itself).
6062 
6063    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6064    owns that are to be zeroed. This saves a global synchronization in the implementation.
6065 
6066    Level: intermediate
6067 
6068 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6069           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6070 @*/
6071 PetscErrorCode MatZeroRows(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6072 {
6073   PetscFunctionBegin;
6074   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6075   PetscValidType(mat,1);
6076   if (numRows) PetscValidIntPointer(rows,3);
6077   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6078   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6079   PetscCheck(mat->ops->zerorows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6080   MatCheckPreallocated(mat,1);
6081 
6082   PetscCall((*mat->ops->zerorows)(mat,numRows,rows,diag,x,b));
6083   PetscCall(MatViewFromOptions(mat,NULL,"-mat_view"));
6084   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6085   PetscFunctionReturn(0);
6086 }
6087 
6088 /*@
6089    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6090    of a set of rows of a matrix.
6091 
6092    Collective on Mat
6093 
6094    Input Parameters:
6095 +  mat - the matrix
6096 .  is - index set of rows to remove (if NULL then no row is removed)
6097 .  diag - value put in all diagonals of eliminated rows
6098 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6099 -  b - optional vector of right hand side, that will be adjusted by provided solution
6100 
6101    Note:
6102    See `MatZeroRows()` for details on how this routine operates.
6103 
6104    Level: intermediate
6105 
6106 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6107           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6108 @*/
6109 PetscErrorCode MatZeroRowsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6110 {
6111   PetscInt       numRows = 0;
6112   const PetscInt *rows = NULL;
6113 
6114   PetscFunctionBegin;
6115   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6116   PetscValidType(mat,1);
6117   if (is) {
6118     PetscValidHeaderSpecific(is,IS_CLASSID,2);
6119     PetscCall(ISGetLocalSize(is,&numRows));
6120     PetscCall(ISGetIndices(is,&rows));
6121   }
6122   PetscCall(MatZeroRows(mat,numRows,rows,diag,x,b));
6123   if (is) {
6124     PetscCall(ISRestoreIndices(is,&rows));
6125   }
6126   PetscFunctionReturn(0);
6127 }
6128 
6129 /*@
6130    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6131    of a set of rows of a matrix. These rows must be local to the process.
6132 
6133    Collective on Mat
6134 
6135    Input Parameters:
6136 +  mat - the matrix
6137 .  numRows - the number of rows to remove
6138 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6139 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6140 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6141 -  b - optional vector of right hand side, that will be adjusted by provided solution
6142 
6143    Notes:
6144    See `MatZeroRows()` for details on how this routine operates.
6145 
6146    The grid coordinates are across the entire grid, not just the local portion
6147 
6148    In Fortran idxm and idxn should be declared as
6149 $     MatStencil idxm(4,m)
6150    and the values inserted using
6151 $    idxm(MatStencil_i,1) = i
6152 $    idxm(MatStencil_j,1) = j
6153 $    idxm(MatStencil_k,1) = k
6154 $    idxm(MatStencil_c,1) = c
6155    etc
6156 
6157    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6158    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6159    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6160    DM_BOUNDARY_PERIODIC boundary type.
6161 
6162    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
6163    a single value per point) you can skip filling those indices.
6164 
6165    Level: intermediate
6166 
6167 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6168           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6169 @*/
6170 PetscErrorCode MatZeroRowsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6171 {
6172   PetscInt       dim     = mat->stencil.dim;
6173   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6174   PetscInt       *dims   = mat->stencil.dims+1;
6175   PetscInt       *starts = mat->stencil.starts;
6176   PetscInt       *dxm    = (PetscInt*) rows;
6177   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6178 
6179   PetscFunctionBegin;
6180   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6181   PetscValidType(mat,1);
6182   if (numRows) PetscValidPointer(rows,3);
6183 
6184   PetscCall(PetscMalloc1(numRows, &jdxm));
6185   for (i = 0; i < numRows; ++i) {
6186     /* Skip unused dimensions (they are ordered k, j, i, c) */
6187     for (j = 0; j < 3-sdim; ++j) dxm++;
6188     /* Local index in X dir */
6189     tmp = *dxm++ - starts[0];
6190     /* Loop over remaining dimensions */
6191     for (j = 0; j < dim-1; ++j) {
6192       /* If nonlocal, set index to be negative */
6193       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6194       /* Update local index */
6195       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6196     }
6197     /* Skip component slot if necessary */
6198     if (mat->stencil.noc) dxm++;
6199     /* Local row number */
6200     if (tmp >= 0) {
6201       jdxm[numNewRows++] = tmp;
6202     }
6203   }
6204   PetscCall(MatZeroRowsLocal(mat,numNewRows,jdxm,diag,x,b));
6205   PetscCall(PetscFree(jdxm));
6206   PetscFunctionReturn(0);
6207 }
6208 
6209 /*@
6210    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6211    of a set of rows and columns of a matrix.
6212 
6213    Collective on Mat
6214 
6215    Input Parameters:
6216 +  mat - the matrix
6217 .  numRows - the number of rows/columns to remove
6218 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6219 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6220 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6221 -  b - optional vector of right hand side, that will be adjusted by provided solution
6222 
6223    Notes:
6224    See `MatZeroRowsColumns()` for details on how this routine operates.
6225 
6226    The grid coordinates are across the entire grid, not just the local portion
6227 
6228    In Fortran idxm and idxn should be declared as
6229 $     MatStencil idxm(4,m)
6230    and the values inserted using
6231 $    idxm(MatStencil_i,1) = i
6232 $    idxm(MatStencil_j,1) = j
6233 $    idxm(MatStencil_k,1) = k
6234 $    idxm(MatStencil_c,1) = c
6235    etc
6236 
6237    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6238    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6239    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6240    DM_BOUNDARY_PERIODIC boundary type.
6241 
6242    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
6243    a single value per point) you can skip filling those indices.
6244 
6245    Level: intermediate
6246 
6247 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6248           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6249 @*/
6250 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6251 {
6252   PetscInt       dim     = mat->stencil.dim;
6253   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6254   PetscInt       *dims   = mat->stencil.dims+1;
6255   PetscInt       *starts = mat->stencil.starts;
6256   PetscInt       *dxm    = (PetscInt*) rows;
6257   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6258 
6259   PetscFunctionBegin;
6260   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6261   PetscValidType(mat,1);
6262   if (numRows) PetscValidPointer(rows,3);
6263 
6264   PetscCall(PetscMalloc1(numRows, &jdxm));
6265   for (i = 0; i < numRows; ++i) {
6266     /* Skip unused dimensions (they are ordered k, j, i, c) */
6267     for (j = 0; j < 3-sdim; ++j) dxm++;
6268     /* Local index in X dir */
6269     tmp = *dxm++ - starts[0];
6270     /* Loop over remaining dimensions */
6271     for (j = 0; j < dim-1; ++j) {
6272       /* If nonlocal, set index to be negative */
6273       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6274       /* Update local index */
6275       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6276     }
6277     /* Skip component slot if necessary */
6278     if (mat->stencil.noc) dxm++;
6279     /* Local row number */
6280     if (tmp >= 0) {
6281       jdxm[numNewRows++] = tmp;
6282     }
6283   }
6284   PetscCall(MatZeroRowsColumnsLocal(mat,numNewRows,jdxm,diag,x,b));
6285   PetscCall(PetscFree(jdxm));
6286   PetscFunctionReturn(0);
6287 }
6288 
6289 /*@C
6290    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6291    of a set of rows of a matrix; using local numbering of rows.
6292 
6293    Collective on Mat
6294 
6295    Input Parameters:
6296 +  mat - the matrix
6297 .  numRows - the number of rows to remove
6298 .  rows - the local row indices
6299 .  diag - value put in all diagonals of eliminated rows
6300 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6301 -  b - optional vector of right hand side, that will be adjusted by provided solution
6302 
6303    Notes:
6304    Before calling `MatZeroRowsLocal()`, the user must first set the
6305    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6306 
6307    See `MatZeroRows()` for details on how this routine operates.
6308 
6309    Level: intermediate
6310 
6311 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6312           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6313 @*/
6314 PetscErrorCode MatZeroRowsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6315 {
6316   PetscFunctionBegin;
6317   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6318   PetscValidType(mat,1);
6319   if (numRows) PetscValidIntPointer(rows,3);
6320   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6321   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6322   MatCheckPreallocated(mat,1);
6323 
6324   if (mat->ops->zerorowslocal) {
6325     PetscCall((*mat->ops->zerorowslocal)(mat,numRows,rows,diag,x,b));
6326   } else {
6327     IS             is, newis;
6328     const PetscInt *newRows;
6329 
6330     PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6331     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6332     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping,is,&newis));
6333     PetscCall(ISGetIndices(newis,&newRows));
6334     PetscCall((*mat->ops->zerorows)(mat,numRows,newRows,diag,x,b));
6335     PetscCall(ISRestoreIndices(newis,&newRows));
6336     PetscCall(ISDestroy(&newis));
6337     PetscCall(ISDestroy(&is));
6338   }
6339   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6340   PetscFunctionReturn(0);
6341 }
6342 
6343 /*@
6344    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6345    of a set of rows of a matrix; using local numbering of rows.
6346 
6347    Collective on Mat
6348 
6349    Input Parameters:
6350 +  mat - the matrix
6351 .  is - index set of rows to remove
6352 .  diag - value put in all diagonals of eliminated rows
6353 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6354 -  b - optional vector of right hand side, that will be adjusted by provided solution
6355 
6356    Notes:
6357    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6358    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`.
6359 
6360    See `MatZeroRows()` for details on how this routine operates.
6361 
6362    Level: intermediate
6363 
6364 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6365           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6366 @*/
6367 PetscErrorCode MatZeroRowsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6368 {
6369   PetscInt       numRows;
6370   const PetscInt *rows;
6371 
6372   PetscFunctionBegin;
6373   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6374   PetscValidType(mat,1);
6375   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6376   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6377   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6378   MatCheckPreallocated(mat,1);
6379 
6380   PetscCall(ISGetLocalSize(is,&numRows));
6381   PetscCall(ISGetIndices(is,&rows));
6382   PetscCall(MatZeroRowsLocal(mat,numRows,rows,diag,x,b));
6383   PetscCall(ISRestoreIndices(is,&rows));
6384   PetscFunctionReturn(0);
6385 }
6386 
6387 /*@
6388    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6389    of a set of rows and columns of a matrix; using local numbering of rows.
6390 
6391    Collective on Mat
6392 
6393    Input Parameters:
6394 +  mat - the matrix
6395 .  numRows - the number of rows to remove
6396 .  rows - the global row indices
6397 .  diag - value put in all diagonals of eliminated rows
6398 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6399 -  b - optional vector of right hand side, that will be adjusted by provided solution
6400 
6401    Notes:
6402    Before calling MatZeroRowsColumnsLocal(), the user must first set the
6403    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6404 
6405    See `MatZeroRowsColumns()` for details on how this routine operates.
6406 
6407    Level: intermediate
6408 
6409 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6410           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6411 @*/
6412 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6413 {
6414   IS             is, newis;
6415   const PetscInt *newRows;
6416 
6417   PetscFunctionBegin;
6418   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6419   PetscValidType(mat,1);
6420   if (numRows) PetscValidIntPointer(rows,3);
6421   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6422   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6423   MatCheckPreallocated(mat,1);
6424 
6425   PetscCheck(mat->cmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6426   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is));
6427   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping,is,&newis));
6428   PetscCall(ISGetIndices(newis,&newRows));
6429   PetscCall((*mat->ops->zerorowscolumns)(mat,numRows,newRows,diag,x,b));
6430   PetscCall(ISRestoreIndices(newis,&newRows));
6431   PetscCall(ISDestroy(&newis));
6432   PetscCall(ISDestroy(&is));
6433   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6434   PetscFunctionReturn(0);
6435 }
6436 
6437 /*@
6438    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6439    of a set of rows and columns of a matrix; using local numbering of rows.
6440 
6441    Collective on Mat
6442 
6443    Input Parameters:
6444 +  mat - the matrix
6445 .  is - index set of rows to remove
6446 .  diag - value put in all diagonals of eliminated rows
6447 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6448 -  b - optional vector of right hand side, that will be adjusted by provided solution
6449 
6450    Notes:
6451    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6452    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`.
6453 
6454    See `MatZeroRowsColumns()` for details on how this routine operates.
6455 
6456    Level: intermediate
6457 
6458 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6459           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6460 @*/
6461 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6462 {
6463   PetscInt       numRows;
6464   const PetscInt *rows;
6465 
6466   PetscFunctionBegin;
6467   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6468   PetscValidType(mat,1);
6469   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6470   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6471   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6472   MatCheckPreallocated(mat,1);
6473 
6474   PetscCall(ISGetLocalSize(is,&numRows));
6475   PetscCall(ISGetIndices(is,&rows));
6476   PetscCall(MatZeroRowsColumnsLocal(mat,numRows,rows,diag,x,b));
6477   PetscCall(ISRestoreIndices(is,&rows));
6478   PetscFunctionReturn(0);
6479 }
6480 
6481 /*@C
6482    MatGetSize - Returns the numbers of rows and columns in a matrix.
6483 
6484    Not Collective
6485 
6486    Input Parameter:
6487 .  mat - the matrix
6488 
6489    Output Parameters:
6490 +  m - the number of global rows
6491 -  n - the number of global columns
6492 
6493    Note: both output parameters can be NULL on input.
6494 
6495    Level: beginner
6496 
6497 .seealso: `MatGetLocalSize()`
6498 @*/
6499 PetscErrorCode MatGetSize(Mat mat,PetscInt *m,PetscInt *n)
6500 {
6501   PetscFunctionBegin;
6502   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6503   if (m) *m = mat->rmap->N;
6504   if (n) *n = mat->cmap->N;
6505   PetscFunctionReturn(0);
6506 }
6507 
6508 /*@C
6509    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6510    of a matrix. For all matrices this is the local size of the left and right vectors as returned by MatCreateVecs().
6511 
6512    Not Collective
6513 
6514    Input Parameter:
6515 .  mat - the matrix
6516 
6517    Output Parameters:
6518 +  m - the number of local rows, use `NULL` to not obtain this value
6519 -  n - the number of local columns, use `NULL` to not obtain this value
6520 
6521    Level: beginner
6522 
6523 .seealso: `MatGetSize()`
6524 @*/
6525 PetscErrorCode MatGetLocalSize(Mat mat,PetscInt *m,PetscInt *n)
6526 {
6527   PetscFunctionBegin;
6528   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6529   if (m) PetscValidIntPointer(m,2);
6530   if (n) PetscValidIntPointer(n,3);
6531   if (m) *m = mat->rmap->n;
6532   if (n) *n = mat->cmap->n;
6533   PetscFunctionReturn(0);
6534 }
6535 
6536 /*@C
6537    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6538    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6539 
6540    Not Collective, unless matrix has not been allocated, then collective on Mat
6541 
6542    Input Parameter:
6543 .  mat - the matrix
6544 
6545    Output Parameters:
6546 +  m - the global index of the first local column, use `NULL` to not obtain this value
6547 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6548 
6549    Level: developer
6550 
6551 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6552 
6553 @*/
6554 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat,PetscInt *m,PetscInt *n)
6555 {
6556   PetscFunctionBegin;
6557   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6558   PetscValidType(mat,1);
6559   if (m) PetscValidIntPointer(m,2);
6560   if (n) PetscValidIntPointer(n,3);
6561   MatCheckPreallocated(mat,1);
6562   if (m) *m = mat->cmap->rstart;
6563   if (n) *n = mat->cmap->rend;
6564   PetscFunctionReturn(0);
6565 }
6566 
6567 /*@C
6568    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6569    this MPI rank. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6570    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6571 
6572    Not Collective
6573 
6574    Input Parameter:
6575 .  mat - the matrix
6576 
6577    Output Parameters:
6578 +  m - the global index of the first local row, use `NULL` to not obtain this value
6579 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6580 
6581    Note:
6582   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6583   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6584   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6585 
6586    Level: beginner
6587 
6588 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6589           `PetscLayout`
6590 
6591 @*/
6592 PetscErrorCode MatGetOwnershipRange(Mat mat,PetscInt *m,PetscInt *n)
6593 {
6594   PetscFunctionBegin;
6595   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6596   PetscValidType(mat,1);
6597   if (m) PetscValidIntPointer(m,2);
6598   if (n) PetscValidIntPointer(n,3);
6599   MatCheckPreallocated(mat,1);
6600   if (m) *m = mat->rmap->rstart;
6601   if (n) *n = mat->rmap->rend;
6602   PetscFunctionReturn(0);
6603 }
6604 
6605 /*@C
6606    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6607    each process. For all matrices  it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix
6608    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6609 
6610    Not Collective, unless matrix has not been allocated, then collective on Mat
6611 
6612    Input Parameters:
6613 .  mat - the matrix
6614 
6615    Output Parameters:
6616 .  ranges - start of each processors portion plus one more than the total length at the end
6617 
6618    Level: beginner
6619 
6620 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6621 
6622 @*/
6623 PetscErrorCode MatGetOwnershipRanges(Mat mat,const PetscInt **ranges)
6624 {
6625   PetscFunctionBegin;
6626   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6627   PetscValidType(mat,1);
6628   MatCheckPreallocated(mat,1);
6629   PetscCall(PetscLayoutGetRanges(mat->rmap,ranges));
6630   PetscFunctionReturn(0);
6631 }
6632 
6633 /*@C
6634    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6635    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6636 
6637    Not Collective, unless matrix has not been allocated, then collective on Mat
6638 
6639    Input Parameters:
6640 .  mat - the matrix
6641 
6642    Output Parameters:
6643 .  ranges - start of each processors portion plus one more then the total length at the end
6644 
6645    Level: beginner
6646 
6647 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6648 
6649 @*/
6650 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat,const PetscInt **ranges)
6651 {
6652   PetscFunctionBegin;
6653   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6654   PetscValidType(mat,1);
6655   MatCheckPreallocated(mat,1);
6656   PetscCall(PetscLayoutGetRanges(mat->cmap,ranges));
6657   PetscFunctionReturn(0);
6658 }
6659 
6660 /*@C
6661    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6662    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6663    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6664 
6665    Not Collective
6666 
6667    Input Parameter:
6668 .  A - matrix
6669 
6670    Output Parameters:
6671 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6672 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6673 
6674    Level: intermediate
6675 
6676 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6677 @*/
6678 PetscErrorCode MatGetOwnershipIS(Mat A,IS *rows,IS *cols)
6679 {
6680   PetscErrorCode (*f)(Mat,IS*,IS*);
6681 
6682   PetscFunctionBegin;
6683   MatCheckPreallocated(A,1);
6684   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatGetOwnershipIS_C",&f));
6685   if (f) {
6686     PetscCall((*f)(A,rows,cols));
6687   } else {   /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6688     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->rmap->n,A->rmap->rstart,1,rows));
6689     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF,A->cmap->N,0,1,cols));
6690   }
6691   PetscFunctionReturn(0);
6692 }
6693 
6694 /*@C
6695    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix.
6696    Uses levels of fill only, not drop tolerance. Use MatLUFactorNumeric()
6697    to complete the factorization.
6698 
6699    Collective on Mat
6700 
6701    Input Parameters:
6702 +  mat - the matrix
6703 .  row - row permutation
6704 .  column - column permutation
6705 -  info - structure containing
6706 $      levels - number of levels of fill.
6707 $      expected fill - as ratio of original fill.
6708 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6709                 missing diagonal entries)
6710 
6711    Output Parameters:
6712 .  fact - new matrix that has been symbolically factored
6713 
6714    Notes:
6715     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
6716 
6717    Most users should employ the simplified KSP interface for linear solvers
6718    instead of working directly with matrix algebra routines such as this.
6719    See, e.g., KSPCreate().
6720 
6721    Level: developer
6722 
6723 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6724           `MatGetOrdering()`, `MatFactorInfo`
6725 
6726     Note: this uses the definition of level of fill as in Y. Saad, 2003
6727 
6728     Developer Note: fortran interface is not autogenerated as the f90
6729     interface definition cannot be generated correctly [due to MatFactorInfo]
6730 
6731    References:
6732 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6733 @*/
6734 PetscErrorCode MatILUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
6735 {
6736   PetscFunctionBegin;
6737   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6738   PetscValidType(mat,2);
6739   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,3);
6740   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,4);
6741   PetscValidPointer(info,5);
6742   PetscValidPointer(fact,1);
6743   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels of fill negative %" PetscInt_FMT,(PetscInt)info->levels);
6744   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6745   if (!fact->ops->ilufactorsymbolic) {
6746     MatSolverType stype;
6747     PetscCall(MatFactorGetSolverType(fact,&stype));
6748     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ILU using solver type %s",((PetscObject)mat)->type_name,stype);
6749   }
6750   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6751   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6752   MatCheckPreallocated(mat,2);
6753 
6754   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic,mat,row,col,0));
6755   PetscCall((fact->ops->ilufactorsymbolic)(fact,mat,row,col,info));
6756   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic,mat,row,col,0));
6757   PetscFunctionReturn(0);
6758 }
6759 
6760 /*@C
6761    MatICCFactorSymbolic - Performs symbolic incomplete
6762    Cholesky factorization for a symmetric matrix.  Use
6763    MatCholeskyFactorNumeric() to complete the factorization.
6764 
6765    Collective on Mat
6766 
6767    Input Parameters:
6768 +  mat - the matrix
6769 .  perm - row and column permutation
6770 -  info - structure containing
6771 $      levels - number of levels of fill.
6772 $      expected fill - as ratio of original fill.
6773 
6774    Output Parameter:
6775 .  fact - the factored matrix
6776 
6777    Notes:
6778    Most users should employ the KSP interface for linear solvers
6779    instead of working directly with matrix algebra routines such as this.
6780    See, e.g., KSPCreate().
6781 
6782    Level: developer
6783 
6784 .seealso: `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6785 
6786     Note: this uses the definition of level of fill as in Y. Saad, 2003
6787 
6788     Developer Note: fortran interface is not autogenerated as the f90
6789     interface definition cannot be generated correctly [due to MatFactorInfo]
6790 
6791    References:
6792 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6793 @*/
6794 PetscErrorCode MatICCFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
6795 {
6796   PetscFunctionBegin;
6797   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
6798   PetscValidType(mat,2);
6799   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,3);
6800   PetscValidPointer(info,4);
6801   PetscValidPointer(fact,1);
6802   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6803   PetscCheck(info->levels >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels negative %" PetscInt_FMT,(PetscInt) info->levels);
6804   PetscCheck(info->fill >= 1.0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6805   if (!(fact)->ops->iccfactorsymbolic) {
6806     MatSolverType stype;
6807     PetscCall(MatFactorGetSolverType(fact,&stype));
6808     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ICC using solver type %s",((PetscObject)mat)->type_name,stype);
6809   }
6810   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6811   MatCheckPreallocated(mat,2);
6812 
6813   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic,mat,perm,0,0));
6814   PetscCall((fact->ops->iccfactorsymbolic)(fact,mat,perm,info));
6815   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic,mat,perm,0,0));
6816   PetscFunctionReturn(0);
6817 }
6818 
6819 /*@C
6820    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6821    points to an array of valid matrices, they may be reused to store the new
6822    submatrices.
6823 
6824    Collective on Mat
6825 
6826    Input Parameters:
6827 +  mat - the matrix
6828 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6829 .  irow, icol - index sets of rows and columns to extract
6830 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6831 
6832    Output Parameter:
6833 .  submat - the array of submatrices
6834 
6835    Notes:
6836    MatCreateSubMatrices() can extract ONLY sequential submatrices
6837    (from both sequential and parallel matrices). Use MatCreateSubMatrix()
6838    to extract a parallel submatrix.
6839 
6840    Some matrix types place restrictions on the row and column
6841    indices, such as that they be sorted or that they be equal to each other.
6842 
6843    The index sets may not have duplicate entries.
6844 
6845    When extracting submatrices from a parallel matrix, each processor can
6846    form a different submatrix by setting the rows and columns of its
6847    individual index sets according to the local submatrix desired.
6848 
6849    When finished using the submatrices, the user should destroy
6850    them with MatDestroySubMatrices().
6851 
6852    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
6853    original matrix has not changed from that last call to MatCreateSubMatrices().
6854 
6855    This routine creates the matrices in submat; you should NOT create them before
6856    calling it. It also allocates the array of matrix pointers submat.
6857 
6858    For BAIJ matrices the index sets must respect the block structure, that is if they
6859    request one row/column in a block, they must request all rows/columns that are in
6860    that block. For example, if the block size is 2 you cannot request just row 0 and
6861    column 0.
6862 
6863    Fortran Note:
6864    The Fortran interface is slightly different from that given below; it
6865    requires one to pass in  as submat a Mat (integer) array of size at least n+1.
6866 
6867    Level: advanced
6868 
6869 .seealso: `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6870 @*/
6871 PetscErrorCode MatCreateSubMatrices(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
6872 {
6873   PetscInt       i;
6874   PetscBool      eq;
6875 
6876   PetscFunctionBegin;
6877   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6878   PetscValidType(mat,1);
6879   if (n) {
6880     PetscValidPointer(irow,3);
6881     for (i=0; i<n; i++) PetscValidHeaderSpecific(irow[i],IS_CLASSID,3);
6882     PetscValidPointer(icol,4);
6883     for (i=0; i<n; i++) PetscValidHeaderSpecific(icol[i],IS_CLASSID,4);
6884   }
6885   PetscValidPointer(submat,6);
6886   if (n && scall == MAT_REUSE_MATRIX) {
6887     PetscValidPointer(*submat,6);
6888     for (i=0; i<n; i++) PetscValidHeaderSpecific((*submat)[i],MAT_CLASSID,6);
6889   }
6890   PetscCheck(mat->ops->createsubmatrices,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6891   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6892   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6893   MatCheckPreallocated(mat,1);
6894   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
6895   PetscCall((*mat->ops->createsubmatrices)(mat,n,irow,icol,scall,submat));
6896   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
6897   for (i=0; i<n; i++) {
6898     (*submat)[i]->factortype = MAT_FACTOR_NONE;  /* in case in place factorization was previously done on submatrix */
6899     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
6900     if (eq) {
6901       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
6902     }
6903 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6904     if (mat->boundtocpu && mat->bindingpropagates) {
6905       PetscCall(MatBindToCPU((*submat)[i],PETSC_TRUE));
6906       PetscCall(MatSetBindingPropagates((*submat)[i],PETSC_TRUE));
6907     }
6908 #endif
6909   }
6910   PetscFunctionReturn(0);
6911 }
6912 
6913 /*@C
6914    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of IS that may live on subcomms).
6915 
6916    Collective on Mat
6917 
6918    Input Parameters:
6919 +  mat - the matrix
6920 .  n   - the number of submatrixes to be extracted
6921 .  irow, icol - index sets of rows and columns to extract
6922 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6923 
6924    Output Parameter:
6925 .  submat - the array of submatrices
6926 
6927    Level: advanced
6928 
6929 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6930 @*/
6931 PetscErrorCode MatCreateSubMatricesMPI(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
6932 {
6933   PetscInt       i;
6934   PetscBool      eq;
6935 
6936   PetscFunctionBegin;
6937   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6938   PetscValidType(mat,1);
6939   if (n) {
6940     PetscValidPointer(irow,3);
6941     PetscValidHeaderSpecific(*irow,IS_CLASSID,3);
6942     PetscValidPointer(icol,4);
6943     PetscValidHeaderSpecific(*icol,IS_CLASSID,4);
6944   }
6945   PetscValidPointer(submat,6);
6946   if (n && scall == MAT_REUSE_MATRIX) {
6947     PetscValidPointer(*submat,6);
6948     PetscValidHeaderSpecific(**submat,MAT_CLASSID,6);
6949   }
6950   PetscCheck(mat->ops->createsubmatricesmpi,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6951   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6952   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6953   MatCheckPreallocated(mat,1);
6954 
6955   PetscCall(PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0));
6956   PetscCall((*mat->ops->createsubmatricesmpi)(mat,n,irow,icol,scall,submat));
6957   PetscCall(PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0));
6958   for (i=0; i<n; i++) {
6959     PetscCall(ISEqualUnsorted(irow[i],icol[i],&eq));
6960     if (eq) {
6961       PetscCall(MatPropagateSymmetryOptions(mat,(*submat)[i]));
6962     }
6963   }
6964   PetscFunctionReturn(0);
6965 }
6966 
6967 /*@C
6968    MatDestroyMatrices - Destroys an array of matrices.
6969 
6970    Collective on Mat
6971 
6972    Input Parameters:
6973 +  n - the number of local matrices
6974 -  mat - the matrices (note that this is a pointer to the array of matrices)
6975 
6976    Level: advanced
6977 
6978     Notes:
6979     Frees not only the matrices, but also the array that contains the matrices
6980            In Fortran will not free the array.
6981 
6982 .seealso: `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6983 @*/
6984 PetscErrorCode MatDestroyMatrices(PetscInt n,Mat *mat[])
6985 {
6986   PetscInt       i;
6987 
6988   PetscFunctionBegin;
6989   if (!*mat) PetscFunctionReturn(0);
6990   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
6991   PetscValidPointer(mat,2);
6992 
6993   for (i=0; i<n; i++) {
6994     PetscCall(MatDestroy(&(*mat)[i]));
6995   }
6996 
6997   /* memory is allocated even if n = 0 */
6998   PetscCall(PetscFree(*mat));
6999   PetscFunctionReturn(0);
7000 }
7001 
7002 /*@C
7003    MatDestroySubMatrices - Destroys a set of matrices obtained with MatCreateSubMatrices().
7004 
7005    Collective on Mat
7006 
7007    Input Parameters:
7008 +  n - the number of local matrices
7009 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7010                        sequence of MatCreateSubMatrices())
7011 
7012    Level: advanced
7013 
7014     Notes:
7015     Frees not only the matrices, but also the array that contains the matrices
7016            In Fortran will not free the array.
7017 
7018 .seealso: `MatCreateSubMatrices()`
7019 @*/
7020 PetscErrorCode MatDestroySubMatrices(PetscInt n,Mat *mat[])
7021 {
7022   Mat            mat0;
7023 
7024   PetscFunctionBegin;
7025   if (!*mat) PetscFunctionReturn(0);
7026   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7027   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %" PetscInt_FMT,n);
7028   PetscValidPointer(mat,2);
7029 
7030   mat0 = (*mat)[0];
7031   if (mat0 && mat0->ops->destroysubmatrices) {
7032     PetscCall((mat0->ops->destroysubmatrices)(n,mat));
7033   } else {
7034     PetscCall(MatDestroyMatrices(n,mat));
7035   }
7036   PetscFunctionReturn(0);
7037 }
7038 
7039 /*@C
7040    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7041 
7042    Collective on Mat
7043 
7044    Input Parameters:
7045 .  mat - the matrix
7046 
7047    Output Parameter:
7048 .  matstruct - the sequential matrix with the nonzero structure of mat
7049 
7050   Level: intermediate
7051 
7052 .seealso: `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7053 @*/
7054 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat,Mat *matstruct)
7055 {
7056   PetscFunctionBegin;
7057   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7058   PetscValidPointer(matstruct,2);
7059 
7060   PetscValidType(mat,1);
7061   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7062   MatCheckPreallocated(mat,1);
7063 
7064   PetscCheck(mat->ops->getseqnonzerostructure,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)mat)->type_name);
7065   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7066   PetscCall((*mat->ops->getseqnonzerostructure)(mat,matstruct));
7067   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure,mat,0,0,0));
7068   PetscFunctionReturn(0);
7069 }
7070 
7071 /*@C
7072    MatDestroySeqNonzeroStructure - Destroys matrix obtained with MatGetSeqNonzeroStructure().
7073 
7074    Collective on Mat
7075 
7076    Input Parameters:
7077 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7078                        sequence of MatGetSequentialNonzeroStructure())
7079 
7080    Level: advanced
7081 
7082     Notes:
7083     Frees not only the matrices, but also the array that contains the matrices
7084 
7085 .seealso: `MatGetSeqNonzeroStructure()`
7086 @*/
7087 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7088 {
7089   PetscFunctionBegin;
7090   PetscValidPointer(mat,1);
7091   PetscCall(MatDestroy(mat));
7092   PetscFunctionReturn(0);
7093 }
7094 
7095 /*@
7096    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7097    replaces the index sets by larger ones that represent submatrices with
7098    additional overlap.
7099 
7100    Collective on Mat
7101 
7102    Input Parameters:
7103 +  mat - the matrix
7104 .  n   - the number of index sets
7105 .  is  - the array of index sets (these index sets will changed during the call)
7106 -  ov  - the additional overlap requested
7107 
7108    Options Database:
7109 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7110 
7111    Level: developer
7112 
7113    Developer Note:
7114    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.
7115 
7116 .seealso: `MatCreateSubMatrices()`
7117 @*/
7118 PetscErrorCode MatIncreaseOverlap(Mat mat,PetscInt n,IS is[],PetscInt ov)
7119 {
7120   PetscInt       i,bs,cbs;
7121 
7122   PetscFunctionBegin;
7123   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7124   PetscValidType(mat,1);
7125   PetscValidLogicalCollectiveInt(mat,n,2);
7126   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7127   if (n) {
7128     PetscValidPointer(is,3);
7129     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i],IS_CLASSID,3);
7130   }
7131   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7132   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7133   MatCheckPreallocated(mat,1);
7134 
7135   if (!ov || !n) PetscFunctionReturn(0);
7136   PetscCheck(mat->ops->increaseoverlap,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7137   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7138   PetscCall((*mat->ops->increaseoverlap)(mat,n,is,ov));
7139   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7140   PetscCall(MatGetBlockSizes(mat,&bs,&cbs));
7141   if (bs == cbs) {
7142     for (i=0; i<n; i++) {
7143       PetscCall(ISSetBlockSize(is[i],bs));
7144     }
7145   }
7146   PetscFunctionReturn(0);
7147 }
7148 
7149 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat,IS*,PetscInt);
7150 
7151 /*@
7152    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7153    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7154    additional overlap.
7155 
7156    Collective on Mat
7157 
7158    Input Parameters:
7159 +  mat - the matrix
7160 .  n   - the number of index sets
7161 .  is  - the array of index sets (these index sets will changed during the call)
7162 -  ov  - the additional overlap requested
7163 
7164    Options Database:
7165 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7166 
7167    Level: developer
7168 
7169 .seealso: `MatCreateSubMatrices()`
7170 @*/
7171 PetscErrorCode MatIncreaseOverlapSplit(Mat mat,PetscInt n,IS is[],PetscInt ov)
7172 {
7173   PetscInt       i;
7174 
7175   PetscFunctionBegin;
7176   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7177   PetscValidType(mat,1);
7178   PetscCheck(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %" PetscInt_FMT,n);
7179   if (n) {
7180     PetscValidPointer(is,3);
7181     PetscValidHeaderSpecific(*is,IS_CLASSID,3);
7182   }
7183   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7184   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7185   MatCheckPreallocated(mat,1);
7186   if (!ov) PetscFunctionReturn(0);
7187   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0));
7188   for (i=0; i<n; i++) {
7189     PetscCall(MatIncreaseOverlapSplit_Single(mat,&is[i],ov));
7190   }
7191   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0));
7192   PetscFunctionReturn(0);
7193 }
7194 
7195 /*@
7196    MatGetBlockSize - Returns the matrix block size.
7197 
7198    Not Collective
7199 
7200    Input Parameter:
7201 .  mat - the matrix
7202 
7203    Output Parameter:
7204 .  bs - block size
7205 
7206    Notes:
7207     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7208 
7209    If the block size has not been set yet this routine returns 1.
7210 
7211    Level: intermediate
7212 
7213 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7214 @*/
7215 PetscErrorCode MatGetBlockSize(Mat mat,PetscInt *bs)
7216 {
7217   PetscFunctionBegin;
7218   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7219   PetscValidIntPointer(bs,2);
7220   *bs = PetscAbs(mat->rmap->bs);
7221   PetscFunctionReturn(0);
7222 }
7223 
7224 /*@
7225    MatGetBlockSizes - Returns the matrix block row and column sizes.
7226 
7227    Not Collective
7228 
7229    Input Parameter:
7230 .  mat - the matrix
7231 
7232    Output Parameters:
7233 +  rbs - row block size
7234 -  cbs - column block size
7235 
7236    Notes:
7237     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7238     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7239 
7240    If a block size has not been set yet this routine returns 1.
7241 
7242    Level: intermediate
7243 
7244 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7245 @*/
7246 PetscErrorCode MatGetBlockSizes(Mat mat,PetscInt *rbs, PetscInt *cbs)
7247 {
7248   PetscFunctionBegin;
7249   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7250   if (rbs) PetscValidIntPointer(rbs,2);
7251   if (cbs) PetscValidIntPointer(cbs,3);
7252   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7253   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7254   PetscFunctionReturn(0);
7255 }
7256 
7257 /*@
7258    MatSetBlockSize - Sets the matrix block size.
7259 
7260    Logically Collective on Mat
7261 
7262    Input Parameters:
7263 +  mat - the matrix
7264 -  bs - block size
7265 
7266    Notes:
7267     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7268     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7269 
7270     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block size
7271     is compatible with the matrix local sizes.
7272 
7273    Level: intermediate
7274 
7275 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7276 @*/
7277 PetscErrorCode MatSetBlockSize(Mat mat,PetscInt bs)
7278 {
7279   PetscFunctionBegin;
7280   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7281   PetscValidLogicalCollectiveInt(mat,bs,2);
7282   PetscCall(MatSetBlockSizes(mat,bs,bs));
7283   PetscFunctionReturn(0);
7284 }
7285 
7286 typedef struct {
7287   PetscInt         n;
7288   IS               *is;
7289   Mat              *mat;
7290   PetscObjectState nonzerostate;
7291   Mat              C;
7292 } EnvelopeData;
7293 
7294 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7295 {
7296   for (PetscInt i=0; i<edata->n; i++) {
7297     PetscCall(ISDestroy(&edata->is[i]));
7298   }
7299   PetscCall(PetscFree(edata->is));
7300   PetscCall(PetscFree(edata));
7301   return 0;
7302 }
7303 
7304 /*
7305    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7306          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7307 
7308    Collective on mat
7309 
7310    Input Parameter:
7311 .  mat - the matrix
7312 
7313    Notes:
7314      There can be zeros within the blocks
7315 
7316      The blocks can overlap between processes, including laying on more than two processes
7317 
7318 */
7319 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7320 {
7321   PetscInt                    n,*sizes,*starts,i = 0,env = 0, tbs = 0, lblocks = 0,rstart,II,ln = 0,cnt = 0,cstart,cend;
7322   PetscInt                    *diag,*odiag,sc;
7323   VecScatter                  scatter;
7324   PetscScalar                 *seqv;
7325   const PetscScalar           *parv;
7326   const PetscInt              *ia,*ja;
7327   PetscBool                   set,flag,done;
7328   Mat                         AA = mat,A;
7329   MPI_Comm                    comm;
7330   PetscMPIInt                 rank,size,tag;
7331   MPI_Status                  status;
7332   PetscContainer              container;
7333   EnvelopeData                *edata;
7334   Vec                         seq,par;
7335   IS                          isglobal;
7336 
7337   PetscFunctionBegin;
7338   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7339   PetscCall(MatIsSymmetricKnown(mat,&set,&flag));
7340   if (!set || !flag) {
7341     /* TOO: only needs nonzero structure of transpose */
7342     PetscCall(MatTranspose(mat,MAT_INITIAL_MATRIX,&AA));
7343     PetscCall(MatAXPY(AA,1.0,mat,DIFFERENT_NONZERO_PATTERN));
7344   }
7345   PetscCall(MatAIJGetLocalMat(AA,&A));
7346   PetscCall(MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7347   PetscCheck(done,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unable to get IJ structure from matrix");
7348 
7349   PetscCall(MatGetLocalSize(mat,&n,NULL));
7350   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag));
7351   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
7352   PetscCallMPI(MPI_Comm_size(comm,&size));
7353   PetscCallMPI(MPI_Comm_rank(comm,&rank));
7354 
7355   PetscCall(PetscMalloc2(n,&sizes,n,&starts));
7356 
7357   if (rank > 0) {
7358     PetscCallMPI(MPI_Recv(&env,1,MPIU_INT,rank-1,tag,comm,&status));
7359     PetscCallMPI(MPI_Recv(&tbs,1,MPIU_INT,rank-1,tag,comm,&status));
7360   }
7361   PetscCall(MatGetOwnershipRange(mat,&rstart,NULL));
7362   for (i=0; i<n; i++) {
7363     env = PetscMax(env,ja[ia[i+1]-1]);
7364     II = rstart + i;
7365     if (env == II) {
7366       starts[lblocks]  = tbs;
7367       sizes[lblocks++] = 1 + II - tbs;
7368       tbs = 1 + II;
7369     }
7370   }
7371   if (rank < size-1) {
7372     PetscCallMPI(MPI_Send(&env,1,MPIU_INT,rank+1,tag,comm));
7373     PetscCallMPI(MPI_Send(&tbs,1,MPIU_INT,rank+1,tag,comm));
7374   }
7375 
7376   PetscCall(MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ia,&ja,&done));
7377   if (!set || !flag) {
7378     PetscCall(MatDestroy(&AA));
7379   }
7380   PetscCall(MatDestroy(&A));
7381 
7382   PetscCall(PetscNew(&edata));
7383   PetscCall(MatGetNonzeroState(mat,&edata->nonzerostate));
7384   edata->n = lblocks;
7385   /* create IS needed for extracting blocks from the original matrix */
7386   PetscCall(PetscMalloc1(lblocks,&edata->is));
7387   for (PetscInt i=0; i<lblocks; i++) {
7388     PetscCall(ISCreateStride(PETSC_COMM_SELF,sizes[i],starts[i],1,&edata->is[i]));
7389   }
7390 
7391   /* Create the resulting inverse matrix structure with preallocation information */
7392   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&edata->C));
7393   PetscCall(MatSetSizes(edata->C,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N));
7394   PetscCall(MatSetBlockSizesFromMats(edata->C,mat,mat));
7395   PetscCall(MatSetType(edata->C,MATAIJ));
7396 
7397   /* Communicate the start and end of each row, from each block to the correct rank */
7398   /* TODO: Use PetscSF instead of VecScatter */
7399   for (PetscInt i=0; i<lblocks; i++) ln += sizes[i];
7400   PetscCall(VecCreateSeq(PETSC_COMM_SELF,2*ln,&seq));
7401   PetscCall(VecGetArrayWrite(seq,&seqv));
7402   for (PetscInt i=0; i<lblocks; i++) {
7403     for (PetscInt j=0; j<sizes[i]; j++) {
7404       seqv[cnt]   = starts[i];
7405       seqv[cnt+1] = starts[i] + sizes[i];
7406       cnt += 2;
7407     }
7408   }
7409   PetscCall(VecRestoreArrayWrite(seq,&seqv));
7410   PetscCallMPI(MPI_Scan(&cnt,&sc,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
7411   sc -= cnt;
7412   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat),2*mat->rmap->n,2*mat->rmap->N,&par));
7413   PetscCall(ISCreateStride(PETSC_COMM_SELF,cnt,sc,1,&isglobal));
7414   PetscCall(VecScatterCreate(seq, NULL  ,par, isglobal,&scatter));
7415   PetscCall(ISDestroy(&isglobal));
7416   PetscCall(VecScatterBegin(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7417   PetscCall(VecScatterEnd(scatter,seq,par,INSERT_VALUES,SCATTER_FORWARD));
7418   PetscCall(VecScatterDestroy(&scatter));
7419   PetscCall(VecDestroy(&seq));
7420   PetscCall(MatGetOwnershipRangeColumn(mat,&cstart,&cend));
7421   PetscCall(PetscMalloc2(mat->rmap->n,&diag,mat->rmap->n,&odiag));
7422   PetscCall(VecGetArrayRead(par,&parv));
7423   cnt = 0;
7424   PetscCall(MatGetSize(mat,NULL,&n));
7425   for (PetscInt i=0; i<mat->rmap->n; i++) {
7426     PetscInt start,end,d = 0,od = 0;
7427 
7428     start = (PetscInt)PetscRealPart(parv[cnt]);
7429     end   = (PetscInt)PetscRealPart(parv[cnt+1]);
7430     cnt  += 2;
7431 
7432     if (start < cstart) {od += cstart - start + n - cend; d += cend - cstart;}
7433     else if (start < cend) {od += n - cend; d += cend - start;}
7434     else od += n - start;
7435     if (end <= cstart) {od -= cstart - end + n - cend; d -= cend - cstart;}
7436     else if (end < cend) {od -= n - cend; d -= cend - end;}
7437     else od -= n - end;
7438 
7439     odiag[i] = od;
7440     diag[i]  = d;
7441   }
7442   PetscCall(VecRestoreArrayRead(par,&parv));
7443   PetscCall(VecDestroy(&par));
7444   PetscCall(MatXAIJSetPreallocation(edata->C,mat->rmap->bs,diag,odiag,NULL,NULL));
7445   PetscCall(PetscFree2(diag,odiag));
7446   PetscCall(PetscFree2(sizes,starts));
7447 
7448   PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&container));
7449   PetscCall(PetscContainerSetPointer(container,edata));
7450   PetscCall(PetscContainerSetUserDestroy(container,(PetscErrorCode (*)(void*))EnvelopeDataDestroy));
7451   PetscCall(PetscObjectCompose((PetscObject)mat,"EnvelopeData",(PetscObject)container));
7452   PetscCall(PetscObjectDereference((PetscObject)container));
7453   PetscFunctionReturn(0);
7454 }
7455 
7456 /*@
7457   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7458 
7459   Collective on Mat
7460 
7461   Input Parameters:
7462 . A - the matrix
7463 
7464   Output Parameters:
7465 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7466 
7467   Notes:
7468      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7469 
7470   Level: advanced
7471 
7472 .seealso: MatInvertBlockDiagonal(), MatComputeBlockDiagonal()
7473 @*/
7474 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A,MatReuse reuse, Mat *C)
7475 {
7476   PetscContainer    container;
7477   EnvelopeData      *edata;
7478   PetscObjectState  nonzerostate;
7479 
7480   PetscFunctionBegin;
7481   PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7482   if (!container) {
7483     PetscCall(MatComputeVariableBlockEnvelope(A));
7484     PetscCall(PetscObjectQuery((PetscObject)A,"EnvelopeData",(PetscObject*)&container));
7485   }
7486   PetscCall(PetscContainerGetPointer(container,(void**)&edata));
7487   PetscCall(MatGetNonzeroState(A,&nonzerostate));
7488   PetscCheck(nonzerostate <= edata->nonzerostate,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Cannot handle changes to matrix nonzero structure");
7489   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"C matrix must be the same as previously output");
7490 
7491   PetscCall(MatCreateSubMatrices(A,edata->n,edata->is,edata->is,MAT_INITIAL_MATRIX,&edata->mat));
7492   *C   = edata->C;
7493 
7494   for (PetscInt i=0; i<edata->n; i++) {
7495     Mat         D;
7496     PetscScalar *dvalues;
7497 
7498     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE,MAT_INITIAL_MATRIX,&D));
7499     PetscCall(MatSetOption(*C,MAT_ROW_ORIENTED,PETSC_FALSE));
7500     PetscCall(MatSeqDenseInvert(D));
7501     PetscCall(MatDenseGetArray(D,&dvalues));
7502     PetscCall(MatSetValuesIS(*C,edata->is[i],edata->is[i],dvalues,INSERT_VALUES));
7503     PetscCall(MatDestroy(&D));
7504   }
7505   PetscCall(MatDestroySubMatrices(edata->n,&edata->mat));
7506   PetscCall(MatAssemblyBegin(*C,MAT_FINAL_ASSEMBLY));
7507   PetscCall(MatAssemblyEnd(*C,MAT_FINAL_ASSEMBLY));
7508   PetscFunctionReturn(0);
7509 }
7510 
7511 /*@
7512    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7513 
7514    Logically Collective on Mat
7515 
7516    Input Parameters:
7517 +  mat - the matrix
7518 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7519 -  bsizes - the block sizes
7520 
7521    Notes:
7522     Currently used by PCVPBJACOBI for AIJ matrices
7523 
7524     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.
7525 
7526    Level: intermediate
7527 
7528 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7529 @*/
7530 PetscErrorCode MatSetVariableBlockSizes(Mat mat,PetscInt nblocks,PetscInt *bsizes)
7531 {
7532   PetscInt       i,ncnt = 0, nlocal;
7533 
7534   PetscFunctionBegin;
7535   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7536   PetscCheck(nblocks >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Number of local blocks must be great than or equal to zero");
7537   PetscCall(MatGetLocalSize(mat,&nlocal,NULL));
7538   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
7539   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);
7540   PetscCall(PetscFree(mat->bsizes));
7541   mat->nblocks = nblocks;
7542   PetscCall(PetscMalloc1(nblocks,&mat->bsizes));
7543   PetscCall(PetscArraycpy(mat->bsizes,bsizes,nblocks));
7544   PetscFunctionReturn(0);
7545 }
7546 
7547 /*@C
7548    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7549 
7550    Logically Collective on Mat
7551 
7552    Input Parameter:
7553 .  mat - the matrix
7554 
7555    Output Parameters:
7556 +  nblocks - the number of blocks on this process
7557 -  bsizes - the block sizes
7558 
7559    Notes: Currently not supported from Fortran
7560 
7561    Level: intermediate
7562 
7563 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7564 @*/
7565 PetscErrorCode MatGetVariableBlockSizes(Mat mat,PetscInt *nblocks,const PetscInt **bsizes)
7566 {
7567   PetscFunctionBegin;
7568   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7569   *nblocks = mat->nblocks;
7570   *bsizes  = mat->bsizes;
7571   PetscFunctionReturn(0);
7572 }
7573 
7574 /*@
7575    MatSetBlockSizes - Sets the matrix block row and column sizes.
7576 
7577    Logically Collective on Mat
7578 
7579    Input Parameters:
7580 +  mat - the matrix
7581 .  rbs - row block size
7582 -  cbs - column block size
7583 
7584    Notes:
7585     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7586     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7587     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7588 
7589     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block sizes
7590     are compatible with the matrix local sizes.
7591 
7592     The row and column block size determine the blocksize of the "row" and "column" vectors returned by MatCreateVecs().
7593 
7594    Level: intermediate
7595 
7596 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7597 @*/
7598 PetscErrorCode MatSetBlockSizes(Mat mat,PetscInt rbs,PetscInt cbs)
7599 {
7600   PetscFunctionBegin;
7601   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7602   PetscValidLogicalCollectiveInt(mat,rbs,2);
7603   PetscValidLogicalCollectiveInt(mat,cbs,3);
7604   if (mat->ops->setblocksizes) PetscCall((*mat->ops->setblocksizes)(mat,rbs,cbs));
7605   if (mat->rmap->refcnt) {
7606     ISLocalToGlobalMapping l2g = NULL;
7607     PetscLayout            nmap = NULL;
7608 
7609     PetscCall(PetscLayoutDuplicate(mat->rmap,&nmap));
7610     if (mat->rmap->mapping) {
7611       PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping,&l2g));
7612     }
7613     PetscCall(PetscLayoutDestroy(&mat->rmap));
7614     mat->rmap = nmap;
7615     mat->rmap->mapping = l2g;
7616   }
7617   if (mat->cmap->refcnt) {
7618     ISLocalToGlobalMapping l2g = NULL;
7619     PetscLayout            nmap = NULL;
7620 
7621     PetscCall(PetscLayoutDuplicate(mat->cmap,&nmap));
7622     if (mat->cmap->mapping) {
7623       PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping,&l2g));
7624     }
7625     PetscCall(PetscLayoutDestroy(&mat->cmap));
7626     mat->cmap = nmap;
7627     mat->cmap->mapping = l2g;
7628   }
7629   PetscCall(PetscLayoutSetBlockSize(mat->rmap,rbs));
7630   PetscCall(PetscLayoutSetBlockSize(mat->cmap,cbs));
7631   PetscFunctionReturn(0);
7632 }
7633 
7634 /*@
7635    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7636 
7637    Logically Collective on Mat
7638 
7639    Input Parameters:
7640 +  mat - the matrix
7641 .  fromRow - matrix from which to copy row block size
7642 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7643 
7644    Level: developer
7645 
7646 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7647 @*/
7648 PetscErrorCode MatSetBlockSizesFromMats(Mat mat,Mat fromRow,Mat fromCol)
7649 {
7650   PetscFunctionBegin;
7651   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7652   PetscValidHeaderSpecific(fromRow,MAT_CLASSID,2);
7653   PetscValidHeaderSpecific(fromCol,MAT_CLASSID,3);
7654   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap,fromRow->rmap->bs));
7655   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap,fromCol->cmap->bs));
7656   PetscFunctionReturn(0);
7657 }
7658 
7659 /*@
7660    MatResidual - Default routine to calculate the residual.
7661 
7662    Collective on Mat
7663 
7664    Input Parameters:
7665 +  mat - the matrix
7666 .  b   - the right-hand-side
7667 -  x   - the approximate solution
7668 
7669    Output Parameter:
7670 .  r - location to store the residual
7671 
7672    Level: developer
7673 
7674 .seealso: `PCMGSetResidual()`
7675 @*/
7676 PetscErrorCode MatResidual(Mat mat,Vec b,Vec x,Vec r)
7677 {
7678   PetscFunctionBegin;
7679   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7680   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
7681   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
7682   PetscValidHeaderSpecific(r,VEC_CLASSID,4);
7683   PetscValidType(mat,1);
7684   MatCheckPreallocated(mat,1);
7685   PetscCall(PetscLogEventBegin(MAT_Residual,mat,0,0,0));
7686   if (!mat->ops->residual) {
7687     PetscCall(MatMult(mat,x,r));
7688     PetscCall(VecAYPX(r,-1.0,b));
7689   } else {
7690     PetscCall((*mat->ops->residual)(mat,b,x,r));
7691   }
7692   PetscCall(PetscLogEventEnd(MAT_Residual,mat,0,0,0));
7693   PetscFunctionReturn(0);
7694 }
7695 
7696 /*@C
7697     MatGetRowIJ - Returns the compressed row storage i and j indices for sequential matrices.
7698 
7699    Collective on Mat
7700 
7701     Input Parameters:
7702 +   mat - the matrix
7703 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7704 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be   symmetrized
7705 -   inodecompressed - PETSC_TRUE or PETSC_FALSE  indicating if the nonzero structure of the
7706                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7707                  always used.
7708 
7709     Output Parameters:
7710 +   n - number of rows in the (possibly compressed) matrix
7711 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7712 .   ja - the column indices
7713 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7714            are responsible for handling the case when done == PETSC_FALSE and ia and ja are not set
7715 
7716     Level: developer
7717 
7718     Notes:
7719     You CANNOT change any of the ia[] or ja[] values.
7720 
7721     Use MatRestoreRowIJ() when you are finished accessing the ia[] and ja[] values.
7722 
7723     Fortran Notes:
7724     In Fortran use
7725 $
7726 $      PetscInt ia(1), ja(1)
7727 $      PetscOffset iia, jja
7728 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7729 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7730 
7731      or
7732 $
7733 $    PetscInt, pointer :: ia(:),ja(:)
7734 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7735 $    ! Access the ith and jth entries via ia(i) and ja(j)
7736 
7737 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7738 @*/
7739 PetscErrorCode MatGetRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7740 {
7741   PetscFunctionBegin;
7742   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7743   PetscValidType(mat,1);
7744   if (n) PetscValidIntPointer(n,5);
7745   if (ia) PetscValidPointer(ia,6);
7746   if (ja) PetscValidPointer(ja,7);
7747   if (done) PetscValidBoolPointer(done,8);
7748   MatCheckPreallocated(mat,1);
7749   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7750   else {
7751     if (done) *done = PETSC_TRUE;
7752     PetscCall(PetscLogEventBegin(MAT_GetRowIJ,mat,0,0,0));
7753     PetscCall((*mat->ops->getrowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7754     PetscCall(PetscLogEventEnd(MAT_GetRowIJ,mat,0,0,0));
7755   }
7756   PetscFunctionReturn(0);
7757 }
7758 
7759 /*@C
7760     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7761 
7762     Collective on Mat
7763 
7764     Input Parameters:
7765 +   mat - the matrix
7766 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7767 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7768                 symmetrized
7769 .   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7770                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7771                  always used.
7772 .   n - number of columns in the (possibly compressed) matrix
7773 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7774 -   ja - the row indices
7775 
7776     Output Parameters:
7777 .   done - PETSC_TRUE or PETSC_FALSE, indicating whether the values have been returned
7778 
7779     Level: developer
7780 
7781 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7782 @*/
7783 PetscErrorCode MatGetColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7784 {
7785   PetscFunctionBegin;
7786   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7787   PetscValidType(mat,1);
7788   PetscValidIntPointer(n,5);
7789   if (ia) PetscValidPointer(ia,6);
7790   if (ja) PetscValidPointer(ja,7);
7791   PetscValidBoolPointer(done,8);
7792   MatCheckPreallocated(mat,1);
7793   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7794   else {
7795     *done = PETSC_TRUE;
7796     PetscCall((*mat->ops->getcolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7797   }
7798   PetscFunctionReturn(0);
7799 }
7800 
7801 /*@C
7802     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with
7803     MatGetRowIJ().
7804 
7805     Collective on Mat
7806 
7807     Input Parameters:
7808 +   mat - the matrix
7809 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7810 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7811                 symmetrized
7812 .   inodecompressed -  PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7813                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7814                  always used.
7815 .   n - size of (possibly compressed) matrix
7816 .   ia - the row pointers
7817 -   ja - the column indices
7818 
7819     Output Parameters:
7820 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7821 
7822     Note:
7823     This routine zeros out n, ia, and ja. This is to prevent accidental
7824     us of the array after it has been restored. If you pass NULL, it will
7825     not zero the pointers.  Use of ia or ja after MatRestoreRowIJ() is invalid.
7826 
7827     Level: developer
7828 
7829 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7830 @*/
7831 PetscErrorCode MatRestoreRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7832 {
7833   PetscFunctionBegin;
7834   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7835   PetscValidType(mat,1);
7836   if (ia) PetscValidPointer(ia,6);
7837   if (ja) PetscValidPointer(ja,7);
7838   if (done) PetscValidBoolPointer(done,8);
7839   MatCheckPreallocated(mat,1);
7840 
7841   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7842   else {
7843     if (done) *done = PETSC_TRUE;
7844     PetscCall((*mat->ops->restorerowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7845     if (n)  *n = 0;
7846     if (ia) *ia = NULL;
7847     if (ja) *ja = NULL;
7848   }
7849   PetscFunctionReturn(0);
7850 }
7851 
7852 /*@C
7853     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with
7854     MatGetColumnIJ().
7855 
7856     Collective on Mat
7857 
7858     Input Parameters:
7859 +   mat - the matrix
7860 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7861 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7862                 symmetrized
7863 -   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7864                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7865                  always used.
7866 
7867     Output Parameters:
7868 +   n - size of (possibly compressed) matrix
7869 .   ia - the column pointers
7870 .   ja - the row indices
7871 -   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7872 
7873     Level: developer
7874 
7875 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7876 @*/
7877 PetscErrorCode MatRestoreColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7878 {
7879   PetscFunctionBegin;
7880   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7881   PetscValidType(mat,1);
7882   if (ia) PetscValidPointer(ia,6);
7883   if (ja) PetscValidPointer(ja,7);
7884   PetscValidBoolPointer(done,8);
7885   MatCheckPreallocated(mat,1);
7886 
7887   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7888   else {
7889     *done = PETSC_TRUE;
7890     PetscCall((*mat->ops->restorecolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done));
7891     if (n)  *n = 0;
7892     if (ia) *ia = NULL;
7893     if (ja) *ja = NULL;
7894   }
7895   PetscFunctionReturn(0);
7896 }
7897 
7898 /*@C
7899     MatColoringPatch -Used inside matrix coloring routines that
7900     use MatGetRowIJ() and/or MatGetColumnIJ().
7901 
7902     Collective on Mat
7903 
7904     Input Parameters:
7905 +   mat - the matrix
7906 .   ncolors - max color value
7907 .   n   - number of entries in colorarray
7908 -   colorarray - array indicating color for each column
7909 
7910     Output Parameters:
7911 .   iscoloring - coloring generated using colorarray information
7912 
7913     Level: developer
7914 
7915 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7916 
7917 @*/
7918 PetscErrorCode MatColoringPatch(Mat mat,PetscInt ncolors,PetscInt n,ISColoringValue colorarray[],ISColoring *iscoloring)
7919 {
7920   PetscFunctionBegin;
7921   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7922   PetscValidType(mat,1);
7923   PetscValidIntPointer(colorarray,4);
7924   PetscValidPointer(iscoloring,5);
7925   MatCheckPreallocated(mat,1);
7926 
7927   if (!mat->ops->coloringpatch) {
7928     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat),ncolors,n,colorarray,PETSC_OWN_POINTER,iscoloring));
7929   } else {
7930     PetscCall((*mat->ops->coloringpatch)(mat,ncolors,n,colorarray,iscoloring));
7931   }
7932   PetscFunctionReturn(0);
7933 }
7934 
7935 /*@
7936    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7937 
7938    Logically Collective on Mat
7939 
7940    Input Parameter:
7941 .  mat - the factored matrix to be reset
7942 
7943    Notes:
7944    This routine should be used only with factored matrices formed by in-place
7945    factorization via ILU(0) (or by in-place LU factorization for the MATSEQDENSE
7946    format).  This option can save memory, for example, when solving nonlinear
7947    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7948    ILU(0) preconditioner.
7949 
7950    Note that one can specify in-place ILU(0) factorization by calling
7951 .vb
7952      PCType(pc,PCILU);
7953      PCFactorSeUseInPlace(pc);
7954 .ve
7955    or by using the options -pc_type ilu -pc_factor_in_place
7956 
7957    In-place factorization ILU(0) can also be used as a local
7958    solver for the blocks within the block Jacobi or additive Schwarz
7959    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7960    for details on setting local solver options.
7961 
7962    Most users should employ the simplified KSP interface for linear solvers
7963    instead of working directly with matrix algebra routines such as this.
7964    See, e.g., KSPCreate().
7965 
7966    Level: developer
7967 
7968 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7969 
7970 @*/
7971 PetscErrorCode MatSetUnfactored(Mat mat)
7972 {
7973   PetscFunctionBegin;
7974   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7975   PetscValidType(mat,1);
7976   MatCheckPreallocated(mat,1);
7977   mat->factortype = MAT_FACTOR_NONE;
7978   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
7979   PetscCall((*mat->ops->setunfactored)(mat));
7980   PetscFunctionReturn(0);
7981 }
7982 
7983 /*MC
7984     MatDenseGetArrayF90 - Accesses a matrix array from Fortran90.
7985 
7986     Synopsis:
7987     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7988 
7989     Not collective
7990 
7991     Input Parameter:
7992 .   x - matrix
7993 
7994     Output Parameters:
7995 +   xx_v - the Fortran90 pointer to the array
7996 -   ierr - error code
7997 
7998     Example of Usage:
7999 .vb
8000       PetscScalar, pointer xx_v(:,:)
8001       ....
8002       call MatDenseGetArrayF90(x,xx_v,ierr)
8003       a = xx_v(3)
8004       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8005 .ve
8006 
8007     Level: advanced
8008 
8009 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8010 
8011 M*/
8012 
8013 /*MC
8014     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8015     accessed with MatDenseGetArrayF90().
8016 
8017     Synopsis:
8018     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8019 
8020     Not collective
8021 
8022     Input Parameters:
8023 +   x - matrix
8024 -   xx_v - the Fortran90 pointer to the array
8025 
8026     Output Parameter:
8027 .   ierr - error code
8028 
8029     Example of Usage:
8030 .vb
8031        PetscScalar, pointer xx_v(:,:)
8032        ....
8033        call MatDenseGetArrayF90(x,xx_v,ierr)
8034        a = xx_v(3)
8035        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8036 .ve
8037 
8038     Level: advanced
8039 
8040 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8041 
8042 M*/
8043 
8044 /*MC
8045     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran90.
8046 
8047     Synopsis:
8048     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8049 
8050     Not collective
8051 
8052     Input Parameter:
8053 .   x - matrix
8054 
8055     Output Parameters:
8056 +   xx_v - the Fortran90 pointer to the array
8057 -   ierr - error code
8058 
8059     Example of Usage:
8060 .vb
8061       PetscScalar, pointer xx_v(:)
8062       ....
8063       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8064       a = xx_v(3)
8065       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8066 .ve
8067 
8068     Level: advanced
8069 
8070 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8071 
8072 M*/
8073 
8074 /*MC
8075     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8076     accessed with MatSeqAIJGetArrayF90().
8077 
8078     Synopsis:
8079     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8080 
8081     Not collective
8082 
8083     Input Parameters:
8084 +   x - matrix
8085 -   xx_v - the Fortran90 pointer to the array
8086 
8087     Output Parameter:
8088 .   ierr - error code
8089 
8090     Example of Usage:
8091 .vb
8092        PetscScalar, pointer xx_v(:)
8093        ....
8094        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8095        a = xx_v(3)
8096        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8097 .ve
8098 
8099     Level: advanced
8100 
8101 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8102 
8103 M*/
8104 
8105 /*@
8106     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8107                       as the original matrix.
8108 
8109     Collective on Mat
8110 
8111     Input Parameters:
8112 +   mat - the original matrix
8113 .   isrow - parallel IS containing the rows this processor should obtain
8114 .   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.
8115 -   cll - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
8116 
8117     Output Parameter:
8118 .   newmat - the new submatrix, of the same type as the old
8119 
8120     Level: advanced
8121 
8122     Notes:
8123     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8124 
8125     Some matrix types place restrictions on the row and column indices, such
8126     as that they be sorted or that they be equal to each other.
8127 
8128     The index sets may not have duplicate entries.
8129 
8130       The first time this is called you should use a cll of MAT_INITIAL_MATRIX,
8131    the MatCreateSubMatrix() routine will create the newmat for you. Any additional calls
8132    to this routine with a mat of the same nonzero structure and with a call of MAT_REUSE_MATRIX
8133    will reuse the matrix generated the first time.  You should call MatDestroy() on newmat when
8134    you are finished using it.
8135 
8136     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8137     the input matrix.
8138 
8139     If iscol is NULL then all columns are obtained (not supported in Fortran).
8140 
8141    Example usage:
8142    Consider the following 8x8 matrix with 34 non-zero values, that is
8143    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8144    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8145    as follows:
8146 
8147 .vb
8148             1  2  0  |  0  3  0  |  0  4
8149     Proc0   0  5  6  |  7  0  0  |  8  0
8150             9  0 10  | 11  0  0  | 12  0
8151     -------------------------------------
8152            13  0 14  | 15 16 17  |  0  0
8153     Proc1   0 18  0  | 19 20 21  |  0  0
8154             0  0  0  | 22 23  0  | 24  0
8155     -------------------------------------
8156     Proc2  25 26 27  |  0  0 28  | 29  0
8157            30  0  0  | 31 32 33  |  0 34
8158 .ve
8159 
8160     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8161 
8162 .vb
8163             2  0  |  0  3  0  |  0
8164     Proc0   5  6  |  7  0  0  |  8
8165     -------------------------------
8166     Proc1  18  0  | 19 20 21  |  0
8167     -------------------------------
8168     Proc2  26 27  |  0  0 28  | 29
8169             0  0  | 31 32 33  |  0
8170 .ve
8171 
8172 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8173 @*/
8174 PetscErrorCode MatCreateSubMatrix(Mat mat,IS isrow,IS iscol,MatReuse cll,Mat *newmat)
8175 {
8176   PetscMPIInt    size;
8177   Mat            *local;
8178   IS             iscoltmp;
8179   PetscBool      flg;
8180 
8181   PetscFunctionBegin;
8182   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8183   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
8184   if (iscol) PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
8185   PetscValidPointer(newmat,5);
8186   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat,MAT_CLASSID,5);
8187   PetscValidType(mat,1);
8188   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8189   PetscCheck(cll != MAT_IGNORE_MATRIX,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Cannot use MAT_IGNORE_MATRIX");
8190 
8191   MatCheckPreallocated(mat,1);
8192   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8193 
8194   if (!iscol || isrow == iscol) {
8195     PetscBool   stride;
8196     PetscMPIInt grabentirematrix = 0,grab;
8197     PetscCall(PetscObjectTypeCompare((PetscObject)isrow,ISSTRIDE,&stride));
8198     if (stride) {
8199       PetscInt first,step,n,rstart,rend;
8200       PetscCall(ISStrideGetInfo(isrow,&first,&step));
8201       if (step == 1) {
8202         PetscCall(MatGetOwnershipRange(mat,&rstart,&rend));
8203         if (rstart == first) {
8204           PetscCall(ISGetLocalSize(isrow,&n));
8205           if (n == rend-rstart) {
8206             grabentirematrix = 1;
8207           }
8208         }
8209       }
8210     }
8211     PetscCall(MPIU_Allreduce(&grabentirematrix,&grab,1,MPI_INT,MPI_MIN,PetscObjectComm((PetscObject)mat)));
8212     if (grab) {
8213       PetscCall(PetscInfo(mat,"Getting entire matrix as submatrix\n"));
8214       if (cll == MAT_INITIAL_MATRIX) {
8215         *newmat = mat;
8216         PetscCall(PetscObjectReference((PetscObject)mat));
8217       }
8218       PetscFunctionReturn(0);
8219     }
8220   }
8221 
8222   if (!iscol) {
8223     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat),mat->cmap->n,mat->cmap->rstart,1,&iscoltmp));
8224   } else {
8225     iscoltmp = iscol;
8226   }
8227 
8228   /* if original matrix is on just one processor then use submatrix generated */
8229   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8230     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_REUSE_MATRIX,&newmat));
8231     goto setproperties;
8232   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8233     PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_INITIAL_MATRIX,&local));
8234     *newmat = *local;
8235     PetscCall(PetscFree(local));
8236     goto setproperties;
8237   } else if (!mat->ops->createsubmatrix) {
8238     /* Create a new matrix type that implements the operation using the full matrix */
8239     PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8240     switch (cll) {
8241     case MAT_INITIAL_MATRIX:
8242       PetscCall(MatCreateSubMatrixVirtual(mat,isrow,iscoltmp,newmat));
8243       break;
8244     case MAT_REUSE_MATRIX:
8245       PetscCall(MatSubMatrixVirtualUpdate(*newmat,mat,isrow,iscoltmp));
8246       break;
8247     default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8248     }
8249     PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8250     goto setproperties;
8251   }
8252 
8253   PetscCheck(mat->ops->createsubmatrix,PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8254   PetscCall(PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0));
8255   PetscCall((*mat->ops->createsubmatrix)(mat,isrow,iscoltmp,cll,newmat));
8256   PetscCall(PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0));
8257 
8258 setproperties:
8259   PetscCall(ISEqualUnsorted(isrow,iscoltmp,&flg));
8260   if (flg) PetscCall(MatPropagateSymmetryOptions(mat,*newmat));
8261   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8262   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8263   PetscFunctionReturn(0);
8264 }
8265 
8266 /*@
8267    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8268 
8269    Not Collective
8270 
8271    Input Parameters:
8272 +  A - the matrix we wish to propagate options from
8273 -  B - the matrix we wish to propagate options to
8274 
8275    Level: beginner
8276 
8277    Notes: Propagates the options associated to MAT_SYMMETRY_ETERNAL, MAT_STRUCTURALLY_SYMMETRIC, MAT_HERMITIAN, MAT_SPD and MAT_SYMMETRIC
8278 
8279 .seealso: `MatSetOption()`
8280 @*/
8281 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8282 {
8283   PetscFunctionBegin;
8284   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8285   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
8286   if (A->symmetric_eternal) { /* symmetric_eternal does not have a corresponding *set flag */
8287     PetscCall(MatSetOption(B,MAT_SYMMETRY_ETERNAL,A->symmetric_eternal));
8288   }
8289   if (A->structurally_symmetric_set) PetscCall(MatSetOption(B,MAT_STRUCTURALLY_SYMMETRIC,A->structurally_symmetric));
8290   if (A->hermitian_set) PetscCall(MatSetOption(B,MAT_HERMITIAN,A->hermitian));
8291   if (A->spd_set) PetscCall(MatSetOption(B,MAT_SPD,A->spd));
8292   if (A->symmetric_set) PetscCall(MatSetOption(B,MAT_SYMMETRIC,A->symmetric));
8293   PetscFunctionReturn(0);
8294 }
8295 
8296 /*@
8297    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8298    used during the assembly process to store values that belong to
8299    other processors.
8300 
8301    Not Collective
8302 
8303    Input Parameters:
8304 +  mat   - the matrix
8305 .  size  - the initial size of the stash.
8306 -  bsize - the initial size of the block-stash(if used).
8307 
8308    Options Database Keys:
8309 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8310 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8311 
8312    Level: intermediate
8313 
8314    Notes:
8315      The block-stash is used for values set with MatSetValuesBlocked() while
8316      the stash is used for values set with MatSetValues()
8317 
8318      Run with the option -info and look for output of the form
8319      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8320      to determine the appropriate value, MM, to use for size and
8321      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8322      to determine the value, BMM to use for bsize
8323 
8324 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8325 
8326 @*/
8327 PetscErrorCode MatStashSetInitialSize(Mat mat,PetscInt size, PetscInt bsize)
8328 {
8329   PetscFunctionBegin;
8330   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8331   PetscValidType(mat,1);
8332   PetscCall(MatStashSetInitialSize_Private(&mat->stash,size));
8333   PetscCall(MatStashSetInitialSize_Private(&mat->bstash,bsize));
8334   PetscFunctionReturn(0);
8335 }
8336 
8337 /*@
8338    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8339      the matrix
8340 
8341    Neighbor-wise Collective on Mat
8342 
8343    Input Parameters:
8344 +  mat   - the matrix
8345 .  x,y - the vectors
8346 -  w - where the result is stored
8347 
8348    Level: intermediate
8349 
8350    Notes:
8351     w may be the same vector as y.
8352 
8353     This allows one to use either the restriction or interpolation (its transpose)
8354     matrix to do the interpolation
8355 
8356 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8357 
8358 @*/
8359 PetscErrorCode MatInterpolateAdd(Mat A,Vec x,Vec y,Vec w)
8360 {
8361   PetscInt       M,N,Ny;
8362 
8363   PetscFunctionBegin;
8364   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8365   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8366   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8367   PetscValidHeaderSpecific(w,VEC_CLASSID,4);
8368   PetscCall(MatGetSize(A,&M,&N));
8369   PetscCall(VecGetSize(y,&Ny));
8370   if (M == Ny) {
8371     PetscCall(MatMultAdd(A,x,y,w));
8372   } else {
8373     PetscCall(MatMultTransposeAdd(A,x,y,w));
8374   }
8375   PetscFunctionReturn(0);
8376 }
8377 
8378 /*@
8379    MatInterpolate - y = A*x or A'*x depending on the shape of
8380      the matrix
8381 
8382    Neighbor-wise Collective on Mat
8383 
8384    Input Parameters:
8385 +  mat   - the matrix
8386 -  x,y - the vectors
8387 
8388    Level: intermediate
8389 
8390    Notes:
8391     This allows one to use either the restriction or interpolation (its transpose)
8392     matrix to do the interpolation
8393 
8394 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8395 
8396 @*/
8397 PetscErrorCode MatInterpolate(Mat A,Vec x,Vec y)
8398 {
8399   PetscInt       M,N,Ny;
8400 
8401   PetscFunctionBegin;
8402   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8403   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8404   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8405   PetscCall(MatGetSize(A,&M,&N));
8406   PetscCall(VecGetSize(y,&Ny));
8407   if (M == Ny) {
8408     PetscCall(MatMult(A,x,y));
8409   } else {
8410     PetscCall(MatMultTranspose(A,x,y));
8411   }
8412   PetscFunctionReturn(0);
8413 }
8414 
8415 /*@
8416    MatRestrict - y = A*x or A'*x
8417 
8418    Neighbor-wise Collective on Mat
8419 
8420    Input Parameters:
8421 +  mat   - the matrix
8422 -  x,y - the vectors
8423 
8424    Level: intermediate
8425 
8426    Notes:
8427     This allows one to use either the restriction or interpolation (its transpose)
8428     matrix to do the restriction
8429 
8430 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`
8431 
8432 @*/
8433 PetscErrorCode MatRestrict(Mat A,Vec x,Vec y)
8434 {
8435   PetscInt       M,N,Ny;
8436 
8437   PetscFunctionBegin;
8438   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8439   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8440   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8441   PetscCall(MatGetSize(A,&M,&N));
8442   PetscCall(VecGetSize(y,&Ny));
8443   if (M == Ny) {
8444     PetscCall(MatMult(A,x,y));
8445   } else {
8446     PetscCall(MatMultTranspose(A,x,y));
8447   }
8448   PetscFunctionReturn(0);
8449 }
8450 
8451 /*@
8452    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8453 
8454    Neighbor-wise Collective on Mat
8455 
8456    Input Parameters:
8457 +  mat   - the matrix
8458 -  w, x - the input dense matrices
8459 
8460    Output Parameters:
8461 .  y - the output dense matrix
8462 
8463    Level: intermediate
8464 
8465    Notes:
8466     This allows one to use either the restriction or interpolation (its transpose)
8467     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8468     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8469 
8470 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`
8471 
8472 @*/
8473 PetscErrorCode MatMatInterpolateAdd(Mat A,Mat x,Mat w,Mat *y)
8474 {
8475   PetscInt       M,N,Mx,Nx,Mo,My = 0,Ny = 0;
8476   PetscBool      trans = PETSC_TRUE;
8477   MatReuse       reuse = MAT_INITIAL_MATRIX;
8478 
8479   PetscFunctionBegin;
8480   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8481   PetscValidHeaderSpecific(x,MAT_CLASSID,2);
8482   PetscValidType(x,2);
8483   if (w) PetscValidHeaderSpecific(w,MAT_CLASSID,3);
8484   if (*y) PetscValidHeaderSpecific(*y,MAT_CLASSID,4);
8485   PetscCall(MatGetSize(A,&M,&N));
8486   PetscCall(MatGetSize(x,&Mx,&Nx));
8487   if (N == Mx) trans = PETSC_FALSE;
8488   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);
8489   Mo = trans ? N : M;
8490   if (*y) {
8491     PetscCall(MatGetSize(*y,&My,&Ny));
8492     if (Mo == My && Nx == Ny) { reuse = MAT_REUSE_MATRIX; }
8493     else {
8494       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);
8495       PetscCall(MatDestroy(y));
8496     }
8497   }
8498 
8499   if (w && *y == w) { /* this is to minimize changes in PCMG */
8500     PetscBool flg;
8501 
8502     PetscCall(PetscObjectQuery((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject*)&w));
8503     if (w) {
8504       PetscInt My,Ny,Mw,Nw;
8505 
8506       PetscCall(PetscObjectTypeCompare((PetscObject)*y,((PetscObject)w)->type_name,&flg));
8507       PetscCall(MatGetSize(*y,&My,&Ny));
8508       PetscCall(MatGetSize(w,&Mw,&Nw));
8509       if (!flg || My != Mw || Ny != Nw) w = NULL;
8510     }
8511     if (!w) {
8512       PetscCall(MatDuplicate(*y,MAT_COPY_VALUES,&w));
8513       PetscCall(PetscObjectCompose((PetscObject)*y,"__MatMatIntAdd_w",(PetscObject)w));
8514       PetscCall(PetscLogObjectParent((PetscObject)*y,(PetscObject)w));
8515       PetscCall(PetscObjectDereference((PetscObject)w));
8516     } else {
8517       PetscCall(MatCopy(*y,w,UNKNOWN_NONZERO_PATTERN));
8518     }
8519   }
8520   if (!trans) {
8521     PetscCall(MatMatMult(A,x,reuse,PETSC_DEFAULT,y));
8522   } else {
8523     PetscCall(MatTransposeMatMult(A,x,reuse,PETSC_DEFAULT,y));
8524   }
8525   if (w) PetscCall(MatAXPY(*y,1.0,w,UNKNOWN_NONZERO_PATTERN));
8526   PetscFunctionReturn(0);
8527 }
8528 
8529 /*@
8530    MatMatInterpolate - Y = A*X or A'*X
8531 
8532    Neighbor-wise Collective on Mat
8533 
8534    Input Parameters:
8535 +  mat   - the matrix
8536 -  x - the input dense matrix
8537 
8538    Output Parameters:
8539 .  y - the output dense matrix
8540 
8541    Level: intermediate
8542 
8543    Notes:
8544     This allows one to use either the restriction or interpolation (its transpose)
8545     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8546     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8547 
8548 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`
8549 
8550 @*/
8551 PetscErrorCode MatMatInterpolate(Mat A,Mat x,Mat *y)
8552 {
8553   PetscFunctionBegin;
8554   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8555   PetscFunctionReturn(0);
8556 }
8557 
8558 /*@
8559    MatMatRestrict - Y = A*X or A'*X
8560 
8561    Neighbor-wise Collective on Mat
8562 
8563    Input Parameters:
8564 +  mat   - the matrix
8565 -  x - the input dense matrix
8566 
8567    Output Parameters:
8568 .  y - the output dense matrix
8569 
8570    Level: intermediate
8571 
8572    Notes:
8573     This allows one to use either the restriction or interpolation (its transpose)
8574     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8575     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8576 
8577 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`
8578 @*/
8579 PetscErrorCode MatMatRestrict(Mat A,Mat x,Mat *y)
8580 {
8581   PetscFunctionBegin;
8582   PetscCall(MatMatInterpolateAdd(A,x,NULL,y));
8583   PetscFunctionReturn(0);
8584 }
8585 
8586 /*@
8587    MatGetNullSpace - retrieves the null space of a matrix.
8588 
8589    Logically Collective on Mat
8590 
8591    Input Parameters:
8592 +  mat - the matrix
8593 -  nullsp - the null space object
8594 
8595    Level: developer
8596 
8597 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`
8598 @*/
8599 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8600 {
8601   PetscFunctionBegin;
8602   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8603   PetscValidPointer(nullsp,2);
8604   *nullsp = (mat->symmetric_set && mat->symmetric && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8605   PetscFunctionReturn(0);
8606 }
8607 
8608 /*@
8609    MatSetNullSpace - attaches a null space to a matrix.
8610 
8611    Logically Collective on Mat
8612 
8613    Input Parameters:
8614 +  mat - the matrix
8615 -  nullsp - the null space object
8616 
8617    Level: advanced
8618 
8619    Notes:
8620       This null space is used by the KSP linear solvers to solve singular systems.
8621 
8622       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
8623 
8624       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
8625       to zero but the linear system will still be solved in a least squares sense.
8626 
8627       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8628    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).
8629    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
8630    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
8631    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).
8632    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8633 
8634     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
8635     routine also automatically calls MatSetTransposeNullSpace().
8636 
8637     The user should call `MatNullSpaceDestroy()`.
8638 
8639 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8640           `KSPSetPCSide()`
8641 @*/
8642 PetscErrorCode MatSetNullSpace(Mat mat,MatNullSpace nullsp)
8643 {
8644   PetscFunctionBegin;
8645   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8646   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8647   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8648   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8649   mat->nullsp = nullsp;
8650   if (mat->symmetric_set && mat->symmetric) {
8651     PetscCall(MatSetTransposeNullSpace(mat,nullsp));
8652   }
8653   PetscFunctionReturn(0);
8654 }
8655 
8656 /*@
8657    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8658 
8659    Logically Collective on Mat
8660 
8661    Input Parameters:
8662 +  mat - the matrix
8663 -  nullsp - the null space object
8664 
8665    Level: developer
8666 
8667 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8668 @*/
8669 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8670 {
8671   PetscFunctionBegin;
8672   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8673   PetscValidType(mat,1);
8674   PetscValidPointer(nullsp,2);
8675   *nullsp = (mat->symmetric_set && mat->symmetric && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8676   PetscFunctionReturn(0);
8677 }
8678 
8679 /*@
8680    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8681 
8682    Logically Collective on Mat
8683 
8684    Input Parameters:
8685 +  mat - the matrix
8686 -  nullsp - the null space object
8687 
8688    Level: advanced
8689 
8690    Notes:
8691       This allows solving singular linear systems defined by the transpose of the matrix using KSP solvers with left preconditioning.
8692 
8693       See MatSetNullSpace()
8694 
8695 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8696 @*/
8697 PetscErrorCode MatSetTransposeNullSpace(Mat mat,MatNullSpace nullsp)
8698 {
8699   PetscFunctionBegin;
8700   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8701   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8702   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8703   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8704   mat->transnullsp = nullsp;
8705   PetscFunctionReturn(0);
8706 }
8707 
8708 /*@
8709    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8710         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8711 
8712    Logically Collective on Mat
8713 
8714    Input Parameters:
8715 +  mat - the matrix
8716 -  nullsp - the null space object
8717 
8718    Level: advanced
8719 
8720    Notes:
8721       Overwrites any previous near null space that may have been attached
8722 
8723       You can remove the null space by calling this routine with an nullsp of NULL
8724 
8725 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8726 @*/
8727 PetscErrorCode MatSetNearNullSpace(Mat mat,MatNullSpace nullsp)
8728 {
8729   PetscFunctionBegin;
8730   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8731   PetscValidType(mat,1);
8732   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8733   MatCheckPreallocated(mat,1);
8734   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8735   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8736   mat->nearnullsp = nullsp;
8737   PetscFunctionReturn(0);
8738 }
8739 
8740 /*@
8741    MatGetNearNullSpace - Get null space attached with MatSetNearNullSpace()
8742 
8743    Not Collective
8744 
8745    Input Parameter:
8746 .  mat - the matrix
8747 
8748    Output Parameter:
8749 .  nullsp - the null space object, NULL if not set
8750 
8751    Level: developer
8752 
8753 .seealso: `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8754 @*/
8755 PetscErrorCode MatGetNearNullSpace(Mat mat,MatNullSpace *nullsp)
8756 {
8757   PetscFunctionBegin;
8758   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8759   PetscValidType(mat,1);
8760   PetscValidPointer(nullsp,2);
8761   MatCheckPreallocated(mat,1);
8762   *nullsp = mat->nearnullsp;
8763   PetscFunctionReturn(0);
8764 }
8765 
8766 /*@C
8767    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8768 
8769    Collective on Mat
8770 
8771    Input Parameters:
8772 +  mat - the matrix
8773 .  row - row/column permutation
8774 .  fill - expected fill factor >= 1.0
8775 -  level - level of fill, for ICC(k)
8776 
8777    Notes:
8778    Probably really in-place only when level of fill is zero, otherwise allocates
8779    new space to store factored matrix and deletes previous memory.
8780 
8781    Most users should employ the simplified KSP interface for linear solvers
8782    instead of working directly with matrix algebra routines such as this.
8783    See, e.g., KSPCreate().
8784 
8785    Level: developer
8786 
8787 .seealso: `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8788 
8789     Developer Note: fortran interface is not autogenerated as the f90
8790     interface definition cannot be generated correctly [due to MatFactorInfo]
8791 
8792 @*/
8793 PetscErrorCode MatICCFactor(Mat mat,IS row,const MatFactorInfo *info)
8794 {
8795   PetscFunctionBegin;
8796   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8797   PetscValidType(mat,1);
8798   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
8799   PetscValidPointer(info,3);
8800   PetscCheck(mat->rmap->N == mat->cmap->N,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
8801   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
8802   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8803   PetscCheck(mat->ops->iccfactor,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8804   MatCheckPreallocated(mat,1);
8805   PetscCall((*mat->ops->iccfactor)(mat,row,info));
8806   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8807   PetscFunctionReturn(0);
8808 }
8809 
8810 /*@
8811    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8812          ghosted ones.
8813 
8814    Not Collective
8815 
8816    Input Parameters:
8817 +  mat - the matrix
8818 -  diag - the diagonal values, including ghost ones
8819 
8820    Level: developer
8821 
8822    Notes:
8823     Works only for MPIAIJ and MPIBAIJ matrices
8824 
8825 .seealso: `MatDiagonalScale()`
8826 @*/
8827 PetscErrorCode MatDiagonalScaleLocal(Mat mat,Vec diag)
8828 {
8829   PetscMPIInt    size;
8830 
8831   PetscFunctionBegin;
8832   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8833   PetscValidHeaderSpecific(diag,VEC_CLASSID,2);
8834   PetscValidType(mat,1);
8835 
8836   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be already assembled");
8837   PetscCall(PetscLogEventBegin(MAT_Scale,mat,0,0,0));
8838   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
8839   if (size == 1) {
8840     PetscInt n,m;
8841     PetscCall(VecGetSize(diag,&n));
8842     PetscCall(MatGetSize(mat,NULL,&m));
8843     if (m == n) {
8844       PetscCall(MatDiagonalScale(mat,NULL,diag));
8845     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only supported for sequential matrices when no ghost points/periodic conditions");
8846   } else {
8847     PetscUseMethod(mat,"MatDiagonalScaleLocal_C",(Mat,Vec),(mat,diag));
8848   }
8849   PetscCall(PetscLogEventEnd(MAT_Scale,mat,0,0,0));
8850   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8851   PetscFunctionReturn(0);
8852 }
8853 
8854 /*@
8855    MatGetInertia - Gets the inertia from a factored matrix
8856 
8857    Collective on Mat
8858 
8859    Input Parameter:
8860 .  mat - the matrix
8861 
8862    Output Parameters:
8863 +   nneg - number of negative eigenvalues
8864 .   nzero - number of zero eigenvalues
8865 -   npos - number of positive eigenvalues
8866 
8867    Level: advanced
8868 
8869    Notes:
8870     Matrix must have been factored by MatCholeskyFactor()
8871 
8872 @*/
8873 PetscErrorCode MatGetInertia(Mat mat,PetscInt *nneg,PetscInt *nzero,PetscInt *npos)
8874 {
8875   PetscFunctionBegin;
8876   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8877   PetscValidType(mat,1);
8878   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
8879   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Numeric factor mat is not assembled");
8880   PetscCheck(mat->ops->getinertia,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8881   PetscCall((*mat->ops->getinertia)(mat,nneg,nzero,npos));
8882   PetscFunctionReturn(0);
8883 }
8884 
8885 /* ----------------------------------------------------------------*/
8886 /*@C
8887    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8888 
8889    Neighbor-wise Collective on Mats
8890 
8891    Input Parameters:
8892 +  mat - the factored matrix
8893 -  b - the right-hand-side vectors
8894 
8895    Output Parameter:
8896 .  x - the result vectors
8897 
8898    Notes:
8899    The vectors b and x cannot be the same.  I.e., one cannot
8900    call MatSolves(A,x,x).
8901 
8902    Notes:
8903    Most users should employ the simplified KSP interface for linear solvers
8904    instead of working directly with matrix algebra routines such as this.
8905    See, e.g., KSPCreate().
8906 
8907    Level: developer
8908 
8909 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8910 @*/
8911 PetscErrorCode MatSolves(Mat mat,Vecs b,Vecs x)
8912 {
8913   PetscFunctionBegin;
8914   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8915   PetscValidType(mat,1);
8916   PetscCheck(x != b,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
8917   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
8918   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
8919 
8920   PetscCheck(mat->ops->solves,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8921   MatCheckPreallocated(mat,1);
8922   PetscCall(PetscLogEventBegin(MAT_Solves,mat,0,0,0));
8923   PetscCall((*mat->ops->solves)(mat,b,x));
8924   PetscCall(PetscLogEventEnd(MAT_Solves,mat,0,0,0));
8925   PetscFunctionReturn(0);
8926 }
8927 
8928 /*@
8929    MatIsSymmetric - Test whether a matrix is symmetric
8930 
8931    Collective on Mat
8932 
8933    Input Parameters:
8934 +  A - the matrix to test
8935 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8936 
8937    Output Parameters:
8938 .  flg - the result
8939 
8940    Notes:
8941     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
8942 
8943    Level: intermediate
8944 
8945 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`
8946 @*/
8947 PetscErrorCode MatIsSymmetric(Mat A,PetscReal tol,PetscBool *flg)
8948 {
8949   PetscFunctionBegin;
8950   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8951   PetscValidBoolPointer(flg,3);
8952 
8953   if (!A->symmetric_set) {
8954     if (!A->ops->issymmetric) {
8955       MatType mattype;
8956       PetscCall(MatGetType(A,&mattype));
8957       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for symmetric",mattype);
8958     }
8959     PetscCall((*A->ops->issymmetric)(A,tol,flg));
8960     if (!tol) {
8961       PetscCall(MatSetOption(A,MAT_SYMMETRIC,*flg));
8962     }
8963   } else if (A->symmetric) {
8964     *flg = PETSC_TRUE;
8965   } else if (!tol) {
8966     *flg = PETSC_FALSE;
8967   } else {
8968     if (!A->ops->issymmetric) {
8969       MatType mattype;
8970       PetscCall(MatGetType(A,&mattype));
8971       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for symmetric",mattype);
8972     }
8973     PetscCall((*A->ops->issymmetric)(A,tol,flg));
8974   }
8975   PetscFunctionReturn(0);
8976 }
8977 
8978 /*@
8979    MatIsHermitian - Test whether a matrix is Hermitian
8980 
8981    Collective on Mat
8982 
8983    Input Parameters:
8984 +  A - the matrix to test
8985 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8986 
8987    Output Parameters:
8988 .  flg - the result
8989 
8990    Level: intermediate
8991 
8992 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8993           `MatIsSymmetricKnown()`, `MatIsSymmetric()`
8994 @*/
8995 PetscErrorCode MatIsHermitian(Mat A,PetscReal tol,PetscBool *flg)
8996 {
8997   PetscFunctionBegin;
8998   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8999   PetscValidBoolPointer(flg,3);
9000 
9001   if (!A->hermitian_set) {
9002     if (!A->ops->ishermitian) {
9003       MatType mattype;
9004       PetscCall(MatGetType(A,&mattype));
9005       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for hermitian",mattype);
9006     }
9007     PetscCall((*A->ops->ishermitian)(A,tol,flg));
9008     if (!tol) {
9009       PetscCall(MatSetOption(A,MAT_HERMITIAN,*flg));
9010     }
9011   } else if (A->hermitian) {
9012     *flg = PETSC_TRUE;
9013   } else if (!tol) {
9014     *flg = PETSC_FALSE;
9015   } else {
9016     if (!A->ops->ishermitian) {
9017       MatType mattype;
9018       PetscCall(MatGetType(A,&mattype));
9019       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type %s does not support checking for hermitian",mattype);
9020     }
9021     PetscCall((*A->ops->ishermitian)(A,tol,flg));
9022   }
9023   PetscFunctionReturn(0);
9024 }
9025 
9026 /*@
9027    MatIsSymmetricKnown - Checks the flag on the matrix to see if it is symmetric.
9028 
9029    Not Collective
9030 
9031    Input Parameter:
9032 .  A - the matrix to check
9033 
9034    Output Parameters:
9035 +  set - if the symmetric flag is set (this tells you if the next flag is valid)
9036 -  flg - the result
9037 
9038    Level: advanced
9039 
9040    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsSymmetric()
9041          if you want it explicitly checked
9042 
9043 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9044 @*/
9045 PetscErrorCode MatIsSymmetricKnown(Mat A,PetscBool *set,PetscBool *flg)
9046 {
9047   PetscFunctionBegin;
9048   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9049   PetscValidBoolPointer(set,2);
9050   PetscValidBoolPointer(flg,3);
9051   if (A->symmetric_set) {
9052     *set = PETSC_TRUE;
9053     *flg = A->symmetric;
9054   } else {
9055     *set = PETSC_FALSE;
9056   }
9057   PetscFunctionReturn(0);
9058 }
9059 
9060 /*@
9061    MatIsHermitianKnown - Checks the flag on the matrix to see if it is hermitian.
9062 
9063    Not Collective
9064 
9065    Input Parameter:
9066 .  A - the matrix to check
9067 
9068    Output Parameters:
9069 +  set - if the hermitian flag is set (this tells you if the next flag is valid)
9070 -  flg - the result
9071 
9072    Level: advanced
9073 
9074    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsHermitian()
9075          if you want it explicitly checked
9076 
9077 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9078 @*/
9079 PetscErrorCode MatIsHermitianKnown(Mat A,PetscBool *set,PetscBool *flg)
9080 {
9081   PetscFunctionBegin;
9082   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9083   PetscValidBoolPointer(set,2);
9084   PetscValidBoolPointer(flg,3);
9085   if (A->hermitian_set) {
9086     *set = PETSC_TRUE;
9087     *flg = A->hermitian;
9088   } else {
9089     *set = PETSC_FALSE;
9090   }
9091   PetscFunctionReturn(0);
9092 }
9093 
9094 /*@
9095    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9096 
9097    Collective on Mat
9098 
9099    Input Parameter:
9100 .  A - the matrix to test
9101 
9102    Output Parameters:
9103 .  flg - the result
9104 
9105    Level: intermediate
9106 
9107 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`
9108 @*/
9109 PetscErrorCode MatIsStructurallySymmetric(Mat A,PetscBool *flg)
9110 {
9111   PetscFunctionBegin;
9112   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9113   PetscValidBoolPointer(flg,2);
9114   if (!A->structurally_symmetric_set) {
9115     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);
9116     PetscCall((*A->ops->isstructurallysymmetric)(A,flg));
9117     PetscCall(MatSetOption(A,MAT_STRUCTURALLY_SYMMETRIC,*flg));
9118   } else *flg = A->structurally_symmetric;
9119   PetscFunctionReturn(0);
9120 }
9121 
9122 /*@
9123    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9124        to be communicated to other processors during the MatAssemblyBegin/End() process
9125 
9126     Not collective
9127 
9128    Input Parameter:
9129 .   vec - the vector
9130 
9131    Output Parameters:
9132 +   nstash   - the size of the stash
9133 .   reallocs - the number of additional mallocs incurred.
9134 .   bnstash   - the size of the block stash
9135 -   breallocs - the number of additional mallocs incurred.in the block stash
9136 
9137    Level: advanced
9138 
9139 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9140 
9141 @*/
9142 PetscErrorCode MatStashGetInfo(Mat mat,PetscInt *nstash,PetscInt *reallocs,PetscInt *bnstash,PetscInt *breallocs)
9143 {
9144   PetscFunctionBegin;
9145   PetscCall(MatStashGetInfo_Private(&mat->stash,nstash,reallocs));
9146   PetscCall(MatStashGetInfo_Private(&mat->bstash,bnstash,breallocs));
9147   PetscFunctionReturn(0);
9148 }
9149 
9150 /*@C
9151    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9152      parallel layout
9153 
9154    Collective on Mat
9155 
9156    Input Parameter:
9157 .  mat - the matrix
9158 
9159    Output Parameters:
9160 +   right - (optional) vector that the matrix can be multiplied against
9161 -   left - (optional) vector that the matrix vector product can be stored in
9162 
9163    Notes:
9164     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().
9165 
9166   Notes:
9167     These are new vectors which are not owned by the Mat, they should be destroyed in VecDestroy() when no longer needed
9168 
9169   Level: advanced
9170 
9171 .seealso: `MatCreate()`, `VecDestroy()`
9172 @*/
9173 PetscErrorCode MatCreateVecs(Mat mat,Vec *right,Vec *left)
9174 {
9175   PetscFunctionBegin;
9176   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9177   PetscValidType(mat,1);
9178   if (mat->ops->getvecs) {
9179     PetscCall((*mat->ops->getvecs)(mat,right,left));
9180   } else {
9181     PetscInt rbs,cbs;
9182     PetscCall(MatGetBlockSizes(mat,&rbs,&cbs));
9183     if (right) {
9184       PetscCheck(mat->cmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for columns not yet setup");
9185       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),right));
9186       PetscCall(VecSetSizes(*right,mat->cmap->n,PETSC_DETERMINE));
9187       PetscCall(VecSetBlockSize(*right,cbs));
9188       PetscCall(VecSetType(*right,mat->defaultvectype));
9189 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9190       if (mat->boundtocpu && mat->bindingpropagates) {
9191         PetscCall(VecSetBindingPropagates(*right,PETSC_TRUE));
9192         PetscCall(VecBindToCPU(*right,PETSC_TRUE));
9193       }
9194 #endif
9195       PetscCall(PetscLayoutReference(mat->cmap,&(*right)->map));
9196     }
9197     if (left) {
9198       PetscCheck(mat->rmap->n >= 0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for rows not yet setup");
9199       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat),left));
9200       PetscCall(VecSetSizes(*left,mat->rmap->n,PETSC_DETERMINE));
9201       PetscCall(VecSetBlockSize(*left,rbs));
9202       PetscCall(VecSetType(*left,mat->defaultvectype));
9203 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9204       if (mat->boundtocpu && mat->bindingpropagates) {
9205         PetscCall(VecSetBindingPropagates(*left,PETSC_TRUE));
9206         PetscCall(VecBindToCPU(*left,PETSC_TRUE));
9207       }
9208 #endif
9209       PetscCall(PetscLayoutReference(mat->rmap,&(*left)->map));
9210     }
9211   }
9212   PetscFunctionReturn(0);
9213 }
9214 
9215 /*@C
9216    MatFactorInfoInitialize - Initializes a MatFactorInfo data structure
9217      with default values.
9218 
9219    Not Collective
9220 
9221    Input Parameters:
9222 .    info - the MatFactorInfo data structure
9223 
9224    Notes:
9225     The solvers are generally used through the KSP and PC objects, for example
9226           PCLU, PCILU, PCCHOLESKY, PCICC
9227 
9228    Level: developer
9229 
9230 .seealso: `MatFactorInfo`
9231 
9232     Developer Note: fortran interface is not autogenerated as the f90
9233     interface definition cannot be generated correctly [due to MatFactorInfo]
9234 
9235 @*/
9236 
9237 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9238 {
9239   PetscFunctionBegin;
9240   PetscCall(PetscMemzero(info,sizeof(MatFactorInfo)));
9241   PetscFunctionReturn(0);
9242 }
9243 
9244 /*@
9245    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9246 
9247    Collective on Mat
9248 
9249    Input Parameters:
9250 +  mat - the factored matrix
9251 -  is - the index set defining the Schur indices (0-based)
9252 
9253    Notes:
9254     Call MatFactorSolveSchurComplement() or MatFactorSolveSchurComplementTranspose() after this call to solve a Schur complement system.
9255 
9256    You can call MatFactorGetSchurComplement() or MatFactorCreateSchurComplement() after this call.
9257 
9258    Level: developer
9259 
9260 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9261           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`
9262 
9263 @*/
9264 PetscErrorCode MatFactorSetSchurIS(Mat mat,IS is)
9265 {
9266   PetscErrorCode (*f)(Mat,IS);
9267 
9268   PetscFunctionBegin;
9269   PetscValidType(mat,1);
9270   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9271   PetscValidType(is,2);
9272   PetscValidHeaderSpecific(is,IS_CLASSID,2);
9273   PetscCheckSameComm(mat,1,is,2);
9274   PetscCheck(mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
9275   PetscCall(PetscObjectQueryFunction((PetscObject)mat,"MatFactorSetSchurIS_C",&f));
9276   PetscCheck(f,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9277   PetscCall(MatDestroy(&mat->schur));
9278   PetscCall((*f)(mat,is));
9279   PetscCheck(mat->schur,PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Schur complement has not been created");
9280   PetscFunctionReturn(0);
9281 }
9282 
9283 /*@
9284   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9285 
9286    Logically Collective on Mat
9287 
9288    Input Parameters:
9289 +  F - the factored matrix obtained by calling MatGetFactor() from PETSc-MUMPS interface
9290 .  S - location where to return the Schur complement, can be NULL
9291 -  status - the status of the Schur complement matrix, can be NULL
9292 
9293    Notes:
9294    You must call MatFactorSetSchurIS() before calling this routine.
9295 
9296    The routine provides a copy of the Schur matrix stored within the solver data structures.
9297    The caller must destroy the object when it is no longer needed.
9298    If MatFactorInvertSchurComplement() has been called, the routine gets back the inverse.
9299 
9300    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)
9301 
9302    Developer Notes:
9303     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9304    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9305 
9306    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9307 
9308    Level: advanced
9309 
9310    References:
9311 
9312 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`
9313 @*/
9314 PetscErrorCode MatFactorCreateSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9315 {
9316   PetscFunctionBegin;
9317   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9318   if (S) PetscValidPointer(S,2);
9319   if (status) PetscValidPointer(status,3);
9320   if (S) {
9321     PetscErrorCode (*f)(Mat,Mat*);
9322 
9323     PetscCall(PetscObjectQueryFunction((PetscObject)F,"MatFactorCreateSchurComplement_C",&f));
9324     if (f) {
9325       PetscCall((*f)(F,S));
9326     } else {
9327       PetscCall(MatDuplicate(F->schur,MAT_COPY_VALUES,S));
9328     }
9329   }
9330   if (status) *status = F->schur_status;
9331   PetscFunctionReturn(0);
9332 }
9333 
9334 /*@
9335   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9336 
9337    Logically Collective on Mat
9338 
9339    Input Parameters:
9340 +  F - the factored matrix obtained by calling MatGetFactor()
9341 .  *S - location where to return the Schur complement, can be NULL
9342 -  status - the status of the Schur complement matrix, can be NULL
9343 
9344    Notes:
9345    You must call MatFactorSetSchurIS() before calling this routine.
9346 
9347    Schur complement mode is currently implemented for sequential matrices.
9348    The routine returns a the Schur Complement stored within the data strutures of the solver.
9349    If MatFactorInvertSchurComplement() has previously been called, the returned matrix is actually the inverse of the Schur complement.
9350    The returned matrix should not be destroyed; the caller should call MatFactorRestoreSchurComplement() when the object is no longer needed.
9351 
9352    Use MatFactorCreateSchurComplement() to create a copy of the Schur complement matrix that is within a factored matrix
9353 
9354    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9355 
9356    Level: advanced
9357 
9358    References:
9359 
9360 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9361 @*/
9362 PetscErrorCode MatFactorGetSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
9363 {
9364   PetscFunctionBegin;
9365   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9366   if (S) PetscValidPointer(S,2);
9367   if (status) PetscValidPointer(status,3);
9368   if (S) *S = F->schur;
9369   if (status) *status = F->schur_status;
9370   PetscFunctionReturn(0);
9371 }
9372 
9373 /*@
9374   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to MatFactorGetSchurComplement
9375 
9376    Logically Collective on Mat
9377 
9378    Input Parameters:
9379 +  F - the factored matrix obtained by calling MatGetFactor()
9380 .  *S - location where the Schur complement is stored
9381 -  status - the status of the Schur complement matrix (see MatFactorSchurStatus)
9382 
9383    Notes:
9384 
9385    Level: advanced
9386 
9387    References:
9388 
9389 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9390 @*/
9391 PetscErrorCode MatFactorRestoreSchurComplement(Mat F,Mat* S,MatFactorSchurStatus status)
9392 {
9393   PetscFunctionBegin;
9394   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9395   if (S) {
9396     PetscValidHeaderSpecific(*S,MAT_CLASSID,2);
9397     *S = NULL;
9398   }
9399   F->schur_status = status;
9400   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9401   PetscFunctionReturn(0);
9402 }
9403 
9404 /*@
9405   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9406 
9407    Logically Collective on Mat
9408 
9409    Input Parameters:
9410 +  F - the factored matrix obtained by calling MatGetFactor()
9411 .  rhs - location where the right hand side of the Schur complement system is stored
9412 -  sol - location where the solution of the Schur complement system has to be returned
9413 
9414    Notes:
9415    The sizes of the vectors should match the size of the Schur complement
9416 
9417    Must be called after MatFactorSetSchurIS()
9418 
9419    Level: advanced
9420 
9421    References:
9422 
9423 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9424 @*/
9425 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9426 {
9427   PetscFunctionBegin;
9428   PetscValidType(F,1);
9429   PetscValidType(rhs,2);
9430   PetscValidType(sol,3);
9431   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9432   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9433   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9434   PetscCheckSameComm(F,1,rhs,2);
9435   PetscCheckSameComm(F,1,sol,3);
9436   PetscCall(MatFactorFactorizeSchurComplement(F));
9437   switch (F->schur_status) {
9438   case MAT_FACTOR_SCHUR_FACTORED:
9439     PetscCall(MatSolveTranspose(F->schur,rhs,sol));
9440     break;
9441   case MAT_FACTOR_SCHUR_INVERTED:
9442     PetscCall(MatMultTranspose(F->schur,rhs,sol));
9443     break;
9444   default:
9445     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9446   }
9447   PetscFunctionReturn(0);
9448 }
9449 
9450 /*@
9451   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9452 
9453    Logically Collective on Mat
9454 
9455    Input Parameters:
9456 +  F - the factored matrix obtained by calling MatGetFactor()
9457 .  rhs - location where the right hand side of the Schur complement system is stored
9458 -  sol - location where the solution of the Schur complement system has to be returned
9459 
9460    Notes:
9461    The sizes of the vectors should match the size of the Schur complement
9462 
9463    Must be called after MatFactorSetSchurIS()
9464 
9465    Level: advanced
9466 
9467    References:
9468 
9469 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9470 @*/
9471 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9472 {
9473   PetscFunctionBegin;
9474   PetscValidType(F,1);
9475   PetscValidType(rhs,2);
9476   PetscValidType(sol,3);
9477   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9478   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9479   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9480   PetscCheckSameComm(F,1,rhs,2);
9481   PetscCheckSameComm(F,1,sol,3);
9482   PetscCall(MatFactorFactorizeSchurComplement(F));
9483   switch (F->schur_status) {
9484   case MAT_FACTOR_SCHUR_FACTORED:
9485     PetscCall(MatSolve(F->schur,rhs,sol));
9486     break;
9487   case MAT_FACTOR_SCHUR_INVERTED:
9488     PetscCall(MatMult(F->schur,rhs,sol));
9489     break;
9490   default:
9491     SETERRQ(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %d",F->schur_status);
9492   }
9493   PetscFunctionReturn(0);
9494 }
9495 
9496 /*@
9497   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9498 
9499    Logically Collective on Mat
9500 
9501    Input Parameters:
9502 .  F - the factored matrix obtained by calling MatGetFactor()
9503 
9504    Notes:
9505     Must be called after MatFactorSetSchurIS().
9506 
9507    Call MatFactorGetSchurComplement() or  MatFactorCreateSchurComplement() AFTER this call to actually compute the inverse and get access to it.
9508 
9509    Level: advanced
9510 
9511    References:
9512 
9513 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9514 @*/
9515 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9516 {
9517   PetscFunctionBegin;
9518   PetscValidType(F,1);
9519   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9520   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9521   PetscCall(MatFactorFactorizeSchurComplement(F));
9522   PetscCall(MatFactorInvertSchurComplement_Private(F));
9523   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9524   PetscFunctionReturn(0);
9525 }
9526 
9527 /*@
9528   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9529 
9530    Logically Collective on Mat
9531 
9532    Input Parameters:
9533 .  F - the factored matrix obtained by calling MatGetFactor()
9534 
9535    Notes:
9536     Must be called after MatFactorSetSchurIS().
9537 
9538    Level: advanced
9539 
9540    References:
9541 
9542 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9543 @*/
9544 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9545 {
9546   PetscFunctionBegin;
9547   PetscValidType(F,1);
9548   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9549   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9550   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9551   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9552   PetscFunctionReturn(0);
9553 }
9554 
9555 /*@
9556    MatPtAP - Creates the matrix product C = P^T * A * P
9557 
9558    Neighbor-wise Collective on Mat
9559 
9560    Input Parameters:
9561 +  A - the matrix
9562 .  P - the projection matrix
9563 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9564 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use PETSC_DEFAULT if you do not have a good estimate
9565           if the result is a dense matrix this is irrelevant
9566 
9567    Output Parameters:
9568 .  C - the product matrix
9569 
9570    Notes:
9571    C will be created and must be destroyed by the user with MatDestroy().
9572 
9573    For matrix types without special implementation the function fallbacks to MatMatMult() followed by MatTransposeMatMult().
9574 
9575    Level: intermediate
9576 
9577 .seealso: `MatMatMult()`, `MatRARt()`
9578 @*/
9579 PetscErrorCode MatPtAP(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
9580 {
9581   PetscFunctionBegin;
9582   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9583   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9584 
9585   if (scall == MAT_INITIAL_MATRIX) {
9586     PetscCall(MatProductCreate(A,P,NULL,C));
9587     PetscCall(MatProductSetType(*C,MATPRODUCT_PtAP));
9588     PetscCall(MatProductSetAlgorithm(*C,"default"));
9589     PetscCall(MatProductSetFill(*C,fill));
9590 
9591     (*C)->product->api_user = PETSC_TRUE;
9592     PetscCall(MatProductSetFromOptions(*C));
9593     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);
9594     PetscCall(MatProductSymbolic(*C));
9595   } else { /* scall == MAT_REUSE_MATRIX */
9596     PetscCall(MatProductReplaceMats(A,P,NULL,*C));
9597   }
9598 
9599   PetscCall(MatProductNumeric(*C));
9600   if (A->symmetric) {
9601     if (A->spd) {
9602       PetscCall(MatSetOption(*C,MAT_SPD,PETSC_TRUE));
9603     } else {
9604       PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9605     }
9606   }
9607   PetscFunctionReturn(0);
9608 }
9609 
9610 /*@
9611    MatRARt - Creates the matrix product C = R * A * R^T
9612 
9613    Neighbor-wise Collective on Mat
9614 
9615    Input Parameters:
9616 +  A - the matrix
9617 .  R - the projection matrix
9618 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9619 -  fill - expected fill as ratio of nnz(C)/nnz(A), use PETSC_DEFAULT if you do not have a good estimate
9620           if the result is a dense matrix this is irrelevant
9621 
9622    Output Parameters:
9623 .  C - the product matrix
9624 
9625    Notes:
9626    C will be created and must be destroyed by the user with MatDestroy().
9627 
9628    This routine is currently only implemented for pairs of AIJ matrices and classes
9629    which inherit from AIJ. Due to PETSc sparse matrix block row distribution among processes,
9630    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9631    We recommend using MatPtAP().
9632 
9633    Level: intermediate
9634 
9635 .seealso: `MatMatMult()`, `MatPtAP()`
9636 @*/
9637 PetscErrorCode MatRARt(Mat A,Mat R,MatReuse scall,PetscReal fill,Mat *C)
9638 {
9639   PetscFunctionBegin;
9640   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C,5);
9641   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9642 
9643   if (scall == MAT_INITIAL_MATRIX) {
9644     PetscCall(MatProductCreate(A,R,NULL,C));
9645     PetscCall(MatProductSetType(*C,MATPRODUCT_RARt));
9646     PetscCall(MatProductSetAlgorithm(*C,"default"));
9647     PetscCall(MatProductSetFill(*C,fill));
9648 
9649     (*C)->product->api_user = PETSC_TRUE;
9650     PetscCall(MatProductSetFromOptions(*C));
9651     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);
9652     PetscCall(MatProductSymbolic(*C));
9653   } else { /* scall == MAT_REUSE_MATRIX */
9654     PetscCall(MatProductReplaceMats(A,R,NULL,*C));
9655   }
9656 
9657   PetscCall(MatProductNumeric(*C));
9658   if (A->symmetric_set && A->symmetric) {
9659     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9660   }
9661   PetscFunctionReturn(0);
9662 }
9663 
9664 static PetscErrorCode MatProduct_Private(Mat A,Mat B,MatReuse scall,PetscReal fill,MatProductType ptype, Mat *C)
9665 {
9666   PetscFunctionBegin;
9667   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9668 
9669   if (scall == MAT_INITIAL_MATRIX) {
9670     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n",MatProductTypes[ptype]));
9671     PetscCall(MatProductCreate(A,B,NULL,C));
9672     PetscCall(MatProductSetType(*C,ptype));
9673     PetscCall(MatProductSetAlgorithm(*C,MATPRODUCTALGORITHMDEFAULT));
9674     PetscCall(MatProductSetFill(*C,fill));
9675 
9676     (*C)->product->api_user = PETSC_TRUE;
9677     PetscCall(MatProductSetFromOptions(*C));
9678     PetscCall(MatProductSymbolic(*C));
9679   } else { /* scall == MAT_REUSE_MATRIX */
9680     Mat_Product *product = (*C)->product;
9681     PetscBool isdense;
9682 
9683     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C),&isdense,MATSEQDENSE,MATMPIDENSE,""));
9684     if (isdense && product && product->type != ptype) {
9685       PetscCall(MatProductClear(*C));
9686       product = NULL;
9687     }
9688     PetscCall(PetscInfo(A,"Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n",product ? "with" : "without",MatProductTypes[ptype]));
9689     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9690       if (isdense) {
9691         PetscCall(MatProductCreate_Private(A,B,NULL,*C));
9692         product = (*C)->product;
9693         product->fill     = fill;
9694         product->api_user = PETSC_TRUE;
9695         product->clear    = PETSC_TRUE;
9696 
9697         PetscCall(MatProductSetType(*C,ptype));
9698         PetscCall(MatProductSetFromOptions(*C));
9699         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);
9700         PetscCall(MatProductSymbolic(*C));
9701       } else SETERRQ(PetscObjectComm((PetscObject)(*C)),PETSC_ERR_SUP,"Call MatProductCreate() first");
9702     } else { /* user may change input matrices A or B when REUSE */
9703       PetscCall(MatProductReplaceMats(A,B,NULL,*C));
9704     }
9705   }
9706   PetscCall(MatProductNumeric(*C));
9707   PetscFunctionReturn(0);
9708 }
9709 
9710 /*@
9711    MatMatMult - Performs Matrix-Matrix Multiplication C=A*B.
9712 
9713    Neighbor-wise Collective on Mat
9714 
9715    Input Parameters:
9716 +  A - the left matrix
9717 .  B - the right matrix
9718 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9719 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if you do not have a good estimate
9720           if the result is a dense matrix this is irrelevant
9721 
9722    Output Parameters:
9723 .  C - the product matrix
9724 
9725    Notes:
9726    Unless scall is MAT_REUSE_MATRIX C will be created.
9727 
9728    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
9729    call to this function with MAT_INITIAL_MATRIX.
9730 
9731    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9732 
9733    If you have many matrices with the same non-zero structure to multiply, you should use MatProductCreate()/MatProductSymbolic()/MatProductReplaceMats(), and call MatProductNumeric() repeatedly.
9734 
9735    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.
9736 
9737    Example of Usage:
9738 .vb
9739      MatProductCreate(A,B,NULL,&C);
9740      MatProductSetType(C,MATPRODUCT_AB);
9741      MatProductSymbolic(C);
9742      MatProductNumeric(C); // compute C=A * B
9743      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9744      MatProductNumeric(C);
9745      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9746      MatProductNumeric(C);
9747 .ve
9748 
9749    Level: intermediate
9750 
9751 .seealso: `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9752 @*/
9753 PetscErrorCode MatMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9754 {
9755   PetscFunctionBegin;
9756   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AB,C));
9757   PetscFunctionReturn(0);
9758 }
9759 
9760 /*@
9761    MatMatTransposeMult - Performs Matrix-Matrix Multiplication C=A*B^T.
9762 
9763    Neighbor-wise Collective on Mat
9764 
9765    Input Parameters:
9766 +  A - the left matrix
9767 .  B - the right matrix
9768 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9769 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9770 
9771    Output Parameters:
9772 .  C - the product matrix
9773 
9774    Notes:
9775    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9776 
9777    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9778 
9779   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9780    actually needed.
9781 
9782    This routine is currently only implemented for pairs of SeqAIJ matrices, for the SeqDense class,
9783    and for pairs of MPIDense matrices.
9784 
9785    Options Database Keys:
9786 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for MPIDense matrices: the
9787               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9788               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9789 
9790    Level: intermediate
9791 
9792 .seealso: `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`
9793 @*/
9794 PetscErrorCode MatMatTransposeMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9795 {
9796   PetscFunctionBegin;
9797   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_ABt,C));
9798   if (A == B) {
9799     PetscCall(MatSetOption(*C,MAT_SYMMETRIC,PETSC_TRUE));
9800   }
9801   PetscFunctionReturn(0);
9802 }
9803 
9804 /*@
9805    MatTransposeMatMult - Performs Matrix-Matrix Multiplication C=A^T*B.
9806 
9807    Neighbor-wise Collective on Mat
9808 
9809    Input Parameters:
9810 +  A - the left matrix
9811 .  B - the right matrix
9812 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9813 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9814 
9815    Output Parameters:
9816 .  C - the product matrix
9817 
9818    Notes:
9819    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9820 
9821    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9822 
9823   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9824    actually needed.
9825 
9826    This routine is currently implemented for pairs of AIJ matrices and pairs of SeqDense matrices and classes
9827    which inherit from SeqAIJ.  C will be of the same type as the input matrices.
9828 
9829    Level: intermediate
9830 
9831 .seealso: `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9832 @*/
9833 PetscErrorCode MatTransposeMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9834 {
9835   PetscFunctionBegin;
9836   PetscCall(MatProduct_Private(A,B,scall,fill,MATPRODUCT_AtB,C));
9837   PetscFunctionReturn(0);
9838 }
9839 
9840 /*@
9841    MatMatMatMult - Performs Matrix-Matrix-Matrix Multiplication D=A*B*C.
9842 
9843    Neighbor-wise Collective on Mat
9844 
9845    Input Parameters:
9846 +  A - the left matrix
9847 .  B - the middle matrix
9848 .  C - the right matrix
9849 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9850 -  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
9851           if the result is a dense matrix this is irrelevant
9852 
9853    Output Parameters:
9854 .  D - the product matrix
9855 
9856    Notes:
9857    Unless scall is MAT_REUSE_MATRIX D will be created.
9858 
9859    MAT_REUSE_MATRIX can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9860 
9861    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9862    actually needed.
9863 
9864    If you have many matrices with the same non-zero structure to multiply, you
9865    should use MAT_REUSE_MATRIX in all calls but the first
9866 
9867    Level: intermediate
9868 
9869 .seealso: `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9870 @*/
9871 PetscErrorCode MatMatMatMult(Mat A,Mat B,Mat C,MatReuse scall,PetscReal fill,Mat *D)
9872 {
9873   PetscFunctionBegin;
9874   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D,6);
9875   PetscCheck(scall != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9876 
9877   if (scall == MAT_INITIAL_MATRIX) {
9878     PetscCall(MatProductCreate(A,B,C,D));
9879     PetscCall(MatProductSetType(*D,MATPRODUCT_ABC));
9880     PetscCall(MatProductSetAlgorithm(*D,"default"));
9881     PetscCall(MatProductSetFill(*D,fill));
9882 
9883     (*D)->product->api_user = PETSC_TRUE;
9884     PetscCall(MatProductSetFromOptions(*D));
9885     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);
9886     PetscCall(MatProductSymbolic(*D));
9887   } else { /* user may change input matrices when REUSE */
9888     PetscCall(MatProductReplaceMats(A,B,C,*D));
9889   }
9890   PetscCall(MatProductNumeric(*D));
9891   PetscFunctionReturn(0);
9892 }
9893 
9894 /*@
9895    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9896 
9897    Collective on Mat
9898 
9899    Input Parameters:
9900 +  mat - the matrix
9901 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9902 .  subcomm - MPI communicator split from the communicator where mat resides in (or MPI_COMM_NULL if nsubcomm is used)
9903 -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9904 
9905    Output Parameter:
9906 .  matredundant - redundant matrix
9907 
9908    Notes:
9909    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
9910    original matrix has not changed from that last call to MatCreateRedundantMatrix().
9911 
9912    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9913    calling it.
9914 
9915    Level: advanced
9916 
9917 .seealso: `MatDestroy()`
9918 @*/
9919 PetscErrorCode MatCreateRedundantMatrix(Mat mat,PetscInt nsubcomm,MPI_Comm subcomm,MatReuse reuse,Mat *matredundant)
9920 {
9921   MPI_Comm       comm;
9922   PetscMPIInt    size;
9923   PetscInt       mloc_sub,nloc_sub,rstart,rend,M=mat->rmap->N,N=mat->cmap->N,bs=mat->rmap->bs;
9924   Mat_Redundant  *redund=NULL;
9925   PetscSubcomm   psubcomm=NULL;
9926   MPI_Comm       subcomm_in=subcomm;
9927   Mat            *matseq;
9928   IS             isrow,iscol;
9929   PetscBool      newsubcomm=PETSC_FALSE;
9930 
9931   PetscFunctionBegin;
9932   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9933   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9934     PetscValidPointer(*matredundant,5);
9935     PetscValidHeaderSpecific(*matredundant,MAT_CLASSID,5);
9936   }
9937 
9938   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
9939   if (size == 1 || nsubcomm == 1) {
9940     if (reuse == MAT_INITIAL_MATRIX) {
9941       PetscCall(MatDuplicate(mat,MAT_COPY_VALUES,matredundant));
9942     } else {
9943       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");
9944       PetscCall(MatCopy(mat,*matredundant,SAME_NONZERO_PATTERN));
9945     }
9946     PetscFunctionReturn(0);
9947   }
9948 
9949   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9950   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9951   MatCheckPreallocated(mat,1);
9952 
9953   PetscCall(PetscLogEventBegin(MAT_RedundantMat,mat,0,0,0));
9954   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9955     /* create psubcomm, then get subcomm */
9956     PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
9957     PetscCallMPI(MPI_Comm_size(comm,&size));
9958     PetscCheck(nsubcomm >= 1 && nsubcomm <= size,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"nsubcomm must between 1 and %d",size);
9959 
9960     PetscCall(PetscSubcommCreate(comm,&psubcomm));
9961     PetscCall(PetscSubcommSetNumber(psubcomm,nsubcomm));
9962     PetscCall(PetscSubcommSetType(psubcomm,PETSC_SUBCOMM_CONTIGUOUS));
9963     PetscCall(PetscSubcommSetFromOptions(psubcomm));
9964     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm),&subcomm,NULL));
9965     newsubcomm = PETSC_TRUE;
9966     PetscCall(PetscSubcommDestroy(&psubcomm));
9967   }
9968 
9969   /* get isrow, iscol and a local sequential matrix matseq[0] */
9970   if (reuse == MAT_INITIAL_MATRIX) {
9971     mloc_sub = PETSC_DECIDE;
9972     nloc_sub = PETSC_DECIDE;
9973     if (bs < 1) {
9974       PetscCall(PetscSplitOwnership(subcomm,&mloc_sub,&M));
9975       PetscCall(PetscSplitOwnership(subcomm,&nloc_sub,&N));
9976     } else {
9977       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&mloc_sub,&M));
9978       PetscCall(PetscSplitOwnershipBlock(subcomm,bs,&nloc_sub,&N));
9979     }
9980     PetscCallMPI(MPI_Scan(&mloc_sub,&rend,1,MPIU_INT,MPI_SUM,subcomm));
9981     rstart = rend - mloc_sub;
9982     PetscCall(ISCreateStride(PETSC_COMM_SELF,mloc_sub,rstart,1,&isrow));
9983     PetscCall(ISCreateStride(PETSC_COMM_SELF,N,0,1,&iscol));
9984   } else { /* reuse == MAT_REUSE_MATRIX */
9985     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");
9986     /* retrieve subcomm */
9987     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant),&subcomm));
9988     redund = (*matredundant)->redundant;
9989     isrow  = redund->isrow;
9990     iscol  = redund->iscol;
9991     matseq = redund->matseq;
9992   }
9993   PetscCall(MatCreateSubMatrices(mat,1,&isrow,&iscol,reuse,&matseq));
9994 
9995   /* get matredundant over subcomm */
9996   if (reuse == MAT_INITIAL_MATRIX) {
9997     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],nloc_sub,reuse,matredundant));
9998 
9999     /* create a supporting struct and attach it to C for reuse */
10000     PetscCall(PetscNewLog(*matredundant,&redund));
10001     (*matredundant)->redundant = redund;
10002     redund->isrow              = isrow;
10003     redund->iscol              = iscol;
10004     redund->matseq             = matseq;
10005     if (newsubcomm) {
10006       redund->subcomm          = subcomm;
10007     } else {
10008       redund->subcomm          = MPI_COMM_NULL;
10009     }
10010   } else {
10011     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],PETSC_DECIDE,reuse,matredundant));
10012   }
10013 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
10014   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10015     PetscCall(MatBindToCPU(*matredundant,PETSC_TRUE));
10016     PetscCall(MatSetBindingPropagates(*matredundant,PETSC_TRUE));
10017   }
10018 #endif
10019   PetscCall(PetscLogEventEnd(MAT_RedundantMat,mat,0,0,0));
10020   PetscFunctionReturn(0);
10021 }
10022 
10023 /*@C
10024    MatGetMultiProcBlock - Create multiple [bjacobi] 'parallel submatrices' from
10025    a given 'mat' object. Each submatrix can span multiple procs.
10026 
10027    Collective on Mat
10028 
10029    Input Parameters:
10030 +  mat - the matrix
10031 .  subcomm - the subcommunicator obtained by com_split(comm)
10032 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10033 
10034    Output Parameter:
10035 .  subMat - 'parallel submatrices each spans a given subcomm
10036 
10037   Notes:
10038   The submatrix partition across processors is dictated by 'subComm' a
10039   communicator obtained by MPI_comm_split(). The subComm
10040   is not restriced to be grouped with consecutive original ranks.
10041 
10042   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10043   map directly to the layout of the original matrix [wrt the local
10044   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10045   into the 'DiagonalMat' of the subMat, hence it is used directly from
10046   the subMat. However the offDiagMat looses some columns - and this is
10047   reconstructed with MatSetValues()
10048 
10049   Level: advanced
10050 
10051 .seealso: `MatCreateSubMatrices()`
10052 @*/
10053 PetscErrorCode   MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall,Mat *subMat)
10054 {
10055   PetscMPIInt    commsize,subCommSize;
10056 
10057   PetscFunctionBegin;
10058   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&commsize));
10059   PetscCallMPI(MPI_Comm_size(subComm,&subCommSize));
10060   PetscCheck(subCommSize <= commsize,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"CommSize %d < SubCommZize %d",commsize,subCommSize);
10061 
10062   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");
10063   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock,mat,0,0,0));
10064   PetscCall((*mat->ops->getmultiprocblock)(mat,subComm,scall,subMat));
10065   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock,mat,0,0,0));
10066   PetscFunctionReturn(0);
10067 }
10068 
10069 /*@
10070    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10071 
10072    Not Collective
10073 
10074    Input Parameters:
10075 +  mat - matrix to extract local submatrix from
10076 .  isrow - local row indices for submatrix
10077 -  iscol - local column indices for submatrix
10078 
10079    Output Parameter:
10080 .  submat - the submatrix
10081 
10082    Level: intermediate
10083 
10084    Notes:
10085    The submat should be returned with MatRestoreLocalSubMatrix().
10086 
10087    Depending on the format of mat, the returned submat may not implement MatMult().  Its communicator may be
10088    the same as mat, it may be PETSC_COMM_SELF, or some other subcomm of mat's.
10089 
10090    The submat always implements MatSetValuesLocal().  If isrow and iscol have the same block size, then
10091    MatSetValuesBlockedLocal() will also be implemented.
10092 
10093    The mat must have had a ISLocalToGlobalMapping provided to it with MatSetLocalToGlobalMapping(). Note that
10094    matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10095 
10096 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10097 @*/
10098 PetscErrorCode MatGetLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10099 {
10100   PetscFunctionBegin;
10101   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10102   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10103   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10104   PetscCheckSameComm(isrow,2,iscol,3);
10105   PetscValidPointer(submat,4);
10106   PetscCheck(mat->rmap->mapping,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must have local to global mapping provided before this call");
10107 
10108   if (mat->ops->getlocalsubmatrix) {
10109     PetscCall((*mat->ops->getlocalsubmatrix)(mat,isrow,iscol,submat));
10110   } else {
10111     PetscCall(MatCreateLocalRef(mat,isrow,iscol,submat));
10112   }
10113   PetscFunctionReturn(0);
10114 }
10115 
10116 /*@
10117    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering
10118 
10119    Not Collective
10120 
10121    Input Parameters:
10122 +  mat - matrix to extract local submatrix from
10123 .  isrow - local row indices for submatrix
10124 .  iscol - local column indices for submatrix
10125 -  submat - the submatrix
10126 
10127    Level: intermediate
10128 
10129 .seealso: `MatGetLocalSubMatrix()`
10130 @*/
10131 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10132 {
10133   PetscFunctionBegin;
10134   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10135   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10136   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10137   PetscCheckSameComm(isrow,2,iscol,3);
10138   PetscValidPointer(submat,4);
10139   if (*submat) {
10140     PetscValidHeaderSpecific(*submat,MAT_CLASSID,4);
10141   }
10142 
10143   if (mat->ops->restorelocalsubmatrix) {
10144     PetscCall((*mat->ops->restorelocalsubmatrix)(mat,isrow,iscol,submat));
10145   } else {
10146     PetscCall(MatDestroy(submat));
10147   }
10148   *submat = NULL;
10149   PetscFunctionReturn(0);
10150 }
10151 
10152 /* --------------------------------------------------------*/
10153 /*@
10154    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10155 
10156    Collective on Mat
10157 
10158    Input Parameter:
10159 .  mat - the matrix
10160 
10161    Output Parameter:
10162 .  is - if any rows have zero diagonals this contains the list of them
10163 
10164    Level: developer
10165 
10166 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10167 @*/
10168 PetscErrorCode MatFindZeroDiagonals(Mat mat,IS *is)
10169 {
10170   PetscFunctionBegin;
10171   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10172   PetscValidType(mat,1);
10173   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10174   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10175 
10176   if (!mat->ops->findzerodiagonals) {
10177     Vec                diag;
10178     const PetscScalar *a;
10179     PetscInt          *rows;
10180     PetscInt           rStart, rEnd, r, nrow = 0;
10181 
10182     PetscCall(MatCreateVecs(mat, &diag, NULL));
10183     PetscCall(MatGetDiagonal(mat, diag));
10184     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10185     PetscCall(VecGetArrayRead(diag, &a));
10186     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) ++nrow;
10187     PetscCall(PetscMalloc1(nrow, &rows));
10188     nrow = 0;
10189     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) rows[nrow++] = r+rStart;
10190     PetscCall(VecRestoreArrayRead(diag, &a));
10191     PetscCall(VecDestroy(&diag));
10192     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) mat), nrow, rows, PETSC_OWN_POINTER, is));
10193   } else {
10194     PetscCall((*mat->ops->findzerodiagonals)(mat, is));
10195   }
10196   PetscFunctionReturn(0);
10197 }
10198 
10199 /*@
10200    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10201 
10202    Collective on Mat
10203 
10204    Input Parameter:
10205 .  mat - the matrix
10206 
10207    Output Parameter:
10208 .  is - contains the list of rows with off block diagonal entries
10209 
10210    Level: developer
10211 
10212 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10213 @*/
10214 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat,IS *is)
10215 {
10216   PetscFunctionBegin;
10217   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10218   PetscValidType(mat,1);
10219   PetscCheck(mat->assembled,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10220   PetscCheck(!mat->factortype,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10221 
10222   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);
10223   PetscCall((*mat->ops->findoffblockdiagonalentries)(mat,is));
10224   PetscFunctionReturn(0);
10225 }
10226 
10227 /*@C
10228   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10229 
10230   Collective on Mat
10231 
10232   Input Parameters:
10233 . mat - the matrix
10234 
10235   Output Parameters:
10236 . values - the block inverses in column major order (FORTRAN-like)
10237 
10238    Note:
10239      The size of the blocks is determined by the block size of the matrix.
10240 
10241    Fortran Note:
10242      This routine is not available from Fortran.
10243 
10244   Level: advanced
10245 
10246 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10247 @*/
10248 PetscErrorCode MatInvertBlockDiagonal(Mat mat,const PetscScalar **values)
10249 {
10250   PetscFunctionBegin;
10251   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10252   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10253   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10254   PetscCheck(mat->ops->invertblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10255   PetscCall((*mat->ops->invertblockdiagonal)(mat,values));
10256   PetscFunctionReturn(0);
10257 }
10258 
10259 /*@C
10260   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10261 
10262   Collective on Mat
10263 
10264   Input Parameters:
10265 + mat - the matrix
10266 . nblocks - the number of blocks on the process, set with MatSetVariableBlockSizes()
10267 - bsizes - the size of each block on the process, set with MatSetVariableBlockSizes()
10268 
10269   Output Parameters:
10270 . values - the block inverses in column major order (FORTRAN-like)
10271 
10272    Note:
10273    This routine is not available from Fortran.
10274 
10275   Level: advanced
10276 
10277 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10278 @*/
10279 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *values)
10280 {
10281   PetscFunctionBegin;
10282   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10283   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10284   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10285   PetscCheck(mat->ops->invertvariableblockdiagonal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for type %s",((PetscObject)mat)->type_name);
10286   PetscCall((*mat->ops->invertvariableblockdiagonal)(mat,nblocks,bsizes,values));
10287   PetscFunctionReturn(0);
10288 }
10289 
10290 /*@
10291   MatInvertBlockDiagonalMat - set matrix C to be the inverted block diagonal of matrix A
10292 
10293   Collective on Mat
10294 
10295   Input Parameters:
10296 . A - the matrix
10297 
10298   Output Parameters:
10299 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10300 
10301   Notes: the blocksize of the matrix is used to determine the blocks on the diagonal of C
10302 
10303   Level: advanced
10304 
10305 .seealso: `MatInvertBlockDiagonal()`
10306 @*/
10307 PetscErrorCode MatInvertBlockDiagonalMat(Mat A,Mat C)
10308 {
10309   const PetscScalar *vals;
10310   PetscInt          *dnnz;
10311   PetscInt           m,rstart,rend,bs,i,j;
10312 
10313   PetscFunctionBegin;
10314   PetscCall(MatInvertBlockDiagonal(A,&vals));
10315   PetscCall(MatGetBlockSize(A,&bs));
10316   PetscCall(MatGetLocalSize(A,&m,NULL));
10317   PetscCall(MatSetLayouts(C,A->rmap,A->cmap));
10318   PetscCall(PetscMalloc1(m/bs,&dnnz));
10319   for (j = 0; j < m/bs; j++) dnnz[j] = 1;
10320   PetscCall(MatXAIJSetPreallocation(C,bs,dnnz,NULL,NULL,NULL));
10321   PetscCall(PetscFree(dnnz));
10322   PetscCall(MatGetOwnershipRange(C,&rstart,&rend));
10323   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_FALSE));
10324   for (i = rstart/bs; i < rend/bs; i++) {
10325     PetscCall(MatSetValuesBlocked(C,1,&i,1,&i,&vals[(i-rstart/bs)*bs*bs],INSERT_VALUES));
10326   }
10327   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
10328   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
10329   PetscCall(MatSetOption(C,MAT_ROW_ORIENTED,PETSC_TRUE));
10330   PetscFunctionReturn(0);
10331 }
10332 
10333 /*@C
10334     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10335     via MatTransposeColoringCreate().
10336 
10337     Collective on MatTransposeColoring
10338 
10339     Input Parameter:
10340 .   c - coloring context
10341 
10342     Level: intermediate
10343 
10344 .seealso: `MatTransposeColoringCreate()`
10345 @*/
10346 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10347 {
10348   MatTransposeColoring matcolor=*c;
10349 
10350   PetscFunctionBegin;
10351   if (!matcolor) PetscFunctionReturn(0);
10352   if (--((PetscObject)matcolor)->refct > 0) {matcolor = NULL; PetscFunctionReturn(0);}
10353 
10354   PetscCall(PetscFree3(matcolor->ncolumns,matcolor->nrows,matcolor->colorforrow));
10355   PetscCall(PetscFree(matcolor->rows));
10356   PetscCall(PetscFree(matcolor->den2sp));
10357   PetscCall(PetscFree(matcolor->colorforcol));
10358   PetscCall(PetscFree(matcolor->columns));
10359   if (matcolor->brows>0) PetscCall(PetscFree(matcolor->lstart));
10360   PetscCall(PetscHeaderDestroy(c));
10361   PetscFunctionReturn(0);
10362 }
10363 
10364 /*@C
10365     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10366     a MatTransposeColoring context has been created, computes a dense B^T by Apply
10367     MatTransposeColoring to sparse B.
10368 
10369     Collective on MatTransposeColoring
10370 
10371     Input Parameters:
10372 +   B - sparse matrix B
10373 .   Btdense - symbolic dense matrix B^T
10374 -   coloring - coloring context created with MatTransposeColoringCreate()
10375 
10376     Output Parameter:
10377 .   Btdense - dense matrix B^T
10378 
10379     Level: advanced
10380 
10381      Notes:
10382     These are used internally for some implementations of MatRARt()
10383 
10384 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10385 
10386 @*/
10387 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring,Mat B,Mat Btdense)
10388 {
10389   PetscFunctionBegin;
10390   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10391   PetscValidHeaderSpecific(Btdense,MAT_CLASSID,3);
10392   PetscValidHeaderSpecific(coloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10393 
10394   PetscCheck(B->ops->transcoloringapplysptoden,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)B)->type_name);
10395   PetscCall((B->ops->transcoloringapplysptoden)(coloring,B,Btdense));
10396   PetscFunctionReturn(0);
10397 }
10398 
10399 /*@C
10400     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10401     a MatTransposeColoring context has been created and a dense matrix Cden=A*Btdense
10402     in which Btdens is obtained from MatTransColoringApplySpToDen(), recover sparse matrix
10403     Csp from Cden.
10404 
10405     Collective on MatTransposeColoring
10406 
10407     Input Parameters:
10408 +   coloring - coloring context created with MatTransposeColoringCreate()
10409 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10410 
10411     Output Parameter:
10412 .   Csp - sparse matrix
10413 
10414     Level: advanced
10415 
10416      Notes:
10417     These are used internally for some implementations of MatRARt()
10418 
10419 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10420 
10421 @*/
10422 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring,Mat Cden,Mat Csp)
10423 {
10424   PetscFunctionBegin;
10425   PetscValidHeaderSpecific(matcoloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10426   PetscValidHeaderSpecific(Cden,MAT_CLASSID,2);
10427   PetscValidHeaderSpecific(Csp,MAT_CLASSID,3);
10428 
10429   PetscCheck(Csp->ops->transcoloringapplydentosp,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)Csp)->type_name);
10430   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring,Cden,Csp));
10431   PetscCall(MatAssemblyBegin(Csp,MAT_FINAL_ASSEMBLY));
10432   PetscCall(MatAssemblyEnd(Csp,MAT_FINAL_ASSEMBLY));
10433   PetscFunctionReturn(0);
10434 }
10435 
10436 /*@C
10437    MatTransposeColoringCreate - Creates a matrix coloring context for matrix product C=A*B^T.
10438 
10439    Collective on Mat
10440 
10441    Input Parameters:
10442 +  mat - the matrix product C
10443 -  iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring()
10444 
10445     Output Parameter:
10446 .   color - the new coloring context
10447 
10448     Level: intermediate
10449 
10450 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10451           `MatTransColoringApplyDenToSp()`
10452 @*/
10453 PetscErrorCode MatTransposeColoringCreate(Mat mat,ISColoring iscoloring,MatTransposeColoring *color)
10454 {
10455   MatTransposeColoring c;
10456   MPI_Comm             comm;
10457 
10458   PetscFunctionBegin;
10459   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate,mat,0,0,0));
10460   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
10461   PetscCall(PetscHeaderCreate(c,MAT_TRANSPOSECOLORING_CLASSID,"MatTransposeColoring","Matrix product C=A*B^T via coloring","Mat",comm,MatTransposeColoringDestroy,NULL));
10462 
10463   c->ctype = iscoloring->ctype;
10464   if (mat->ops->transposecoloringcreate) {
10465     PetscCall((*mat->ops->transposecoloringcreate)(mat,iscoloring,c));
10466   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);
10467 
10468   *color = c;
10469   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate,mat,0,0,0));
10470   PetscFunctionReturn(0);
10471 }
10472 
10473 /*@
10474       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10475         matrix has had no new nonzero locations added to the matrix since the previous call then the value will be the
10476         same, otherwise it will be larger
10477 
10478      Not Collective
10479 
10480   Input Parameter:
10481 .    A  - the matrix
10482 
10483   Output Parameter:
10484 .    state - the current state
10485 
10486   Notes:
10487     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10488          different matrices
10489 
10490   Level: intermediate
10491 
10492 .seealso: `PetscObjectStateGet()`
10493 @*/
10494 PetscErrorCode MatGetNonzeroState(Mat mat,PetscObjectState *state)
10495 {
10496   PetscFunctionBegin;
10497   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10498   *state = mat->nonzerostate;
10499   PetscFunctionReturn(0);
10500 }
10501 
10502 /*@
10503       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10504                  matrices from each processor
10505 
10506     Collective
10507 
10508    Input Parameters:
10509 +    comm - the communicators the parallel matrix will live on
10510 .    seqmat - the input sequential matrices
10511 .    n - number of local columns (or PETSC_DECIDE)
10512 -    reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10513 
10514    Output Parameter:
10515 .    mpimat - the parallel matrix generated
10516 
10517     Level: advanced
10518 
10519    Notes:
10520     The number of columns of the matrix in EACH processor MUST be the same.
10521 
10522 @*/
10523 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm,Mat seqmat,PetscInt n,MatReuse reuse,Mat *mpimat)
10524 {
10525   PetscFunctionBegin;
10526   PetscCheck(seqmat->ops->creatempimatconcatenateseqmat,PetscObjectComm((PetscObject)seqmat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)seqmat)->type_name);
10527   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");
10528 
10529   PetscCall(PetscLogEventBegin(MAT_Merge,seqmat,0,0,0));
10530   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm,seqmat,n,reuse,mpimat));
10531   PetscCall(PetscLogEventEnd(MAT_Merge,seqmat,0,0,0));
10532   PetscFunctionReturn(0);
10533 }
10534 
10535 /*@
10536      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent
10537                  ranks' ownership ranges.
10538 
10539     Collective on A
10540 
10541    Input Parameters:
10542 +    A   - the matrix to create subdomains from
10543 -    N   - requested number of subdomains
10544 
10545    Output Parameters:
10546 +    n   - number of subdomains resulting on this rank
10547 -    iss - IS list with indices of subdomains on this rank
10548 
10549     Level: advanced
10550 
10551     Notes:
10552     number of subdomains must be smaller than the communicator size
10553 @*/
10554 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A,PetscInt N,PetscInt *n,IS *iss[])
10555 {
10556   MPI_Comm        comm,subcomm;
10557   PetscMPIInt     size,rank,color;
10558   PetscInt        rstart,rend,k;
10559 
10560   PetscFunctionBegin;
10561   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
10562   PetscCallMPI(MPI_Comm_size(comm,&size));
10563   PetscCallMPI(MPI_Comm_rank(comm,&rank));
10564   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);
10565   *n = 1;
10566   k = ((PetscInt)size)/N + ((PetscInt)size%N>0); /* There are up to k ranks to a color */
10567   color = rank/k;
10568   PetscCallMPI(MPI_Comm_split(comm,color,rank,&subcomm));
10569   PetscCall(PetscMalloc1(1,iss));
10570   PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
10571   PetscCall(ISCreateStride(subcomm,rend-rstart,rstart,1,iss[0]));
10572   PetscCallMPI(MPI_Comm_free(&subcomm));
10573   PetscFunctionReturn(0);
10574 }
10575 
10576 /*@
10577    MatGalerkin - Constructs the coarse grid problem via Galerkin projection.
10578 
10579    If the interpolation and restriction operators are the same, uses MatPtAP.
10580    If they are not the same, use MatMatMatMult.
10581 
10582    Once the coarse grid problem is constructed, correct for interpolation operators
10583    that are not of full rank, which can legitimately happen in the case of non-nested
10584    geometric multigrid.
10585 
10586    Input Parameters:
10587 +  restrct - restriction operator
10588 .  dA - fine grid matrix
10589 .  interpolate - interpolation operator
10590 .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10591 -  fill - expected fill, use PETSC_DEFAULT if you do not have a good estimate
10592 
10593    Output Parameters:
10594 .  A - the Galerkin coarse matrix
10595 
10596    Options Database Key:
10597 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10598 
10599    Level: developer
10600 
10601 .seealso: `MatPtAP()`, `MatMatMatMult()`
10602 @*/
10603 PetscErrorCode  MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10604 {
10605   IS             zerorows;
10606   Vec            diag;
10607 
10608   PetscFunctionBegin;
10609   PetscCheck(reuse != MAT_INPLACE_MATRIX,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
10610   /* Construct the coarse grid matrix */
10611   if (interpolate == restrct) {
10612     PetscCall(MatPtAP(dA,interpolate,reuse,fill,A));
10613   } else {
10614     PetscCall(MatMatMatMult(restrct,dA,interpolate,reuse,fill,A));
10615   }
10616 
10617   /* If the interpolation matrix is not of full rank, A will have zero rows.
10618      This can legitimately happen in the case of non-nested geometric multigrid.
10619      In that event, we set the rows of the matrix to the rows of the identity,
10620      ignoring the equations (as the RHS will also be zero). */
10621 
10622   PetscCall(MatFindZeroRows(*A, &zerorows));
10623 
10624   if (zerorows != NULL) { /* if there are any zero rows */
10625     PetscCall(MatCreateVecs(*A, &diag, NULL));
10626     PetscCall(MatGetDiagonal(*A, diag));
10627     PetscCall(VecISSet(diag, zerorows, 1.0));
10628     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10629     PetscCall(VecDestroy(&diag));
10630     PetscCall(ISDestroy(&zerorows));
10631   }
10632   PetscFunctionReturn(0);
10633 }
10634 
10635 /*@C
10636     MatSetOperation - Allows user to set a matrix operation for any matrix type
10637 
10638    Logically Collective on Mat
10639 
10640     Input Parameters:
10641 +   mat - the matrix
10642 .   op - the name of the operation
10643 -   f - the function that provides the operation
10644 
10645    Level: developer
10646 
10647     Usage:
10648 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10649 $      PetscCall(MatCreateXXX(comm,...&A);
10650 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10651 
10652     Notes:
10653     See the file include/petscmat.h for a complete list of matrix
10654     operations, which all have the form MATOP_<OPERATION>, where
10655     <OPERATION> is the name (in all capital letters) of the
10656     user interface routine (e.g., MatMult() -> MATOP_MULT).
10657 
10658     All user-provided functions (except for MATOP_DESTROY) should have the same calling
10659     sequence as the usual matrix interface routines, since they
10660     are intended to be accessed via the usual matrix interface
10661     routines, e.g.,
10662 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10663 
10664     In particular each function MUST return an error code of 0 on success and
10665     nonzero on failure.
10666 
10667     This routine is distinct from MatShellSetOperation() in that it can be called on any matrix type.
10668 
10669 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10670 @*/
10671 PetscErrorCode MatSetOperation(Mat mat,MatOperation op,void (*f)(void))
10672 {
10673   PetscFunctionBegin;
10674   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10675   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) {
10676     mat->ops->viewnative = mat->ops->view;
10677   }
10678   (((void(**)(void))mat->ops)[op]) = f;
10679   PetscFunctionReturn(0);
10680 }
10681 
10682 /*@C
10683     MatGetOperation - Gets a matrix operation for any matrix type.
10684 
10685     Not Collective
10686 
10687     Input Parameters:
10688 +   mat - the matrix
10689 -   op - the name of the operation
10690 
10691     Output Parameter:
10692 .   f - the function that provides the operation
10693 
10694     Level: developer
10695 
10696     Usage:
10697 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10698 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10699 
10700     Notes:
10701     See the file include/petscmat.h for a complete list of matrix
10702     operations, which all have the form MATOP_<OPERATION>, where
10703     <OPERATION> is the name (in all capital letters) of the
10704     user interface routine (e.g., MatMult() -> MATOP_MULT).
10705 
10706     This routine is distinct from MatShellGetOperation() in that it can be called on any matrix type.
10707 
10708 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10709 @*/
10710 PetscErrorCode MatGetOperation(Mat mat,MatOperation op,void(**f)(void))
10711 {
10712   PetscFunctionBegin;
10713   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10714   *f = (((void (**)(void))mat->ops)[op]);
10715   PetscFunctionReturn(0);
10716 }
10717 
10718 /*@
10719     MatHasOperation - Determines whether the given matrix supports the particular
10720     operation.
10721 
10722    Not Collective
10723 
10724    Input Parameters:
10725 +  mat - the matrix
10726 -  op - the operation, for example, MATOP_GET_DIAGONAL
10727 
10728    Output Parameter:
10729 .  has - either PETSC_TRUE or PETSC_FALSE
10730 
10731    Level: advanced
10732 
10733    Notes:
10734    See the file include/petscmat.h for a complete list of matrix
10735    operations, which all have the form MATOP_<OPERATION>, where
10736    <OPERATION> is the name (in all capital letters) of the
10737    user-level routine.  E.g., MatNorm() -> MATOP_NORM.
10738 
10739 .seealso: `MatCreateShell()`
10740 @*/
10741 PetscErrorCode MatHasOperation(Mat mat,MatOperation op,PetscBool *has)
10742 {
10743   PetscFunctionBegin;
10744   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10745   PetscValidBoolPointer(has,3);
10746   if (mat->ops->hasoperation) {
10747     PetscCall((*mat->ops->hasoperation)(mat,op,has));
10748   } else {
10749     if (((void**)mat->ops)[op]) *has = PETSC_TRUE;
10750     else {
10751       *has = PETSC_FALSE;
10752       if (op == MATOP_CREATE_SUBMATRIX) {
10753         PetscMPIInt size;
10754 
10755         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
10756         if (size == 1) {
10757           PetscCall(MatHasOperation(mat,MATOP_CREATE_SUBMATRICES,has));
10758         }
10759       }
10760     }
10761   }
10762   PetscFunctionReturn(0);
10763 }
10764 
10765 /*@
10766     MatHasCongruentLayouts - Determines whether the rows and columns layouts
10767     of the matrix are congruent
10768 
10769    Collective on mat
10770 
10771    Input Parameters:
10772 .  mat - the matrix
10773 
10774    Output Parameter:
10775 .  cong - either PETSC_TRUE or PETSC_FALSE
10776 
10777    Level: beginner
10778 
10779    Notes:
10780 
10781 .seealso: `MatCreate()`, `MatSetSizes()`
10782 @*/
10783 PetscErrorCode MatHasCongruentLayouts(Mat mat,PetscBool *cong)
10784 {
10785   PetscFunctionBegin;
10786   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10787   PetscValidType(mat,1);
10788   PetscValidBoolPointer(cong,2);
10789   if (!mat->rmap || !mat->cmap) {
10790     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10791     PetscFunctionReturn(0);
10792   }
10793   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10794     PetscCall(PetscLayoutSetUp(mat->rmap));
10795     PetscCall(PetscLayoutSetUp(mat->cmap));
10796     PetscCall(PetscLayoutCompare(mat->rmap,mat->cmap,cong));
10797     if (*cong) mat->congruentlayouts = 1;
10798     else       mat->congruentlayouts = 0;
10799   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10800   PetscFunctionReturn(0);
10801 }
10802 
10803 PetscErrorCode MatSetInf(Mat A)
10804 {
10805   PetscFunctionBegin;
10806   PetscCheck(A->ops->setinf,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10807   PetscCall((*A->ops->setinf)(A));
10808   PetscFunctionReturn(0);
10809 }
10810 
10811 /*C
10812    MatCreateGraph - create a scalar matrix, for use in graph algorithms
10813 
10814    Collective on mat
10815 
10816    Input Parameters:
10817 +  A - the matrix
10818 -  sym - PETSC_TRUE indicates that the graph will be symmetrized
10819 .  scale - PETSC_TRUE indicates that the graph will be scaled with the diagonal
10820 
10821    Output Parameter:
10822 .  graph - the resulting graph
10823 
10824    Level: advanced
10825 
10826    Notes:
10827 
10828 .seealso: `MatCreate()`, `MatFilter()`
10829 */
10830 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, Mat *graph)
10831 {
10832   PetscFunctionBegin;
10833   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
10834   PetscValidType(A,1);
10835   PetscValidPointer(graph,3);
10836   PetscCheck(A->ops->creategraph,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10837   PetscCall((*A->ops->creategraph)(A,sym,scale,graph));
10838   PetscFunctionReturn(0);
10839 }
10840 
10841 /*C
10842    MatFilter - filters a Mat values with an absolut value equal to or below a give threshold
10843 
10844    Collective on mat
10845 
10846    Input Parameter:
10847 .  value - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries <= value
10848 
10849    Input/Output Parameter:
10850 .  A - the Mat to filter in place
10851 
10852    Level: advanced
10853 
10854    Notes:
10855 
10856 .seealso: `MatCreate()`, `MatCreateGraph()`
10857 */
10858 PETSC_EXTERN PetscErrorCode MatFilter(Mat G,PetscReal value,Mat *F)
10859 {
10860   PetscFunctionBegin;
10861   PetscValidHeaderSpecific(G,MAT_CLASSID,1);
10862   PetscValidType(G,1);
10863   PetscValidPointer(F,3);
10864   if (value >= 0.0) {
10865     PetscCheck(G->ops->filter,PetscObjectComm((PetscObject)G),PETSC_ERR_SUP,"No support for this operation for this matrix type");
10866     PetscCall((G->ops->filter)(G,value,F));
10867   }
10868   PetscFunctionReturn(0);
10869 }
10870