xref: /petsc/src/mat/interface/matrix.c (revision d7ca06c0de435eadbf707aa307b64606df8edc03)
1 
2 /*
3    This is where the abstract matrix operations are defined
4 */
5 
6 #include <petsc/private/matimpl.h>        /*I "petscmat.h" I*/
7 #include <petsc/private/isimpl.h>
8 #include <petsc/private/vecimpl.h>
9 
10 /* Logging support */
11 PetscClassId MAT_CLASSID;
12 PetscClassId MAT_COLORING_CLASSID;
13 PetscClassId MAT_FDCOLORING_CLASSID;
14 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
15 
16 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultConstrained, MAT_MultAdd, MAT_MultTranspose;
17 PetscLogEvent MAT_MultTransposeConstrained, MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve,MAT_MatTrSolve;
18 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
19 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
20 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
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_Transpose_SeqAIJ, 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_SetValuesBatch;
36 PetscLogEvent MAT_ViennaCLCopyToGPU;
37 PetscLogEvent MAT_Merge,MAT_Residual,MAT_SetRandom;
38 PetscLogEvent MATCOLORING_Apply,MATCOLORING_Comm,MATCOLORING_Local,MATCOLORING_ISCreate,MATCOLORING_SetUp,MATCOLORING_Weights;
39 
40 const char *const MatFactorTypes[] = {"NONE","LU","CHOLESKY","ILU","ICC","ILUDT","MatFactorType","MAT_FACTOR_",0};
41 
42 /*@
43    MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated it randomly selects appropriate locations
44 
45    Logically Collective on Mat
46 
47    Input Parameters:
48 +  x  - the matrix
49 -  rctx - the random number context, formed by PetscRandomCreate(), or NULL and
50           it will create one internally.
51 
52    Output Parameter:
53 .  x  - the matrix
54 
55    Example of Usage:
56 .vb
57      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
58      MatSetRandom(x,rctx);
59      PetscRandomDestroy(rctx);
60 .ve
61 
62    Level: intermediate
63 
64    Concepts: matrix^setting to random
65    Concepts: random^matrix
66 
67 .seealso: MatZeroEntries(), MatSetValues(), PetscRandomCreate(), PetscRandomDestroy()
68 @*/
69 PetscErrorCode MatSetRandom(Mat x,PetscRandom rctx)
70 {
71   PetscErrorCode ierr;
72   PetscRandom    randObj = NULL;
73 
74   PetscFunctionBegin;
75   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
76   if (rctx) PetscValidHeaderSpecific(rctx,PETSC_RANDOM_CLASSID,2);
77   PetscValidType(x,1);
78 
79   if (!rctx) {
80     MPI_Comm comm;
81     ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr);
82     ierr = PetscRandomCreate(comm,&randObj);CHKERRQ(ierr);
83     ierr = PetscRandomSetFromOptions(randObj);CHKERRQ(ierr);
84     rctx = randObj;
85   }
86 
87   ierr = PetscLogEventBegin(MAT_SetRandom,x,rctx,0,0);CHKERRQ(ierr);
88   ierr = (*x->ops->setrandom)(x,rctx);CHKERRQ(ierr);
89   ierr = PetscLogEventEnd(MAT_SetRandom,x,rctx,0,0);CHKERRQ(ierr);
90 
91   x->assembled = PETSC_TRUE;
92   ierr         = PetscRandomDestroy(&randObj);CHKERRQ(ierr);
93   PetscFunctionReturn(0);
94 }
95 
96 /*@
97    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
98 
99    Logically Collective on Mat
100 
101    Input Parameters:
102 .  mat - the factored matrix
103 
104    Output Parameter:
105 +  pivot - the pivot value computed
106 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
107          the share the matrix
108 
109    Level: advanced
110 
111    Notes:
112     This routine does not work for factorizations done with external packages.
113    This routine should only be called if MatGetFactorError() returns a value of MAT_FACTOR_NUMERIC_ZEROPIVOT
114 
115    This can be called on non-factored matrices that come from, for example, matrices used in SOR.
116 
117 .seealso: MatZeroEntries(), MatFactor(), MatGetFactor(), MatFactorSymbolic(), MatFactorClearError(), MatFactorGetErrorZeroPivot()
118 @*/
119 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat,PetscReal *pivot,PetscInt *row)
120 {
121   PetscFunctionBegin;
122   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
123   *pivot = mat->factorerror_zeropivot_value;
124   *row   = mat->factorerror_zeropivot_row;
125   PetscFunctionReturn(0);
126 }
127 
128 /*@
129    MatFactorGetError - gets the error code from a factorization
130 
131    Logically Collective on Mat
132 
133    Input Parameters:
134 .  mat - the factored matrix
135 
136    Output Parameter:
137 .  err  - the error code
138 
139    Level: advanced
140 
141    Notes:
142     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
143 
144 .seealso: MatZeroEntries(), MatFactor(), MatGetFactor(), MatFactorSymbolic(), MatFactorClearError(), MatFactorGetErrorZeroPivot()
145 @*/
146 PetscErrorCode MatFactorGetError(Mat mat,MatFactorError *err)
147 {
148   PetscFunctionBegin;
149   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
150   *err = mat->factorerrortype;
151   PetscFunctionReturn(0);
152 }
153 
154 /*@
155    MatFactorClearError - clears the error code in a factorization
156 
157    Logically Collective on Mat
158 
159    Input Parameter:
160 .  mat - the factored matrix
161 
162    Level: developer
163 
164    Notes:
165     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
166 
167 .seealso: MatZeroEntries(), MatFactor(), MatGetFactor(), MatFactorSymbolic(), MatFactorGetError(), MatFactorGetErrorZeroPivot()
168 @*/
169 PetscErrorCode MatFactorClearError(Mat mat)
170 {
171   PetscFunctionBegin;
172   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
173   mat->factorerrortype             = MAT_FACTOR_NOERROR;
174   mat->factorerror_zeropivot_value = 0.0;
175   mat->factorerror_zeropivot_row   = 0;
176   PetscFunctionReturn(0);
177 }
178 
179 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat,PetscBool cols,PetscReal tol,IS *nonzero)
180 {
181   PetscErrorCode    ierr;
182   Vec               r,l;
183   const PetscScalar *al;
184   PetscInt          i,nz,gnz,N,n;
185 
186   PetscFunctionBegin;
187   ierr = MatCreateVecs(mat,&r,&l);CHKERRQ(ierr);
188   if (!cols) { /* nonzero rows */
189     ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
190     ierr = MatGetLocalSize(mat,&n,NULL);CHKERRQ(ierr);
191     ierr = VecSet(l,0.0);CHKERRQ(ierr);
192     ierr = VecSetRandom(r,NULL);CHKERRQ(ierr);
193     ierr = MatMult(mat,r,l);CHKERRQ(ierr);
194     ierr = VecGetArrayRead(l,&al);CHKERRQ(ierr);
195   } else { /* nonzero columns */
196     ierr = MatGetSize(mat,NULL,&N);CHKERRQ(ierr);
197     ierr = MatGetLocalSize(mat,NULL,&n);CHKERRQ(ierr);
198     ierr = VecSet(r,0.0);CHKERRQ(ierr);
199     ierr = VecSetRandom(l,NULL);CHKERRQ(ierr);
200     ierr = MatMultTranspose(mat,l,r);CHKERRQ(ierr);
201     ierr = VecGetArrayRead(r,&al);CHKERRQ(ierr);
202   }
203   if (tol <= 0.0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nz++; }
204   else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nz++; }
205   ierr = MPIU_Allreduce(&nz,&gnz,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
206   if (gnz != N) {
207     PetscInt *nzr;
208     ierr = PetscMalloc1(nz,&nzr);CHKERRQ(ierr);
209     if (nz) {
210       if (tol < 0) { for (i=0,nz=0;i<n;i++) if (al[i] != 0.0) nzr[nz++] = i; }
211       else { for (i=0,nz=0;i<n;i++) if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; }
212     }
213     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),nz,nzr,PETSC_OWN_POINTER,nonzero);CHKERRQ(ierr);
214   } else *nonzero = NULL;
215   if (!cols) { /* nonzero rows */
216     ierr = VecRestoreArrayRead(l,&al);CHKERRQ(ierr);
217   } else {
218     ierr = VecRestoreArrayRead(r,&al);CHKERRQ(ierr);
219   }
220   ierr = VecDestroy(&l);CHKERRQ(ierr);
221   ierr = VecDestroy(&r);CHKERRQ(ierr);
222   PetscFunctionReturn(0);
223 }
224 
225 /*@
226       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
227 
228   Input Parameter:
229 .    A  - the matrix
230 
231   Output Parameter:
232 .    keptrows - the rows that are not completely zero
233 
234   Notes:
235     keptrows is set to NULL if all rows are nonzero.
236 
237   Level: intermediate
238 
239  @*/
240 PetscErrorCode MatFindNonzeroRows(Mat mat,IS *keptrows)
241 {
242   PetscErrorCode ierr;
243 
244   PetscFunctionBegin;
245   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
246   PetscValidType(mat,1);
247   PetscValidPointer(keptrows,2);
248   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
249   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
250   if (!mat->ops->findnonzerorows) {
251     ierr = MatFindNonzeroRowsOrCols_Basic(mat,PETSC_FALSE,0.0,keptrows);CHKERRQ(ierr);
252   } else {
253     ierr = (*mat->ops->findnonzerorows)(mat,keptrows);CHKERRQ(ierr);
254   }
255   PetscFunctionReturn(0);
256 }
257 
258 /*@
259       MatFindZeroRows - Locate all rows that are completely zero in the matrix
260 
261   Input Parameter:
262 .    A  - the matrix
263 
264   Output Parameter:
265 .    zerorows - the rows that are completely zero
266 
267   Notes:
268     zerorows is set to NULL if no rows are zero.
269 
270   Level: intermediate
271 
272  @*/
273 PetscErrorCode MatFindZeroRows(Mat mat,IS *zerorows)
274 {
275   PetscErrorCode ierr;
276   IS keptrows;
277   PetscInt m, n;
278 
279   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
280   PetscValidType(mat,1);
281 
282   ierr = MatFindNonzeroRows(mat, &keptrows);CHKERRQ(ierr);
283   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
284      In keeping with this convention, we set zerorows to NULL if there are no zero
285      rows. */
286   if (keptrows == NULL) {
287     *zerorows = NULL;
288   } else {
289     ierr = MatGetOwnershipRange(mat,&m,&n);CHKERRQ(ierr);
290     ierr = ISComplement(keptrows,m,n,zerorows);CHKERRQ(ierr);
291     ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
292   }
293   PetscFunctionReturn(0);
294 }
295 
296 /*@
297    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
298 
299    Not Collective
300 
301    Input Parameters:
302 .   A - the matrix
303 
304    Output Parameters:
305 .   a - the diagonal part (which is a SEQUENTIAL matrix)
306 
307    Notes:
308     see the manual page for MatCreateAIJ() for more information on the "diagonal part" of the matrix.
309           Use caution, as the reference count on the returned matrix is not incremented and it is used as
310 	  part of the containing MPI Mat's normal operation.
311 
312    Level: advanced
313 
314 @*/
315 PetscErrorCode MatGetDiagonalBlock(Mat A,Mat *a)
316 {
317   PetscErrorCode ierr;
318 
319   PetscFunctionBegin;
320   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
321   PetscValidType(A,1);
322   PetscValidPointer(a,3);
323   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
324   if (!A->ops->getdiagonalblock) {
325     PetscMPIInt size;
326     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr);
327     if (size == 1) {
328       *a = A;
329       PetscFunctionReturn(0);
330     } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not coded for this matrix type");
331   }
332   ierr = (*A->ops->getdiagonalblock)(A,a);CHKERRQ(ierr);
333   PetscFunctionReturn(0);
334 }
335 
336 /*@
337    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
338 
339    Collective on Mat
340 
341    Input Parameters:
342 .  mat - the matrix
343 
344    Output Parameter:
345 .   trace - the sum of the diagonal entries
346 
347    Level: advanced
348 
349 @*/
350 PetscErrorCode MatGetTrace(Mat mat,PetscScalar *trace)
351 {
352   PetscErrorCode ierr;
353   Vec            diag;
354 
355   PetscFunctionBegin;
356   ierr = MatCreateVecs(mat,&diag,NULL);CHKERRQ(ierr);
357   ierr = MatGetDiagonal(mat,diag);CHKERRQ(ierr);
358   ierr = VecSum(diag,trace);CHKERRQ(ierr);
359   ierr = VecDestroy(&diag);CHKERRQ(ierr);
360   PetscFunctionReturn(0);
361 }
362 
363 /*@
364    MatRealPart - Zeros out the imaginary part of the matrix
365 
366    Logically Collective on Mat
367 
368    Input Parameters:
369 .  mat - the matrix
370 
371    Level: advanced
372 
373 
374 .seealso: MatImaginaryPart()
375 @*/
376 PetscErrorCode MatRealPart(Mat mat)
377 {
378   PetscErrorCode ierr;
379 
380   PetscFunctionBegin;
381   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
382   PetscValidType(mat,1);
383   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
384   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
385   if (!mat->ops->realpart) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
386   MatCheckPreallocated(mat,1);
387   ierr = (*mat->ops->realpart)(mat);CHKERRQ(ierr);
388 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
389   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
390     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
391   }
392 #endif
393   PetscFunctionReturn(0);
394 }
395 
396 /*@C
397    MatGetGhosts - Get the global index of all ghost nodes defined by the sparse matrix
398 
399    Collective on Mat
400 
401    Input Parameter:
402 .  mat - the matrix
403 
404    Output Parameters:
405 +   nghosts - number of ghosts (note for BAIJ matrices there is one ghost for each block)
406 -   ghosts - the global indices of the ghost points
407 
408    Notes:
409     the nghosts and ghosts are suitable to pass into VecCreateGhost()
410 
411    Level: advanced
412 
413 @*/
414 PetscErrorCode MatGetGhosts(Mat mat,PetscInt *nghosts,const PetscInt *ghosts[])
415 {
416   PetscErrorCode ierr;
417 
418   PetscFunctionBegin;
419   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
420   PetscValidType(mat,1);
421   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
422   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
423   if (!mat->ops->getghosts) {
424     if (nghosts) *nghosts = 0;
425     if (ghosts) *ghosts = 0;
426   } else {
427     ierr = (*mat->ops->getghosts)(mat,nghosts,ghosts);CHKERRQ(ierr);
428   }
429   PetscFunctionReturn(0);
430 }
431 
432 
433 /*@
434    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
435 
436    Logically Collective on Mat
437 
438    Input Parameters:
439 .  mat - the matrix
440 
441    Level: advanced
442 
443 
444 .seealso: MatRealPart()
445 @*/
446 PetscErrorCode MatImaginaryPart(Mat mat)
447 {
448   PetscErrorCode ierr;
449 
450   PetscFunctionBegin;
451   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
452   PetscValidType(mat,1);
453   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
454   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
455   if (!mat->ops->imaginarypart) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
456   MatCheckPreallocated(mat,1);
457   ierr = (*mat->ops->imaginarypart)(mat);CHKERRQ(ierr);
458 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
459   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
460     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
461   }
462 #endif
463   PetscFunctionReturn(0);
464 }
465 
466 /*@
467    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for BAIJ matrices)
468 
469    Not Collective
470 
471    Input Parameter:
472 .  mat - the matrix
473 
474    Output Parameters:
475 +  missing - is any diagonal missing
476 -  dd - first diagonal entry that is missing (optional) on this process
477 
478    Level: advanced
479 
480 
481 .seealso: MatRealPart()
482 @*/
483 PetscErrorCode MatMissingDiagonal(Mat mat,PetscBool *missing,PetscInt *dd)
484 {
485   PetscErrorCode ierr;
486 
487   PetscFunctionBegin;
488   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
489   PetscValidType(mat,1);
490   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
491   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
492   if (!mat->ops->missingdiagonal) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
493   ierr = (*mat->ops->missingdiagonal)(mat,missing,dd);CHKERRQ(ierr);
494   PetscFunctionReturn(0);
495 }
496 
497 /*@C
498    MatGetRow - Gets a row of a matrix.  You MUST call MatRestoreRow()
499    for each row that you get to ensure that your application does
500    not bleed memory.
501 
502    Not Collective
503 
504    Input Parameters:
505 +  mat - the matrix
506 -  row - the row to get
507 
508    Output Parameters:
509 +  ncols -  if not NULL, the number of nonzeros in the row
510 .  cols - if not NULL, the column numbers
511 -  vals - if not NULL, the values
512 
513    Notes:
514    This routine is provided for people who need to have direct access
515    to the structure of a matrix.  We hope that we provide enough
516    high-level matrix routines that few users will need it.
517 
518    MatGetRow() always returns 0-based column indices, regardless of
519    whether the internal representation is 0-based (default) or 1-based.
520 
521    For better efficiency, set cols and/or vals to NULL if you do
522    not wish to extract these quantities.
523 
524    The user can only examine the values extracted with MatGetRow();
525    the values cannot be altered.  To change the matrix entries, one
526    must use MatSetValues().
527 
528    You can only have one call to MatGetRow() outstanding for a particular
529    matrix at a time, per processor. MatGetRow() can only obtain rows
530    associated with the given processor, it cannot get rows from the
531    other processors; for that we suggest using MatCreateSubMatrices(), then
532    MatGetRow() on the submatrix. The row index passed to MatGetRows()
533    is in the global number of rows.
534 
535    Fortran Notes:
536    The calling sequence from Fortran is
537 .vb
538    MatGetRow(matrix,row,ncols,cols,values,ierr)
539          Mat     matrix (input)
540          integer row    (input)
541          integer ncols  (output)
542          integer cols(maxcols) (output)
543          double precision (or double complex) values(maxcols) output
544 .ve
545    where maxcols >= maximum nonzeros in any row of the matrix.
546 
547 
548    Caution:
549    Do not try to change the contents of the output arrays (cols and vals).
550    In some cases, this may corrupt the matrix.
551 
552    Level: advanced
553 
554    Concepts: matrices^row access
555 
556 .seealso: MatRestoreRow(), MatSetValues(), MatGetValues(), MatCreateSubMatrices(), MatGetDiagonal()
557 @*/
558 PetscErrorCode MatGetRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
559 {
560   PetscErrorCode ierr;
561   PetscInt       incols;
562 
563   PetscFunctionBegin;
564   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
565   PetscValidType(mat,1);
566   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
567   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
568   if (!mat->ops->getrow) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
569   MatCheckPreallocated(mat,1);
570   ierr = PetscLogEventBegin(MAT_GetRow,mat,0,0,0);CHKERRQ(ierr);
571   ierr = (*mat->ops->getrow)(mat,row,&incols,(PetscInt**)cols,(PetscScalar**)vals);CHKERRQ(ierr);
572   if (ncols) *ncols = incols;
573   ierr = PetscLogEventEnd(MAT_GetRow,mat,0,0,0);CHKERRQ(ierr);
574   PetscFunctionReturn(0);
575 }
576 
577 /*@
578    MatConjugate - replaces the matrix values with their complex conjugates
579 
580    Logically Collective on Mat
581 
582    Input Parameters:
583 .  mat - the matrix
584 
585    Level: advanced
586 
587 .seealso:  VecConjugate()
588 @*/
589 PetscErrorCode MatConjugate(Mat mat)
590 {
591 #if defined(PETSC_USE_COMPLEX)
592   PetscErrorCode ierr;
593 
594   PetscFunctionBegin;
595   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
596   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
597   if (!mat->ops->conjugate) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not provided for this matrix format, send email to petsc-maint@mcs.anl.gov");
598   ierr = (*mat->ops->conjugate)(mat);CHKERRQ(ierr);
599 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
600   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
601     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
602   }
603 #endif
604   PetscFunctionReturn(0);
605 #else
606   return 0;
607 #endif
608 }
609 
610 /*@C
611    MatRestoreRow - Frees any temporary space allocated by MatGetRow().
612 
613    Not Collective
614 
615    Input Parameters:
616 +  mat - the matrix
617 .  row - the row to get
618 .  ncols, cols - the number of nonzeros and their columns
619 -  vals - if nonzero the column values
620 
621    Notes:
622    This routine should be called after you have finished examining the entries.
623 
624    This routine zeros out ncols, cols, and vals. This is to prevent accidental
625    us of the array after it has been restored. If you pass NULL, it will
626    not zero the pointers.  Use of cols or vals after MatRestoreRow is invalid.
627 
628    Fortran Notes:
629    The calling sequence from Fortran is
630 .vb
631    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
632       Mat     matrix (input)
633       integer row    (input)
634       integer ncols  (output)
635       integer cols(maxcols) (output)
636       double precision (or double complex) values(maxcols) output
637 .ve
638    Where maxcols >= maximum nonzeros in any row of the matrix.
639 
640    In Fortran MatRestoreRow() MUST be called after MatGetRow()
641    before another call to MatGetRow() can be made.
642 
643    Level: advanced
644 
645 .seealso:  MatGetRow()
646 @*/
647 PetscErrorCode MatRestoreRow(Mat mat,PetscInt row,PetscInt *ncols,const PetscInt *cols[],const PetscScalar *vals[])
648 {
649   PetscErrorCode ierr;
650 
651   PetscFunctionBegin;
652   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
653   if (ncols) PetscValidIntPointer(ncols,3);
654   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
655   if (!mat->ops->restorerow) PetscFunctionReturn(0);
656   ierr = (*mat->ops->restorerow)(mat,row,ncols,(PetscInt **)cols,(PetscScalar **)vals);CHKERRQ(ierr);
657   if (ncols) *ncols = 0;
658   if (cols)  *cols = NULL;
659   if (vals)  *vals = NULL;
660   PetscFunctionReturn(0);
661 }
662 
663 /*@
664    MatGetRowUpperTriangular - Sets a flag to enable calls to MatGetRow() for matrix in MATSBAIJ format.
665    You should call MatRestoreRowUpperTriangular() after calling MatGetRow/MatRestoreRow() to disable the flag.
666 
667    Not Collective
668 
669    Input Parameters:
670 +  mat - the matrix
671 
672    Notes:
673    The flag is to ensure that users are aware of MatGetRow() only provides the upper trianglular part of the row for the matrices in MATSBAIJ format.
674 
675    Level: advanced
676 
677    Concepts: matrices^row access
678 
679 .seealso: MatRestoreRowRowUpperTriangular()
680 @*/
681 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
682 {
683   PetscErrorCode ierr;
684 
685   PetscFunctionBegin;
686   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
687   PetscValidType(mat,1);
688   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
689   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
690   if (!mat->ops->getrowuppertriangular) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
691   MatCheckPreallocated(mat,1);
692   ierr = (*mat->ops->getrowuppertriangular)(mat);CHKERRQ(ierr);
693   PetscFunctionReturn(0);
694 }
695 
696 /*@
697    MatRestoreRowUpperTriangular - Disable calls to MatGetRow() for matrix in MATSBAIJ format.
698 
699    Not Collective
700 
701    Input Parameters:
702 +  mat - the matrix
703 
704    Notes:
705    This routine should be called after you have finished MatGetRow/MatRestoreRow().
706 
707 
708    Level: advanced
709 
710 .seealso:  MatGetRowUpperTriangular()
711 @*/
712 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
713 {
714   PetscErrorCode ierr;
715 
716   PetscFunctionBegin;
717   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
718   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
719   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
720   ierr = (*mat->ops->restorerowuppertriangular)(mat);CHKERRQ(ierr);
721   PetscFunctionReturn(0);
722 }
723 
724 /*@C
725    MatSetOptionsPrefix - Sets the prefix used for searching for all
726    Mat options in the database.
727 
728    Logically Collective on Mat
729 
730    Input Parameter:
731 +  A - the Mat context
732 -  prefix - the prefix to prepend to all option names
733 
734    Notes:
735    A hyphen (-) must NOT be given at the beginning of the prefix name.
736    The first character of all runtime options is AUTOMATICALLY the hyphen.
737 
738    Level: advanced
739 
740 .keywords: Mat, set, options, prefix, database
741 
742 .seealso: MatSetFromOptions()
743 @*/
744 PetscErrorCode MatSetOptionsPrefix(Mat A,const char prefix[])
745 {
746   PetscErrorCode ierr;
747 
748   PetscFunctionBegin;
749   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
750   ierr = PetscObjectSetOptionsPrefix((PetscObject)A,prefix);CHKERRQ(ierr);
751   PetscFunctionReturn(0);
752 }
753 
754 /*@C
755    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
756    Mat options in the database.
757 
758    Logically Collective on Mat
759 
760    Input Parameters:
761 +  A - the Mat context
762 -  prefix - the prefix to prepend to all option names
763 
764    Notes:
765    A hyphen (-) must NOT be given at the beginning of the prefix name.
766    The first character of all runtime options is AUTOMATICALLY the hyphen.
767 
768    Level: advanced
769 
770 .keywords: Mat, append, options, prefix, database
771 
772 .seealso: MatGetOptionsPrefix()
773 @*/
774 PetscErrorCode MatAppendOptionsPrefix(Mat A,const char prefix[])
775 {
776   PetscErrorCode ierr;
777 
778   PetscFunctionBegin;
779   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
780   ierr = PetscObjectAppendOptionsPrefix((PetscObject)A,prefix);CHKERRQ(ierr);
781   PetscFunctionReturn(0);
782 }
783 
784 /*@C
785    MatGetOptionsPrefix - Sets the prefix used for searching for all
786    Mat options in the database.
787 
788    Not Collective
789 
790    Input Parameter:
791 .  A - the Mat context
792 
793    Output Parameter:
794 .  prefix - pointer to the prefix string used
795 
796    Notes:
797     On the fortran side, the user should pass in a string 'prefix' of
798    sufficient length to hold the prefix.
799 
800    Level: advanced
801 
802 .keywords: Mat, get, options, prefix, database
803 
804 .seealso: MatAppendOptionsPrefix()
805 @*/
806 PetscErrorCode MatGetOptionsPrefix(Mat A,const char *prefix[])
807 {
808   PetscErrorCode ierr;
809 
810   PetscFunctionBegin;
811   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
812   ierr = PetscObjectGetOptionsPrefix((PetscObject)A,prefix);CHKERRQ(ierr);
813   PetscFunctionReturn(0);
814 }
815 
816 /*@
817    MatResetPreallocation - Reset mat to use the original nonzero pattern provided by users.
818 
819    Collective on Mat
820 
821    Input Parameters:
822 .  A - the Mat context
823 
824    Notes:
825    The allocated memory will be shrunk after calling MatAssembly with MAT_FINAL_ASSEMBLY. Users can reset the preallocation to access the original memory.
826    Currently support MPIAIJ and SEQAIJ.
827 
828    Level: beginner
829 
830 .keywords: Mat, ResetPreallocation
831 
832 .seealso: MatSeqAIJSetPreallocation(), MatMPIAIJSetPreallocation(), MatXAIJSetPreallocation()
833 @*/
834 PetscErrorCode MatResetPreallocation(Mat A)
835 {
836   PetscErrorCode ierr;
837 
838   PetscFunctionBegin;
839   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
840   PetscValidType(A,1);
841   ierr = PetscUseMethod(A,"MatResetPreallocation_C",(Mat),(A));CHKERRQ(ierr);
842   PetscFunctionReturn(0);
843 }
844 
845 
846 /*@
847    MatSetUp - Sets up the internal matrix data structures for the later use.
848 
849    Collective on Mat
850 
851    Input Parameters:
852 .  A - the Mat context
853 
854    Notes:
855    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
856 
857    If a suitable preallocation routine is used, this function does not need to be called.
858 
859    See the Performance chapter of the PETSc users manual for how to preallocate matrices
860 
861    Level: beginner
862 
863 .keywords: Mat, setup
864 
865 .seealso: MatCreate(), MatDestroy()
866 @*/
867 PetscErrorCode MatSetUp(Mat A)
868 {
869   PetscMPIInt    size;
870   PetscErrorCode ierr;
871 
872   PetscFunctionBegin;
873   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
874   if (!((PetscObject)A)->type_name) {
875     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);CHKERRQ(ierr);
876     if (size == 1) {
877       ierr = MatSetType(A, MATSEQAIJ);CHKERRQ(ierr);
878     } else {
879       ierr = MatSetType(A, MATMPIAIJ);CHKERRQ(ierr);
880     }
881   }
882   if (!A->preallocated && A->ops->setup) {
883     ierr = PetscInfo(A,"Warning not preallocating matrix storage\n");CHKERRQ(ierr);
884     ierr = (*A->ops->setup)(A);CHKERRQ(ierr);
885   }
886   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
887   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
888   A->preallocated = PETSC_TRUE;
889   PetscFunctionReturn(0);
890 }
891 
892 #if defined(PETSC_HAVE_SAWS)
893 #include <petscviewersaws.h>
894 #endif
895 /*@C
896    MatView - Visualizes a matrix object.
897 
898    Collective on Mat
899 
900    Input Parameters:
901 +  mat - the matrix
902 -  viewer - visualization context
903 
904   Notes:
905   The available visualization contexts include
906 +    PETSC_VIEWER_STDOUT_SELF - for sequential matrices
907 .    PETSC_VIEWER_STDOUT_WORLD - for parallel matrices created on PETSC_COMM_WORLD
908 .    PETSC_VIEWER_STDOUT_(comm) - for matrices created on MPI communicator comm
909 -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
910 
911    The user can open alternative visualization contexts with
912 +    PetscViewerASCIIOpen() - Outputs matrix to a specified file
913 .    PetscViewerBinaryOpen() - Outputs matrix in binary to a
914          specified file; corresponding input uses MatLoad()
915 .    PetscViewerDrawOpen() - Outputs nonzero matrix structure to
916          an X window display
917 -    PetscViewerSocketOpen() - Outputs matrix to Socket viewer.
918          Currently only the sequential dense and AIJ
919          matrix types support the Socket viewer.
920 
921    The user can call PetscViewerPushFormat() to specify the output
922    format of ASCII printed objects (when using PETSC_VIEWER_STDOUT_SELF,
923    PETSC_VIEWER_STDOUT_WORLD and PetscViewerASCIIOpen).  Available formats include
924 +    PETSC_VIEWER_DEFAULT - default, prints matrix contents
925 .    PETSC_VIEWER_ASCII_MATLAB - prints matrix contents in Matlab format
926 .    PETSC_VIEWER_ASCII_DENSE - prints entire matrix including zeros
927 .    PETSC_VIEWER_ASCII_COMMON - prints matrix contents, using a sparse
928          format common among all matrix types
929 .    PETSC_VIEWER_ASCII_IMPL - prints matrix contents, using an implementation-specific
930          format (which is in many cases the same as the default)
931 .    PETSC_VIEWER_ASCII_INFO - prints basic information about the matrix
932          size and structure (not the matrix entries)
933 .    PETSC_VIEWER_ASCII_INFO_DETAIL - prints more detailed information about
934          the matrix structure
935 
936    Options Database Keys:
937 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatAssemblyEnd()
938 .  -mat_view ::ascii_info_detail - Prints more detailed info
939 .  -mat_view - Prints matrix in ASCII format
940 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
941 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
942 .  -display <name> - Sets display name (default is host)
943 .  -draw_pause <sec> - Sets number of seconds to pause after display
944 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
945 .  -viewer_socket_machine <machine> -
946 .  -viewer_socket_port <port> -
947 .  -mat_view binary - save matrix to file in binary format
948 -  -viewer_binary_filename <name> -
949    Level: beginner
950 
951    Notes:
952     see the manual page for MatLoad() for the exact format of the binary file when the binary
953       viewer is used.
954 
955       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
956       viewer is used.
957 
958       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure.
959       And then use the following mouse functions:
960           left mouse: zoom in
961           middle mouse: zoom out
962           right mouse: continue with the simulation
963 
964    Concepts: matrices^viewing
965    Concepts: matrices^plotting
966    Concepts: matrices^printing
967 
968 .seealso: PetscViewerPushFormat(), PetscViewerASCIIOpen(), PetscViewerDrawOpen(),
969           PetscViewerSocketOpen(), PetscViewerBinaryOpen(), MatLoad()
970 @*/
971 PetscErrorCode MatView(Mat mat,PetscViewer viewer)
972 {
973   PetscErrorCode    ierr;
974   PetscInt          rows,cols,rbs,cbs;
975   PetscBool         iascii,ibinary;
976   PetscViewerFormat format;
977   PetscMPIInt       size;
978 #if defined(PETSC_HAVE_SAWS)
979   PetscBool         issaws;
980 #endif
981 
982   PetscFunctionBegin;
983   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
984   PetscValidType(mat,1);
985   if (!viewer) {
986     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat),&viewer);CHKERRQ(ierr);
987   }
988   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
989   PetscCheckSameComm(mat,1,viewer,2);
990   MatCheckPreallocated(mat,1);
991   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
992   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
993   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
994   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
995   if (ibinary) {
996     PetscBool mpiio;
997     ierr = PetscViewerBinaryGetUseMPIIO(viewer,&mpiio);CHKERRQ(ierr);
998     if (mpiio) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"PETSc matrix viewers do not support using MPI-IO, turn off that flag");
999   }
1000 
1001   ierr = PetscLogEventBegin(MAT_View,mat,viewer,0,0);CHKERRQ(ierr);
1002   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1003   if ((!iascii || (format != PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) && mat->factortype) {
1004     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"No viewers for factored matrix except ASCII info or info_detailed");
1005   }
1006 
1007 #if defined(PETSC_HAVE_SAWS)
1008   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);CHKERRQ(ierr);
1009 #endif
1010   if (iascii) {
1011     if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Must call MatAssemblyBegin/End() before viewing matrix");
1012     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mat,viewer);CHKERRQ(ierr);
1013     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1014       MatNullSpace nullsp,transnullsp;
1015 
1016       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1017       ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1018       ierr = MatGetBlockSizes(mat,&rbs,&cbs);CHKERRQ(ierr);
1019       if (rbs != 1 || cbs != 1) {
1020         if (rbs != cbs) {ierr = PetscViewerASCIIPrintf(viewer,"rows=%D, cols=%D, rbs=%D, cbs = %D\n",rows,cols,rbs,cbs);CHKERRQ(ierr);}
1021         else            {ierr = PetscViewerASCIIPrintf(viewer,"rows=%D, cols=%D, bs=%D\n",rows,cols,rbs);CHKERRQ(ierr);}
1022       } else {
1023         ierr = PetscViewerASCIIPrintf(viewer,"rows=%D, cols=%D\n",rows,cols);CHKERRQ(ierr);
1024       }
1025       if (mat->factortype) {
1026         MatSolverType solver;
1027         ierr = MatFactorGetSolverType(mat,&solver);CHKERRQ(ierr);
1028         ierr = PetscViewerASCIIPrintf(viewer,"package used to perform factorization: %s\n",solver);CHKERRQ(ierr);
1029       }
1030       if (mat->ops->getinfo) {
1031         MatInfo info;
1032         ierr = MatGetInfo(mat,MAT_GLOBAL_SUM,&info);CHKERRQ(ierr);
1033         ierr = PetscViewerASCIIPrintf(viewer,"total: nonzeros=%.f, allocated nonzeros=%.f\n",info.nz_used,info.nz_allocated);CHKERRQ(ierr);
1034         ierr = PetscViewerASCIIPrintf(viewer,"total number of mallocs used during MatSetValues calls =%D\n",(PetscInt)info.mallocs);CHKERRQ(ierr);
1035       }
1036       ierr = MatGetNullSpace(mat,&nullsp);CHKERRQ(ierr);
1037       ierr = MatGetTransposeNullSpace(mat,&transnullsp);CHKERRQ(ierr);
1038       if (nullsp) {ierr = PetscViewerASCIIPrintf(viewer,"  has attached null space\n");CHKERRQ(ierr);}
1039       if (transnullsp && transnullsp != nullsp) {ierr = PetscViewerASCIIPrintf(viewer,"  has attached transposed null space\n");CHKERRQ(ierr);}
1040       ierr = MatGetNearNullSpace(mat,&nullsp);CHKERRQ(ierr);
1041       if (nullsp) {ierr = PetscViewerASCIIPrintf(viewer,"  has attached near null space\n");CHKERRQ(ierr);}
1042     }
1043 #if defined(PETSC_HAVE_SAWS)
1044   } else if (issaws) {
1045     PetscMPIInt rank;
1046 
1047     ierr = PetscObjectName((PetscObject)mat);CHKERRQ(ierr);
1048     ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
1049     if (!((PetscObject)mat)->amsmem && !rank) {
1050       ierr = PetscObjectViewSAWs((PetscObject)mat,viewer);CHKERRQ(ierr);
1051     }
1052 #endif
1053   }
1054   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1055     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1056     ierr = (*mat->ops->viewnative)(mat,viewer);CHKERRQ(ierr);
1057     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1058   } else if (mat->ops->view) {
1059     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1060     ierr = (*mat->ops->view)(mat,viewer);CHKERRQ(ierr);
1061     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1062   }
1063   if (iascii) {
1064     if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Must call MatAssemblyBegin/End() before viewing matrix");
1065     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1066     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1067       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1068     }
1069   }
1070   ierr = PetscLogEventEnd(MAT_View,mat,viewer,0,0);CHKERRQ(ierr);
1071   PetscFunctionReturn(0);
1072 }
1073 
1074 #if defined(PETSC_USE_DEBUG)
1075 #include <../src/sys/totalview/tv_data_display.h>
1076 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1077 {
1078   TV_add_row("Local rows", "int", &mat->rmap->n);
1079   TV_add_row("Local columns", "int", &mat->cmap->n);
1080   TV_add_row("Global rows", "int", &mat->rmap->N);
1081   TV_add_row("Global columns", "int", &mat->cmap->N);
1082   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1083   return TV_format_OK;
1084 }
1085 #endif
1086 
1087 /*@C
1088    MatLoad - Loads a matrix that has been stored in binary format
1089    with MatView().  The matrix format is determined from the options database.
1090    Generates a parallel MPI matrix if the communicator has more than one
1091    processor.  The default matrix type is AIJ.
1092 
1093    Collective on PetscViewer
1094 
1095    Input Parameters:
1096 +  newmat - the newly loaded matrix, this needs to have been created with MatCreate()
1097             or some related function before a call to MatLoad()
1098 -  viewer - binary file viewer, created with PetscViewerBinaryOpen()
1099 
1100    Options Database Keys:
1101    Used with block matrix formats (MATSEQBAIJ,  ...) to specify
1102    block size
1103 .    -matload_block_size <bs>
1104 
1105    Level: beginner
1106 
1107    Notes:
1108    If the Mat type has not yet been given then MATAIJ is used, call MatSetFromOptions() on the
1109    Mat before calling this routine if you wish to set it from the options database.
1110 
1111    MatLoad() automatically loads into the options database any options
1112    given in the file filename.info where filename is the name of the file
1113    that was passed to the PetscViewerBinaryOpen(). The options in the info
1114    file will be ignored if you use the -viewer_binary_skip_info option.
1115 
1116    If the type or size of newmat is not set before a call to MatLoad, PETSc
1117    sets the default matrix type AIJ and sets the local and global sizes.
1118    If type and/or size is already set, then the same are used.
1119 
1120    In parallel, each processor can load a subset of rows (or the
1121    entire matrix).  This routine is especially useful when a large
1122    matrix is stored on disk and only part of it is desired on each
1123    processor.  For example, a parallel solver may access only some of
1124    the rows from each processor.  The algorithm used here reads
1125    relatively small blocks of data rather than reading the entire
1126    matrix and then subsetting it.
1127 
1128    Notes for advanced users:
1129    Most users should not need to know the details of the binary storage
1130    format, since MatLoad() and MatView() completely hide these details.
1131    But for anyone who's interested, the standard binary matrix storage
1132    format is
1133 
1134 $    int    MAT_FILE_CLASSID
1135 $    int    number of rows
1136 $    int    number of columns
1137 $    int    total number of nonzeros
1138 $    int    *number nonzeros in each row
1139 $    int    *column indices of all nonzeros (starting index is zero)
1140 $    PetscScalar *values of all nonzeros
1141 
1142    PETSc automatically does the byte swapping for
1143 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1144 linux, Windows and the paragon; thus if you write your own binary
1145 read/write routines you have to swap the bytes; see PetscBinaryRead()
1146 and PetscBinaryWrite() to see how this may be done.
1147 
1148 .keywords: matrix, load, binary, input
1149 
1150 .seealso: PetscViewerBinaryOpen(), MatView(), VecLoad()
1151 
1152  @*/
1153 PetscErrorCode MatLoad(Mat newmat,PetscViewer viewer)
1154 {
1155   PetscErrorCode ierr;
1156   PetscBool      isbinary,flg;
1157 
1158   PetscFunctionBegin;
1159   PetscValidHeaderSpecific(newmat,MAT_CLASSID,1);
1160   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1161   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1162   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
1163 
1164   if (!((PetscObject)newmat)->type_name) {
1165     ierr = MatSetType(newmat,MATAIJ);CHKERRQ(ierr);
1166   }
1167 
1168   if (!newmat->ops->load) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatLoad is not supported for type");
1169   ierr = PetscLogEventBegin(MAT_Load,viewer,0,0,0);CHKERRQ(ierr);
1170   ierr = (*newmat->ops->load)(newmat,viewer);CHKERRQ(ierr);
1171   ierr = PetscLogEventEnd(MAT_Load,viewer,0,0,0);CHKERRQ(ierr);
1172 
1173   flg  = PETSC_FALSE;
1174   ierr = PetscOptionsGetBool(((PetscObject)newmat)->options,((PetscObject)newmat)->prefix,"-matload_symmetric",&flg,NULL);CHKERRQ(ierr);
1175   if (flg) {
1176     ierr = MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
1177     ierr = MatSetOption(newmat,MAT_SYMMETRY_ETERNAL,PETSC_TRUE);CHKERRQ(ierr);
1178   }
1179   flg  = PETSC_FALSE;
1180   ierr = PetscOptionsGetBool(((PetscObject)newmat)->options,((PetscObject)newmat)->prefix,"-matload_spd",&flg,NULL);CHKERRQ(ierr);
1181   if (flg) {
1182     ierr = MatSetOption(newmat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
1183   }
1184   PetscFunctionReturn(0);
1185 }
1186 
1187 PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1188 {
1189   PetscErrorCode ierr;
1190   Mat_Redundant  *redund = *redundant;
1191   PetscInt       i;
1192 
1193   PetscFunctionBegin;
1194   if (redund){
1195     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1196       ierr = ISDestroy(&redund->isrow);CHKERRQ(ierr);
1197       ierr = ISDestroy(&redund->iscol);CHKERRQ(ierr);
1198       ierr = MatDestroySubMatrices(1,&redund->matseq);CHKERRQ(ierr);
1199     } else {
1200       ierr = PetscFree2(redund->send_rank,redund->recv_rank);CHKERRQ(ierr);
1201       ierr = PetscFree(redund->sbuf_j);CHKERRQ(ierr);
1202       ierr = PetscFree(redund->sbuf_a);CHKERRQ(ierr);
1203       for (i=0; i<redund->nrecvs; i++) {
1204         ierr = PetscFree(redund->rbuf_j[i]);CHKERRQ(ierr);
1205         ierr = PetscFree(redund->rbuf_a[i]);CHKERRQ(ierr);
1206       }
1207       ierr = PetscFree4(redund->sbuf_nz,redund->rbuf_nz,redund->rbuf_j,redund->rbuf_a);CHKERRQ(ierr);
1208     }
1209 
1210     if (redund->subcomm) {
1211       ierr = PetscCommDestroy(&redund->subcomm);CHKERRQ(ierr);
1212     }
1213     ierr = PetscFree(redund);CHKERRQ(ierr);
1214   }
1215   PetscFunctionReturn(0);
1216 }
1217 
1218 /*@
1219    MatDestroy - Frees space taken by a matrix.
1220 
1221    Collective on Mat
1222 
1223    Input Parameter:
1224 .  A - the matrix
1225 
1226    Level: beginner
1227 
1228 @*/
1229 PetscErrorCode MatDestroy(Mat *A)
1230 {
1231   PetscErrorCode ierr;
1232 
1233   PetscFunctionBegin;
1234   if (!*A) PetscFunctionReturn(0);
1235   PetscValidHeaderSpecific(*A,MAT_CLASSID,1);
1236   if (--((PetscObject)(*A))->refct > 0) {*A = NULL; PetscFunctionReturn(0);}
1237 
1238   /* if memory was published with SAWs then destroy it */
1239   ierr = PetscObjectSAWsViewOff((PetscObject)*A);CHKERRQ(ierr);
1240   if ((*A)->ops->destroy) {
1241     ierr = (*(*A)->ops->destroy)(*A);CHKERRQ(ierr);
1242   }
1243 
1244   ierr = PetscFree((*A)->solvertype);CHKERRQ(ierr);
1245   ierr = MatDestroy_Redundant(&(*A)->redundant);CHKERRQ(ierr);
1246   ierr = MatNullSpaceDestroy(&(*A)->nullsp);CHKERRQ(ierr);
1247   ierr = MatNullSpaceDestroy(&(*A)->transnullsp);CHKERRQ(ierr);
1248   ierr = MatNullSpaceDestroy(&(*A)->nearnullsp);CHKERRQ(ierr);
1249   ierr = MatDestroy(&(*A)->schur);CHKERRQ(ierr);
1250   ierr = PetscLayoutDestroy(&(*A)->rmap);CHKERRQ(ierr);
1251   ierr = PetscLayoutDestroy(&(*A)->cmap);CHKERRQ(ierr);
1252   ierr = PetscHeaderDestroy(A);CHKERRQ(ierr);
1253   PetscFunctionReturn(0);
1254 }
1255 
1256 /*@C
1257    MatSetValues - Inserts or adds a block of values into a matrix.
1258    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
1259    MUST be called after all calls to MatSetValues() have been completed.
1260 
1261    Not Collective
1262 
1263    Input Parameters:
1264 +  mat - the matrix
1265 .  v - a logically two-dimensional array of values
1266 .  m, idxm - the number of rows and their global indices
1267 .  n, idxn - the number of columns and their global indices
1268 -  addv - either ADD_VALUES or INSERT_VALUES, where
1269    ADD_VALUES adds values to any existing entries, and
1270    INSERT_VALUES replaces existing entries with new values
1271 
1272    Notes:
1273    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
1274       MatSetUp() before using this routine
1275 
1276    By default the values, v, are row-oriented. See MatSetOption() for other options.
1277 
1278    Calls to MatSetValues() with the INSERT_VALUES and ADD_VALUES
1279    options cannot be mixed without intervening calls to the assembly
1280    routines.
1281 
1282    MatSetValues() uses 0-based row and column numbers in Fortran
1283    as well as in C.
1284 
1285    Negative indices may be passed in idxm and idxn, these rows and columns are
1286    simply ignored. This allows easily inserting element stiffness matrices
1287    with homogeneous Dirchlet boundary conditions that you don't want represented
1288    in the matrix.
1289 
1290    Efficiency Alert:
1291    The routine MatSetValuesBlocked() may offer much better efficiency
1292    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1293 
1294    Level: beginner
1295 
1296    Developer Notes:
1297     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1298                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1299 
1300    Concepts: matrices^putting entries in
1301 
1302 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal(),
1303           InsertMode, INSERT_VALUES, ADD_VALUES
1304 @*/
1305 PetscErrorCode MatSetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1306 {
1307   PetscErrorCode ierr;
1308 #if defined(PETSC_USE_DEBUG)
1309   PetscInt       i,j;
1310 #endif
1311 
1312   PetscFunctionBeginHot;
1313   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1314   PetscValidType(mat,1);
1315   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1316   PetscValidIntPointer(idxm,3);
1317   PetscValidIntPointer(idxn,5);
1318   PetscValidScalarPointer(v,6);
1319   MatCheckPreallocated(mat,1);
1320   if (mat->insertmode == NOT_SET_VALUES) {
1321     mat->insertmode = addv;
1322   }
1323 #if defined(PETSC_USE_DEBUG)
1324   else if (mat->insertmode != addv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1325   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1326   if (!mat->ops->setvalues) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1327 
1328   for (i=0; i<m; i++) {
1329     for (j=0; j<n; j++) {
1330       if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i*n+j]))
1331 #if defined(PETSC_USE_COMPLEX)
1332         SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FP,"Inserting %g+ig at matrix entry (%D,%D)",(double)PetscRealPart(v[i*n+j]),(double)PetscImaginaryPart(v[i*n+j]),idxm[i],idxn[j]);
1333 #else
1334         SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_FP,"Inserting %g at matrix entry (%D,%D)",(double)v[i*n+j],idxm[i],idxn[j]);
1335 #endif
1336     }
1337   }
1338 #endif
1339 
1340   if (mat->assembled) {
1341     mat->was_assembled = PETSC_TRUE;
1342     mat->assembled     = PETSC_FALSE;
1343   }
1344   ierr = PetscLogEventBegin(MAT_SetValues,mat,0,0,0);CHKERRQ(ierr);
1345   ierr = (*mat->ops->setvalues)(mat,m,idxm,n,idxn,v,addv);CHKERRQ(ierr);
1346   ierr = PetscLogEventEnd(MAT_SetValues,mat,0,0,0);CHKERRQ(ierr);
1347 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
1348   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
1349     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
1350   }
1351 #endif
1352   PetscFunctionReturn(0);
1353 }
1354 
1355 
1356 /*@
1357    MatSetValuesRowLocal - Inserts a row (block row for BAIJ matrices) of nonzero
1358         values into a matrix
1359 
1360    Not Collective
1361 
1362    Input Parameters:
1363 +  mat - the matrix
1364 .  row - the (block) row to set
1365 -  v - a logically two-dimensional array of values
1366 
1367    Notes:
1368    By the values, v, are column-oriented (for the block version) and sorted
1369 
1370    All the nonzeros in the row must be provided
1371 
1372    The matrix must have previously had its column indices set
1373 
1374    The row must belong to this process
1375 
1376    Level: intermediate
1377 
1378    Concepts: matrices^putting entries in
1379 
1380 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal(),
1381           InsertMode, INSERT_VALUES, ADD_VALUES, MatSetValues(), MatSetValuesRow(), MatSetLocalToGlobalMapping()
1382 @*/
1383 PetscErrorCode MatSetValuesRowLocal(Mat mat,PetscInt row,const PetscScalar v[])
1384 {
1385   PetscErrorCode ierr;
1386   PetscInt       globalrow;
1387 
1388   PetscFunctionBegin;
1389   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1390   PetscValidType(mat,1);
1391   PetscValidScalarPointer(v,2);
1392   ierr = ISLocalToGlobalMappingApply(mat->rmap->mapping,1,&row,&globalrow);CHKERRQ(ierr);
1393   ierr = MatSetValuesRow(mat,globalrow,v);CHKERRQ(ierr);
1394 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
1395   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
1396     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
1397   }
1398 #endif
1399   PetscFunctionReturn(0);
1400 }
1401 
1402 /*@
1403    MatSetValuesRow - Inserts a row (block row for BAIJ matrices) of nonzero
1404         values into a matrix
1405 
1406    Not Collective
1407 
1408    Input Parameters:
1409 +  mat - the matrix
1410 .  row - the (block) row to set
1411 -  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
1412 
1413    Notes:
1414    The values, v, are column-oriented for the block version.
1415 
1416    All the nonzeros in the row must be provided
1417 
1418    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually MatSetValues() is used.
1419 
1420    The row must belong to this process
1421 
1422    Level: advanced
1423 
1424    Concepts: matrices^putting entries in
1425 
1426 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal(),
1427           InsertMode, INSERT_VALUES, ADD_VALUES, MatSetValues()
1428 @*/
1429 PetscErrorCode MatSetValuesRow(Mat mat,PetscInt row,const PetscScalar v[])
1430 {
1431   PetscErrorCode ierr;
1432 
1433   PetscFunctionBeginHot;
1434   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1435   PetscValidType(mat,1);
1436   MatCheckPreallocated(mat,1);
1437   PetscValidScalarPointer(v,2);
1438 #if defined(PETSC_USE_DEBUG)
1439   if (mat->insertmode == ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add and insert values");
1440   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1441 #endif
1442   mat->insertmode = INSERT_VALUES;
1443 
1444   if (mat->assembled) {
1445     mat->was_assembled = PETSC_TRUE;
1446     mat->assembled     = PETSC_FALSE;
1447   }
1448   ierr = PetscLogEventBegin(MAT_SetValues,mat,0,0,0);CHKERRQ(ierr);
1449   if (!mat->ops->setvaluesrow) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1450   ierr = (*mat->ops->setvaluesrow)(mat,row,v);CHKERRQ(ierr);
1451   ierr = PetscLogEventEnd(MAT_SetValues,mat,0,0,0);CHKERRQ(ierr);
1452 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
1453   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
1454     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
1455   }
1456 #endif
1457   PetscFunctionReturn(0);
1458 }
1459 
1460 /*@
1461    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1462      Using structured grid indexing
1463 
1464    Not Collective
1465 
1466    Input Parameters:
1467 +  mat - the matrix
1468 .  m - number of rows being entered
1469 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1470 .  n - number of columns being entered
1471 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1472 .  v - a logically two-dimensional array of values
1473 -  addv - either ADD_VALUES or INSERT_VALUES, where
1474    ADD_VALUES adds values to any existing entries, and
1475    INSERT_VALUES replaces existing entries with new values
1476 
1477    Notes:
1478    By default the values, v, are row-oriented.  See MatSetOption() for other options.
1479 
1480    Calls to MatSetValuesStencil() with the INSERT_VALUES and ADD_VALUES
1481    options cannot be mixed without intervening calls to the assembly
1482    routines.
1483 
1484    The grid coordinates are across the entire grid, not just the local portion
1485 
1486    MatSetValuesStencil() uses 0-based row and column numbers in Fortran
1487    as well as in C.
1488 
1489    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1490 
1491    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1492    or call MatSetLocalToGlobalMapping() and MatSetStencil() first.
1493 
1494    The columns and rows in the stencil passed in MUST be contained within the
1495    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1496    if you create a DMDA with an overlap of one grid level and on a particular process its first
1497    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1498    first i index you can use in your column and row indices in MatSetStencil() is 5.
1499 
1500    In Fortran idxm and idxn should be declared as
1501 $     MatStencil idxm(4,m),idxn(4,n)
1502    and the values inserted using
1503 $    idxm(MatStencil_i,1) = i
1504 $    idxm(MatStencil_j,1) = j
1505 $    idxm(MatStencil_k,1) = k
1506 $    idxm(MatStencil_c,1) = c
1507    etc
1508 
1509    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1510    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1511    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1512    DM_BOUNDARY_PERIODIC boundary type.
1513 
1514    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
1515    a single value per point) you can skip filling those indices.
1516 
1517    Inspired by the structured grid interface to the HYPRE package
1518    (http://www.llnl.gov/CASC/hypre)
1519 
1520    Efficiency Alert:
1521    The routine MatSetValuesBlockedStencil() may offer much better efficiency
1522    for users of block sparse formats (MATSEQBAIJ and MATMPIBAIJ).
1523 
1524    Level: beginner
1525 
1526    Concepts: matrices^putting entries in
1527 
1528 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal()
1529           MatSetValues(), MatSetValuesBlockedStencil(), MatSetStencil(), DMCreateMatrix(), DMDAVecGetArray(), MatStencil
1530 @*/
1531 PetscErrorCode MatSetValuesStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1532 {
1533   PetscErrorCode ierr;
1534   PetscInt       buf[8192],*bufm=0,*bufn=0,*jdxm,*jdxn;
1535   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1536   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1537 
1538   PetscFunctionBegin;
1539   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1540   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1541   PetscValidType(mat,1);
1542   PetscValidIntPointer(idxm,3);
1543   PetscValidIntPointer(idxn,5);
1544   PetscValidScalarPointer(v,6);
1545 
1546   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1547     jdxm = buf; jdxn = buf+m;
1548   } else {
1549     ierr = PetscMalloc2(m,&bufm,n,&bufn);CHKERRQ(ierr);
1550     jdxm = bufm; jdxn = bufn;
1551   }
1552   for (i=0; i<m; i++) {
1553     for (j=0; j<3-sdim; j++) dxm++;
1554     tmp = *dxm++ - starts[0];
1555     for (j=0; j<dim-1; j++) {
1556       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1557       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1558     }
1559     if (mat->stencil.noc) dxm++;
1560     jdxm[i] = tmp;
1561   }
1562   for (i=0; i<n; i++) {
1563     for (j=0; j<3-sdim; j++) dxn++;
1564     tmp = *dxn++ - starts[0];
1565     for (j=0; j<dim-1; j++) {
1566       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1567       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1568     }
1569     if (mat->stencil.noc) dxn++;
1570     jdxn[i] = tmp;
1571   }
1572   ierr = MatSetValuesLocal(mat,m,jdxm,n,jdxn,v,addv);CHKERRQ(ierr);
1573   ierr = PetscFree2(bufm,bufn);CHKERRQ(ierr);
1574   PetscFunctionReturn(0);
1575 }
1576 
1577 /*@
1578    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1579      Using structured grid indexing
1580 
1581    Not Collective
1582 
1583    Input Parameters:
1584 +  mat - the matrix
1585 .  m - number of rows being entered
1586 .  idxm - grid coordinates for matrix rows being entered
1587 .  n - number of columns being entered
1588 .  idxn - grid coordinates for matrix columns being entered
1589 .  v - a logically two-dimensional array of values
1590 -  addv - either ADD_VALUES or INSERT_VALUES, where
1591    ADD_VALUES adds values to any existing entries, and
1592    INSERT_VALUES replaces existing entries with new values
1593 
1594    Notes:
1595    By default the values, v, are row-oriented and unsorted.
1596    See MatSetOption() for other options.
1597 
1598    Calls to MatSetValuesBlockedStencil() with the INSERT_VALUES and ADD_VALUES
1599    options cannot be mixed without intervening calls to the assembly
1600    routines.
1601 
1602    The grid coordinates are across the entire grid, not just the local portion
1603 
1604    MatSetValuesBlockedStencil() uses 0-based row and column numbers in Fortran
1605    as well as in C.
1606 
1607    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1608 
1609    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1610    or call MatSetBlockSize(), MatSetLocalToGlobalMapping() and MatSetStencil() first.
1611 
1612    The columns and rows in the stencil passed in MUST be contained within the
1613    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1614    if you create a DMDA with an overlap of one grid level and on a particular process its first
1615    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1616    first i index you can use in your column and row indices in MatSetStencil() is 5.
1617 
1618    In Fortran idxm and idxn should be declared as
1619 $     MatStencil idxm(4,m),idxn(4,n)
1620    and the values inserted using
1621 $    idxm(MatStencil_i,1) = i
1622 $    idxm(MatStencil_j,1) = j
1623 $    idxm(MatStencil_k,1) = k
1624    etc
1625 
1626    Negative indices may be passed in idxm and idxn, these rows and columns are
1627    simply ignored. This allows easily inserting element stiffness matrices
1628    with homogeneous Dirchlet boundary conditions that you don't want represented
1629    in the matrix.
1630 
1631    Inspired by the structured grid interface to the HYPRE package
1632    (http://www.llnl.gov/CASC/hypre)
1633 
1634    Level: beginner
1635 
1636    Concepts: matrices^putting entries in
1637 
1638 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal()
1639           MatSetValues(), MatSetValuesStencil(), MatSetStencil(), DMCreateMatrix(), DMDAVecGetArray(), MatStencil,
1640           MatSetBlockSize(), MatSetLocalToGlobalMapping()
1641 @*/
1642 PetscErrorCode MatSetValuesBlockedStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)
1643 {
1644   PetscErrorCode ierr;
1645   PetscInt       buf[8192],*bufm=0,*bufn=0,*jdxm,*jdxn;
1646   PetscInt       j,i,dim = mat->stencil.dim,*dims = mat->stencil.dims+1,tmp;
1647   PetscInt       *starts = mat->stencil.starts,*dxm = (PetscInt*)idxm,*dxn = (PetscInt*)idxn,sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1648 
1649   PetscFunctionBegin;
1650   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1651   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1652   PetscValidType(mat,1);
1653   PetscValidIntPointer(idxm,3);
1654   PetscValidIntPointer(idxn,5);
1655   PetscValidScalarPointer(v,6);
1656 
1657   if ((m+n) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1658     jdxm = buf; jdxn = buf+m;
1659   } else {
1660     ierr = PetscMalloc2(m,&bufm,n,&bufn);CHKERRQ(ierr);
1661     jdxm = bufm; jdxn = bufn;
1662   }
1663   for (i=0; i<m; i++) {
1664     for (j=0; j<3-sdim; j++) dxm++;
1665     tmp = *dxm++ - starts[0];
1666     for (j=0; j<sdim-1; j++) {
1667       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1668       else                                       tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
1669     }
1670     dxm++;
1671     jdxm[i] = tmp;
1672   }
1673   for (i=0; i<n; i++) {
1674     for (j=0; j<3-sdim; j++) dxn++;
1675     tmp = *dxn++ - starts[0];
1676     for (j=0; j<sdim-1; j++) {
1677       if ((*dxn++ - starts[j+1]) < 0 || tmp < 0) tmp = -1;
1678       else                                       tmp = tmp*dims[j] + *(dxn-1) - starts[j+1];
1679     }
1680     dxn++;
1681     jdxn[i] = tmp;
1682   }
1683   ierr = MatSetValuesBlockedLocal(mat,m,jdxm,n,jdxn,v,addv);CHKERRQ(ierr);
1684   ierr = PetscFree2(bufm,bufn);CHKERRQ(ierr);
1685 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
1686   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
1687     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
1688   }
1689 #endif
1690   PetscFunctionReturn(0);
1691 }
1692 
1693 /*@
1694    MatSetStencil - Sets the grid information for setting values into a matrix via
1695         MatSetValuesStencil()
1696 
1697    Not Collective
1698 
1699    Input Parameters:
1700 +  mat - the matrix
1701 .  dim - dimension of the grid 1, 2, or 3
1702 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1703 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1704 -  dof - number of degrees of freedom per node
1705 
1706 
1707    Inspired by the structured grid interface to the HYPRE package
1708    (www.llnl.gov/CASC/hyper)
1709 
1710    For matrices generated with DMCreateMatrix() this routine is automatically called and so not needed by the
1711    user.
1712 
1713    Level: beginner
1714 
1715    Concepts: matrices^putting entries in
1716 
1717 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal()
1718           MatSetValues(), MatSetValuesBlockedStencil(), MatSetValuesStencil()
1719 @*/
1720 PetscErrorCode MatSetStencil(Mat mat,PetscInt dim,const PetscInt dims[],const PetscInt starts[],PetscInt dof)
1721 {
1722   PetscInt i;
1723 
1724   PetscFunctionBegin;
1725   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1726   PetscValidIntPointer(dims,3);
1727   PetscValidIntPointer(starts,4);
1728 
1729   mat->stencil.dim = dim + (dof > 1);
1730   for (i=0; i<dim; i++) {
1731     mat->stencil.dims[i]   = dims[dim-i-1];      /* copy the values in backwards */
1732     mat->stencil.starts[i] = starts[dim-i-1];
1733   }
1734   mat->stencil.dims[dim]   = dof;
1735   mat->stencil.starts[dim] = 0;
1736   mat->stencil.noc         = (PetscBool)(dof == 1);
1737   PetscFunctionReturn(0);
1738 }
1739 
1740 /*@C
1741    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1742 
1743    Not Collective
1744 
1745    Input Parameters:
1746 +  mat - the matrix
1747 .  v - a logically two-dimensional array of values
1748 .  m, idxm - the number of block rows and their global block indices
1749 .  n, idxn - the number of block columns and their global block indices
1750 -  addv - either ADD_VALUES or INSERT_VALUES, where
1751    ADD_VALUES adds values to any existing entries, and
1752    INSERT_VALUES replaces existing entries with new values
1753 
1754    Notes:
1755    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call
1756    MatXXXXSetPreallocation() or MatSetUp() before using this routine.
1757 
1758    The m and n count the NUMBER of blocks in the row direction and column direction,
1759    NOT the total number of rows/columns; for example, if the block size is 2 and
1760    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1761    The values in idxm would be 1 2; that is the first index for each block divided by
1762    the block size.
1763 
1764    Note that you must call MatSetBlockSize() when constructing this matrix (before
1765    preallocating it).
1766 
1767    By default the values, v, are row-oriented, so the layout of
1768    v is the same as for MatSetValues(). See MatSetOption() for other options.
1769 
1770    Calls to MatSetValuesBlocked() with the INSERT_VALUES and ADD_VALUES
1771    options cannot be mixed without intervening calls to the assembly
1772    routines.
1773 
1774    MatSetValuesBlocked() uses 0-based row and column numbers in Fortran
1775    as well as in C.
1776 
1777    Negative indices may be passed in idxm and idxn, these rows and columns are
1778    simply ignored. This allows easily inserting element stiffness matrices
1779    with homogeneous Dirchlet boundary conditions that you don't want represented
1780    in the matrix.
1781 
1782    Each time an entry is set within a sparse matrix via MatSetValues(),
1783    internal searching must be done to determine where to place the
1784    data in the matrix storage space.  By instead inserting blocks of
1785    entries via MatSetValuesBlocked(), the overhead of matrix assembly is
1786    reduced.
1787 
1788    Example:
1789 $   Suppose m=n=2 and block size(bs) = 2 The array is
1790 $
1791 $   1  2  | 3  4
1792 $   5  6  | 7  8
1793 $   - - - | - - -
1794 $   9  10 | 11 12
1795 $   13 14 | 15 16
1796 $
1797 $   v[] should be passed in like
1798 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1799 $
1800 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1801 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1802 
1803    Level: intermediate
1804 
1805    Concepts: matrices^putting entries in blocked
1806 
1807 .seealso: MatSetBlockSize(), MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValues(), MatSetValuesBlockedLocal()
1808 @*/
1809 PetscErrorCode MatSetValuesBlocked(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1810 {
1811   PetscErrorCode ierr;
1812 
1813   PetscFunctionBeginHot;
1814   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1815   PetscValidType(mat,1);
1816   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1817   PetscValidIntPointer(idxm,3);
1818   PetscValidIntPointer(idxn,5);
1819   PetscValidScalarPointer(v,6);
1820   MatCheckPreallocated(mat,1);
1821   if (mat->insertmode == NOT_SET_VALUES) {
1822     mat->insertmode = addv;
1823   }
1824 #if defined(PETSC_USE_DEBUG)
1825   else if (mat->insertmode != addv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
1826   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1827   if (!mat->ops->setvaluesblocked && !mat->ops->setvalues) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1828 #endif
1829 
1830   if (mat->assembled) {
1831     mat->was_assembled = PETSC_TRUE;
1832     mat->assembled     = PETSC_FALSE;
1833   }
1834   ierr = PetscLogEventBegin(MAT_SetValues,mat,0,0,0);CHKERRQ(ierr);
1835   if (mat->ops->setvaluesblocked) {
1836     ierr = (*mat->ops->setvaluesblocked)(mat,m,idxm,n,idxn,v,addv);CHKERRQ(ierr);
1837   } else {
1838     PetscInt buf[8192],*bufr=0,*bufc=0,*iidxm,*iidxn;
1839     PetscInt i,j,bs,cbs;
1840     ierr = MatGetBlockSizes(mat,&bs,&cbs);CHKERRQ(ierr);
1841     if (m*bs+n*cbs <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
1842       iidxm = buf; iidxn = buf + m*bs;
1843     } else {
1844       ierr  = PetscMalloc2(m*bs,&bufr,n*cbs,&bufc);CHKERRQ(ierr);
1845       iidxm = bufr; iidxn = bufc;
1846     }
1847     for (i=0; i<m; i++) {
1848       for (j=0; j<bs; j++) {
1849         iidxm[i*bs+j] = bs*idxm[i] + j;
1850       }
1851     }
1852     for (i=0; i<n; i++) {
1853       for (j=0; j<cbs; j++) {
1854         iidxn[i*cbs+j] = cbs*idxn[i] + j;
1855       }
1856     }
1857     ierr = MatSetValues(mat,m*bs,iidxm,n*cbs,iidxn,v,addv);CHKERRQ(ierr);
1858     ierr = PetscFree2(bufr,bufc);CHKERRQ(ierr);
1859   }
1860   ierr = PetscLogEventEnd(MAT_SetValues,mat,0,0,0);CHKERRQ(ierr);
1861 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
1862   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
1863     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
1864   }
1865 #endif
1866   PetscFunctionReturn(0);
1867 }
1868 
1869 /*@
1870    MatGetValues - Gets a block of values from a matrix.
1871 
1872    Not Collective; currently only returns a local block
1873 
1874    Input Parameters:
1875 +  mat - the matrix
1876 .  v - a logically two-dimensional array for storing the values
1877 .  m, idxm - the number of rows and their global indices
1878 -  n, idxn - the number of columns and their global indices
1879 
1880    Notes:
1881    The user must allocate space (m*n PetscScalars) for the values, v.
1882    The values, v, are then returned in a row-oriented format,
1883    analogous to that used by default in MatSetValues().
1884 
1885    MatGetValues() uses 0-based row and column numbers in
1886    Fortran as well as in C.
1887 
1888    MatGetValues() requires that the matrix has been assembled
1889    with MatAssemblyBegin()/MatAssemblyEnd().  Thus, calls to
1890    MatSetValues() and MatGetValues() CANNOT be made in succession
1891    without intermediate matrix assembly.
1892 
1893    Negative row or column indices will be ignored and those locations in v[] will be
1894    left unchanged.
1895 
1896    Level: advanced
1897 
1898    Concepts: matrices^accessing values
1899 
1900 .seealso: MatGetRow(), MatCreateSubMatrices(), MatSetValues()
1901 @*/
1902 PetscErrorCode MatGetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
1903 {
1904   PetscErrorCode ierr;
1905 
1906   PetscFunctionBegin;
1907   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1908   PetscValidType(mat,1);
1909   if (!m || !n) PetscFunctionReturn(0);
1910   PetscValidIntPointer(idxm,3);
1911   PetscValidIntPointer(idxn,5);
1912   PetscValidScalarPointer(v,6);
1913   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
1914   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1915   if (!mat->ops->getvalues) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
1916   MatCheckPreallocated(mat,1);
1917 
1918   ierr = PetscLogEventBegin(MAT_GetValues,mat,0,0,0);CHKERRQ(ierr);
1919   ierr = (*mat->ops->getvalues)(mat,m,idxm,n,idxn,v);CHKERRQ(ierr);
1920   ierr = PetscLogEventEnd(MAT_GetValues,mat,0,0,0);CHKERRQ(ierr);
1921   PetscFunctionReturn(0);
1922 }
1923 
1924 /*@
1925   MatSetValuesBatch - Adds (ADD_VALUES) many blocks of values into a matrix at once. The blocks must all be square and
1926   the same size. Currently, this can only be called once and creates the given matrix.
1927 
1928   Not Collective
1929 
1930   Input Parameters:
1931 + mat - the matrix
1932 . nb - the number of blocks
1933 . bs - the number of rows (and columns) in each block
1934 . rows - a concatenation of the rows for each block
1935 - v - a concatenation of logically two-dimensional arrays of values
1936 
1937   Notes:
1938   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
1939 
1940   Level: advanced
1941 
1942   Concepts: matrices^putting entries in
1943 
1944 .seealso: MatSetOption(), MatAssemblyBegin(), MatAssemblyEnd(), MatSetValuesBlocked(), MatSetValuesLocal(),
1945           InsertMode, INSERT_VALUES, ADD_VALUES, MatSetValues()
1946 @*/
1947 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
1948 {
1949   PetscErrorCode ierr;
1950 
1951   PetscFunctionBegin;
1952   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1953   PetscValidType(mat,1);
1954   PetscValidScalarPointer(rows,4);
1955   PetscValidScalarPointer(v,5);
1956 #if defined(PETSC_USE_DEBUG)
1957   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1958 #endif
1959 
1960   ierr = PetscLogEventBegin(MAT_SetValuesBatch,mat,0,0,0);CHKERRQ(ierr);
1961   if (mat->ops->setvaluesbatch) {
1962     ierr = (*mat->ops->setvaluesbatch)(mat,nb,bs,rows,v);CHKERRQ(ierr);
1963   } else {
1964     PetscInt b;
1965     for (b = 0; b < nb; ++b) {
1966       ierr = MatSetValues(mat, bs, &rows[b*bs], bs, &rows[b*bs], &v[b*bs*bs], ADD_VALUES);CHKERRQ(ierr);
1967     }
1968   }
1969   ierr = PetscLogEventEnd(MAT_SetValuesBatch,mat,0,0,0);CHKERRQ(ierr);
1970   PetscFunctionReturn(0);
1971 }
1972 
1973 /*@
1974    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
1975    the routine MatSetValuesLocal() to allow users to insert matrix entries
1976    using a local (per-processor) numbering.
1977 
1978    Not Collective
1979 
1980    Input Parameters:
1981 +  x - the matrix
1982 .  rmapping - row mapping created with ISLocalToGlobalMappingCreate()   or ISLocalToGlobalMappingCreateIS()
1983 - cmapping - column mapping
1984 
1985    Level: intermediate
1986 
1987    Concepts: matrices^local to global mapping
1988    Concepts: local to global mapping^for matrices
1989 
1990 .seealso:  MatAssemblyBegin(), MatAssemblyEnd(), MatSetValues(), MatSetValuesLocal()
1991 @*/
1992 PetscErrorCode MatSetLocalToGlobalMapping(Mat x,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1993 {
1994   PetscErrorCode ierr;
1995 
1996   PetscFunctionBegin;
1997   PetscValidHeaderSpecific(x,MAT_CLASSID,1);
1998   PetscValidType(x,1);
1999   PetscValidHeaderSpecific(rmapping,IS_LTOGM_CLASSID,2);
2000   PetscValidHeaderSpecific(cmapping,IS_LTOGM_CLASSID,3);
2001 
2002   if (x->ops->setlocaltoglobalmapping) {
2003     ierr = (*x->ops->setlocaltoglobalmapping)(x,rmapping,cmapping);CHKERRQ(ierr);
2004   } else {
2005     ierr = PetscLayoutSetISLocalToGlobalMapping(x->rmap,rmapping);CHKERRQ(ierr);
2006     ierr = PetscLayoutSetISLocalToGlobalMapping(x->cmap,cmapping);CHKERRQ(ierr);
2007   }
2008   PetscFunctionReturn(0);
2009 }
2010 
2011 
2012 /*@
2013    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by MatSetLocalToGlobalMapping()
2014 
2015    Not Collective
2016 
2017    Input Parameters:
2018 .  A - the matrix
2019 
2020    Output Parameters:
2021 + rmapping - row mapping
2022 - cmapping - column mapping
2023 
2024    Level: advanced
2025 
2026    Concepts: matrices^local to global mapping
2027    Concepts: local to global mapping^for matrices
2028 
2029 .seealso:  MatSetValuesLocal()
2030 @*/
2031 PetscErrorCode MatGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping)
2032 {
2033   PetscFunctionBegin;
2034   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2035   PetscValidType(A,1);
2036   if (rmapping) PetscValidPointer(rmapping,2);
2037   if (cmapping) PetscValidPointer(cmapping,3);
2038   if (rmapping) *rmapping = A->rmap->mapping;
2039   if (cmapping) *cmapping = A->cmap->mapping;
2040   PetscFunctionReturn(0);
2041 }
2042 
2043 /*@
2044    MatGetLayouts - Gets the PetscLayout objects for rows and columns
2045 
2046    Not Collective
2047 
2048    Input Parameters:
2049 .  A - the matrix
2050 
2051    Output Parameters:
2052 + rmap - row layout
2053 - cmap - column layout
2054 
2055    Level: advanced
2056 
2057 .seealso:  MatCreateVecs(), MatGetLocalToGlobalMapping()
2058 @*/
2059 PetscErrorCode MatGetLayouts(Mat A,PetscLayout *rmap,PetscLayout *cmap)
2060 {
2061   PetscFunctionBegin;
2062   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2063   PetscValidType(A,1);
2064   if (rmap) PetscValidPointer(rmap,2);
2065   if (cmap) PetscValidPointer(cmap,3);
2066   if (rmap) *rmap = A->rmap;
2067   if (cmap) *cmap = A->cmap;
2068   PetscFunctionReturn(0);
2069 }
2070 
2071 /*@C
2072    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2073    using a local ordering of the nodes.
2074 
2075    Not Collective
2076 
2077    Input Parameters:
2078 +  mat - the matrix
2079 .  nrow, irow - number of rows and their local indices
2080 .  ncol, icol - number of columns and their local indices
2081 .  y -  a logically two-dimensional array of values
2082 -  addv - either INSERT_VALUES or ADD_VALUES, where
2083    ADD_VALUES adds values to any existing entries, and
2084    INSERT_VALUES replaces existing entries with new values
2085 
2086    Notes:
2087    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2088       MatSetUp() before using this routine
2089 
2090    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine
2091 
2092    Calls to MatSetValuesLocal() with the INSERT_VALUES and ADD_VALUES
2093    options cannot be mixed without intervening calls to the assembly
2094    routines.
2095 
2096    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2097    MUST be called after all calls to MatSetValuesLocal() have been completed.
2098 
2099    Level: intermediate
2100 
2101    Concepts: matrices^putting entries in with local numbering
2102 
2103    Developer Notes:
2104     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2105                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2106 
2107 .seealso:  MatAssemblyBegin(), MatAssemblyEnd(), MatSetValues(), MatSetLocalToGlobalMapping(),
2108            MatSetValueLocal()
2109 @*/
2110 PetscErrorCode MatSetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2111 {
2112   PetscErrorCode ierr;
2113 
2114   PetscFunctionBeginHot;
2115   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2116   PetscValidType(mat,1);
2117   MatCheckPreallocated(mat,1);
2118   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2119   PetscValidIntPointer(irow,3);
2120   PetscValidIntPointer(icol,5);
2121   PetscValidScalarPointer(y,6);
2122   if (mat->insertmode == NOT_SET_VALUES) {
2123     mat->insertmode = addv;
2124   }
2125 #if defined(PETSC_USE_DEBUG)
2126   else if (mat->insertmode != addv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2127   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2128   if (!mat->ops->setvalueslocal && !mat->ops->setvalues) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2129 #endif
2130 
2131   if (mat->assembled) {
2132     mat->was_assembled = PETSC_TRUE;
2133     mat->assembled     = PETSC_FALSE;
2134   }
2135   ierr = PetscLogEventBegin(MAT_SetValues,mat,0,0,0);CHKERRQ(ierr);
2136   if (mat->ops->setvalueslocal) {
2137     ierr = (*mat->ops->setvalueslocal)(mat,nrow,irow,ncol,icol,y,addv);CHKERRQ(ierr);
2138   } else {
2139     PetscInt buf[8192],*bufr=0,*bufc=0,*irowm,*icolm;
2140     if ((nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2141       irowm = buf; icolm = buf+nrow;
2142     } else {
2143       ierr  = PetscMalloc2(nrow,&bufr,ncol,&bufc);CHKERRQ(ierr);
2144       irowm = bufr; icolm = bufc;
2145     }
2146     ierr = ISLocalToGlobalMappingApply(mat->rmap->mapping,nrow,irow,irowm);CHKERRQ(ierr);
2147     ierr = ISLocalToGlobalMappingApply(mat->cmap->mapping,ncol,icol,icolm);CHKERRQ(ierr);
2148     ierr = MatSetValues(mat,nrow,irowm,ncol,icolm,y,addv);CHKERRQ(ierr);
2149     ierr = PetscFree2(bufr,bufc);CHKERRQ(ierr);
2150   }
2151   ierr = PetscLogEventEnd(MAT_SetValues,mat,0,0,0);CHKERRQ(ierr);
2152 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
2153   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
2154     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
2155   }
2156 #endif
2157   PetscFunctionReturn(0);
2158 }
2159 
2160 /*@C
2161    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2162    using a local ordering of the nodes a block at a time.
2163 
2164    Not Collective
2165 
2166    Input Parameters:
2167 +  x - the matrix
2168 .  nrow, irow - number of rows and their local indices
2169 .  ncol, icol - number of columns and their local indices
2170 .  y -  a logically two-dimensional array of values
2171 -  addv - either INSERT_VALUES or ADD_VALUES, where
2172    ADD_VALUES adds values to any existing entries, and
2173    INSERT_VALUES replaces existing entries with new values
2174 
2175    Notes:
2176    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2177       MatSetUp() before using this routine
2178 
2179    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetBlockSize() and MatSetLocalToGlobalMapping()
2180       before using this routineBefore calling MatSetValuesLocal(), the user must first set the
2181 
2182    Calls to MatSetValuesBlockedLocal() with the INSERT_VALUES and ADD_VALUES
2183    options cannot be mixed without intervening calls to the assembly
2184    routines.
2185 
2186    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2187    MUST be called after all calls to MatSetValuesBlockedLocal() have been completed.
2188 
2189    Level: intermediate
2190 
2191    Developer Notes:
2192     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2193                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2194 
2195    Concepts: matrices^putting blocked values in with local numbering
2196 
2197 .seealso:  MatSetBlockSize(), MatSetLocalToGlobalMapping(), MatAssemblyBegin(), MatAssemblyEnd(),
2198            MatSetValuesLocal(),  MatSetValuesBlocked()
2199 @*/
2200 PetscErrorCode MatSetValuesBlockedLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
2201 {
2202   PetscErrorCode ierr;
2203 
2204   PetscFunctionBeginHot;
2205   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2206   PetscValidType(mat,1);
2207   MatCheckPreallocated(mat,1);
2208   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2209   PetscValidIntPointer(irow,3);
2210   PetscValidIntPointer(icol,5);
2211   PetscValidScalarPointer(y,6);
2212   if (mat->insertmode == NOT_SET_VALUES) {
2213     mat->insertmode = addv;
2214   }
2215 #if defined(PETSC_USE_DEBUG)
2216   else if (mat->insertmode != addv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
2217   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2218   if (!mat->ops->setvaluesblockedlocal && !mat->ops->setvaluesblocked && !mat->ops->setvalueslocal && !mat->ops->setvalues) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2219 #endif
2220 
2221   if (mat->assembled) {
2222     mat->was_assembled = PETSC_TRUE;
2223     mat->assembled     = PETSC_FALSE;
2224   }
2225   ierr = PetscLogEventBegin(MAT_SetValues,mat,0,0,0);CHKERRQ(ierr);
2226   if (mat->ops->setvaluesblockedlocal) {
2227     ierr = (*mat->ops->setvaluesblockedlocal)(mat,nrow,irow,ncol,icol,y,addv);CHKERRQ(ierr);
2228   } else {
2229     PetscInt buf[8192],*bufr=0,*bufc=0,*irowm,*icolm;
2230     if ((nrow+ncol) <= (PetscInt)(sizeof(buf)/sizeof(PetscInt))) {
2231       irowm = buf; icolm = buf + nrow;
2232     } else {
2233       ierr  = PetscMalloc2(nrow,&bufr,ncol,&bufc);CHKERRQ(ierr);
2234       irowm = bufr; icolm = bufc;
2235     }
2236     ierr = ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping,nrow,irow,irowm);CHKERRQ(ierr);
2237     ierr = ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping,ncol,icol,icolm);CHKERRQ(ierr);
2238     ierr = MatSetValuesBlocked(mat,nrow,irowm,ncol,icolm,y,addv);CHKERRQ(ierr);
2239     ierr = PetscFree2(bufr,bufc);CHKERRQ(ierr);
2240   }
2241   ierr = PetscLogEventEnd(MAT_SetValues,mat,0,0,0);CHKERRQ(ierr);
2242 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
2243   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
2244     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
2245   }
2246 #endif
2247   PetscFunctionReturn(0);
2248 }
2249 
2250 /*@
2251    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2252 
2253    Collective on Mat and Vec
2254 
2255    Input Parameters:
2256 +  mat - the matrix
2257 -  x   - the vector to be multiplied
2258 
2259    Output Parameters:
2260 .  y - the result
2261 
2262    Notes:
2263    The vectors x and y cannot be the same.  I.e., one cannot
2264    call MatMult(A,y,y).
2265 
2266    Level: developer
2267 
2268    Concepts: matrix-vector product
2269 
2270 .seealso: MatMultTranspose(), MatMultAdd(), MatMultTransposeAdd()
2271 @*/
2272 PetscErrorCode MatMultDiagonalBlock(Mat mat,Vec x,Vec y)
2273 {
2274   PetscErrorCode ierr;
2275 
2276   PetscFunctionBegin;
2277   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2278   PetscValidType(mat,1);
2279   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2280   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2281 
2282   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2283   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2284   if (x == y) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2285   MatCheckPreallocated(mat,1);
2286 
2287   if (!mat->ops->multdiagonalblock) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"This matrix type does not have a multiply defined");
2288   ierr = (*mat->ops->multdiagonalblock)(mat,x,y);CHKERRQ(ierr);
2289   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
2290   PetscFunctionReturn(0);
2291 }
2292 
2293 /* --------------------------------------------------------*/
2294 /*@
2295    MatMult - Computes the matrix-vector product, y = Ax.
2296 
2297    Neighbor-wise Collective on Mat and Vec
2298 
2299    Input Parameters:
2300 +  mat - the matrix
2301 -  x   - the vector to be multiplied
2302 
2303    Output Parameters:
2304 .  y - the result
2305 
2306    Notes:
2307    The vectors x and y cannot be the same.  I.e., one cannot
2308    call MatMult(A,y,y).
2309 
2310    Level: beginner
2311 
2312    Concepts: matrix-vector product
2313 
2314 .seealso: MatMultTranspose(), MatMultAdd(), MatMultTransposeAdd()
2315 @*/
2316 PetscErrorCode MatMult(Mat mat,Vec x,Vec y)
2317 {
2318   PetscErrorCode ierr;
2319 
2320   PetscFunctionBegin;
2321   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2322   PetscValidType(mat,1);
2323   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2324   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2325   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2326   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2327   if (x == y) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2328 #if !defined(PETSC_HAVE_CONSTRAINTS)
2329   if (mat->cmap->N != x->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->cmap->N,x->map->N);
2330   if (mat->rmap->N != y->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %D %D",mat->rmap->N,y->map->N);
2331   if (mat->rmap->n != y->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %D %D",mat->rmap->n,y->map->n);
2332 #endif
2333   VecLocked(y,3);
2334   if (mat->erroriffailure) {ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr);}
2335   MatCheckPreallocated(mat,1);
2336 
2337   ierr = VecLockPush(x);CHKERRQ(ierr);
2338   if (!mat->ops->mult) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"This matrix type does not have a multiply defined");
2339   ierr = PetscLogEventBegin(MAT_Mult,mat,x,y,0);CHKERRQ(ierr);
2340   ierr = (*mat->ops->mult)(mat,x,y);CHKERRQ(ierr);
2341   ierr = PetscLogEventEnd(MAT_Mult,mat,x,y,0);CHKERRQ(ierr);
2342   if (mat->erroriffailure) {ierr = VecValidValues(y,3,PETSC_FALSE);CHKERRQ(ierr);}
2343   ierr = VecLockPop(x);CHKERRQ(ierr);
2344   PetscFunctionReturn(0);
2345 }
2346 
2347 /*@
2348    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2349 
2350    Neighbor-wise Collective on Mat and Vec
2351 
2352    Input Parameters:
2353 +  mat - the matrix
2354 -  x   - the vector to be multiplied
2355 
2356    Output Parameters:
2357 .  y - the result
2358 
2359    Notes:
2360    The vectors x and y cannot be the same.  I.e., one cannot
2361    call MatMultTranspose(A,y,y).
2362 
2363    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2364    use MatMultHermitianTranspose()
2365 
2366    Level: beginner
2367 
2368    Concepts: matrix vector product^transpose
2369 
2370 .seealso: MatMult(), MatMultAdd(), MatMultTransposeAdd(), MatMultHermitianTranspose(), MatTranspose()
2371 @*/
2372 PetscErrorCode MatMultTranspose(Mat mat,Vec x,Vec y)
2373 {
2374   PetscErrorCode ierr;
2375 
2376   PetscFunctionBegin;
2377   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2378   PetscValidType(mat,1);
2379   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2380   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2381 
2382   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2383   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2384   if (x == y) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2385 #if !defined(PETSC_HAVE_CONSTRAINTS)
2386   if (mat->rmap->N != x->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->rmap->N,x->map->N);
2387   if (mat->cmap->N != y->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %D %D",mat->cmap->N,y->map->N);
2388 #endif
2389   if (mat->erroriffailure) {ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr);}
2390   MatCheckPreallocated(mat,1);
2391 
2392   if (!mat->ops->multtranspose) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"This matrix type does not have a multiply transpose defined");
2393   ierr = PetscLogEventBegin(MAT_MultTranspose,mat,x,y,0);CHKERRQ(ierr);
2394   ierr = VecLockPush(x);CHKERRQ(ierr);
2395   ierr = (*mat->ops->multtranspose)(mat,x,y);CHKERRQ(ierr);
2396   ierr = VecLockPop(x);CHKERRQ(ierr);
2397   ierr = PetscLogEventEnd(MAT_MultTranspose,mat,x,y,0);CHKERRQ(ierr);
2398   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
2399   if (mat->erroriffailure) {ierr = VecValidValues(y,3,PETSC_FALSE);CHKERRQ(ierr);}
2400   PetscFunctionReturn(0);
2401 }
2402 
2403 /*@
2404    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2405 
2406    Neighbor-wise Collective on Mat and Vec
2407 
2408    Input Parameters:
2409 +  mat - the matrix
2410 -  x   - the vector to be multilplied
2411 
2412    Output Parameters:
2413 .  y - the result
2414 
2415    Notes:
2416    The vectors x and y cannot be the same.  I.e., one cannot
2417    call MatMultHermitianTranspose(A,y,y).
2418 
2419    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2420 
2421    For real numbers MatMultTranspose() and MatMultHermitianTranspose() are identical.
2422 
2423    Level: beginner
2424 
2425    Concepts: matrix vector product^transpose
2426 
2427 .seealso: MatMult(), MatMultAdd(), MatMultHermitianTransposeAdd(), MatMultTranspose()
2428 @*/
2429 PetscErrorCode MatMultHermitianTranspose(Mat mat,Vec x,Vec y)
2430 {
2431   PetscErrorCode ierr;
2432   Vec            w;
2433 
2434   PetscFunctionBegin;
2435   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2436   PetscValidType(mat,1);
2437   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2438   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2439 
2440   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2441   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2442   if (x == y) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2443 #if !defined(PETSC_HAVE_CONSTRAINTS)
2444   if (mat->rmap->N != x->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->rmap->N,x->map->N);
2445   if (mat->cmap->N != y->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %D %D",mat->cmap->N,y->map->N);
2446 #endif
2447   MatCheckPreallocated(mat,1);
2448 
2449   ierr = PetscLogEventBegin(MAT_MultHermitianTranspose,mat,x,y,0);CHKERRQ(ierr);
2450   if (mat->ops->multhermitiantranspose) {
2451     ierr = VecLockPush(x);CHKERRQ(ierr);
2452     ierr = (*mat->ops->multhermitiantranspose)(mat,x,y);CHKERRQ(ierr);
2453     ierr = VecLockPop(x);CHKERRQ(ierr);
2454   } else {
2455     ierr = VecDuplicate(x,&w);CHKERRQ(ierr);
2456     ierr = VecCopy(x,w);CHKERRQ(ierr);
2457     ierr = VecConjugate(w);CHKERRQ(ierr);
2458     ierr = MatMultTranspose(mat,w,y);CHKERRQ(ierr);
2459     ierr = VecDestroy(&w);CHKERRQ(ierr);
2460     ierr = VecConjugate(y);CHKERRQ(ierr);
2461   }
2462   ierr = PetscLogEventEnd(MAT_MultHermitianTranspose,mat,x,y,0);CHKERRQ(ierr);
2463   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
2464   PetscFunctionReturn(0);
2465 }
2466 
2467 /*@
2468     MatMultAdd -  Computes v3 = v2 + A * v1.
2469 
2470     Neighbor-wise Collective on Mat and Vec
2471 
2472     Input Parameters:
2473 +   mat - the matrix
2474 -   v1, v2 - the vectors
2475 
2476     Output Parameters:
2477 .   v3 - the result
2478 
2479     Notes:
2480     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2481     call MatMultAdd(A,v1,v2,v1).
2482 
2483     Level: beginner
2484 
2485     Concepts: matrix vector product^addition
2486 
2487 .seealso: MatMultTranspose(), MatMult(), MatMultTransposeAdd()
2488 @*/
2489 PetscErrorCode MatMultAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2490 {
2491   PetscErrorCode ierr;
2492 
2493   PetscFunctionBegin;
2494   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2495   PetscValidType(mat,1);
2496   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2497   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2498   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2499 
2500   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2501   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2502   if (mat->cmap->N != v1->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %D %D",mat->cmap->N,v1->map->N);
2503   /* if (mat->rmap->N != v2->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %D %D",mat->rmap->N,v2->map->N);
2504      if (mat->rmap->N != v3->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %D %D",mat->rmap->N,v3->map->N); */
2505   if (mat->rmap->n != v3->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: local dim %D %D",mat->rmap->n,v3->map->n);
2506   if (mat->rmap->n != v2->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: local dim %D %D",mat->rmap->n,v2->map->n);
2507   if (v1 == v3) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2508   MatCheckPreallocated(mat,1);
2509 
2510   if (!mat->ops->multadd) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No MatMultAdd() for matrix type '%s'",((PetscObject)mat)->type_name);
2511   ierr = PetscLogEventBegin(MAT_MultAdd,mat,v1,v2,v3);CHKERRQ(ierr);
2512   ierr = VecLockPush(v1);CHKERRQ(ierr);
2513   ierr = (*mat->ops->multadd)(mat,v1,v2,v3);CHKERRQ(ierr);
2514   ierr = VecLockPop(v1);CHKERRQ(ierr);
2515   ierr = PetscLogEventEnd(MAT_MultAdd,mat,v1,v2,v3);CHKERRQ(ierr);
2516   ierr = PetscObjectStateIncrease((PetscObject)v3);CHKERRQ(ierr);
2517   PetscFunctionReturn(0);
2518 }
2519 
2520 /*@
2521    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2522 
2523    Neighbor-wise Collective on Mat and Vec
2524 
2525    Input Parameters:
2526 +  mat - the matrix
2527 -  v1, v2 - the vectors
2528 
2529    Output Parameters:
2530 .  v3 - the result
2531 
2532    Notes:
2533    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2534    call MatMultTransposeAdd(A,v1,v2,v1).
2535 
2536    Level: beginner
2537 
2538    Concepts: matrix vector product^transpose and addition
2539 
2540 .seealso: MatMultTranspose(), MatMultAdd(), MatMult()
2541 @*/
2542 PetscErrorCode MatMultTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2543 {
2544   PetscErrorCode ierr;
2545 
2546   PetscFunctionBegin;
2547   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2548   PetscValidType(mat,1);
2549   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2550   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2551   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2552 
2553   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2554   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2555   if (!mat->ops->multtransposeadd) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2556   if (v1 == v3) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2557   if (mat->rmap->N != v1->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %D %D",mat->rmap->N,v1->map->N);
2558   if (mat->cmap->N != v2->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %D %D",mat->cmap->N,v2->map->N);
2559   if (mat->cmap->N != v3->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %D %D",mat->cmap->N,v3->map->N);
2560   MatCheckPreallocated(mat,1);
2561 
2562   ierr = PetscLogEventBegin(MAT_MultTransposeAdd,mat,v1,v2,v3);CHKERRQ(ierr);
2563   ierr = VecLockPush(v1);CHKERRQ(ierr);
2564   ierr = (*mat->ops->multtransposeadd)(mat,v1,v2,v3);CHKERRQ(ierr);
2565   ierr = VecLockPop(v1);CHKERRQ(ierr);
2566   ierr = PetscLogEventEnd(MAT_MultTransposeAdd,mat,v1,v2,v3);CHKERRQ(ierr);
2567   ierr = PetscObjectStateIncrease((PetscObject)v3);CHKERRQ(ierr);
2568   PetscFunctionReturn(0);
2569 }
2570 
2571 /*@
2572    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2573 
2574    Neighbor-wise Collective on Mat and Vec
2575 
2576    Input Parameters:
2577 +  mat - the matrix
2578 -  v1, v2 - the vectors
2579 
2580    Output Parameters:
2581 .  v3 - the result
2582 
2583    Notes:
2584    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2585    call MatMultHermitianTransposeAdd(A,v1,v2,v1).
2586 
2587    Level: beginner
2588 
2589    Concepts: matrix vector product^transpose and addition
2590 
2591 .seealso: MatMultHermitianTranspose(), MatMultTranspose(), MatMultAdd(), MatMult()
2592 @*/
2593 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)
2594 {
2595   PetscErrorCode ierr;
2596 
2597   PetscFunctionBegin;
2598   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2599   PetscValidType(mat,1);
2600   PetscValidHeaderSpecific(v1,VEC_CLASSID,2);
2601   PetscValidHeaderSpecific(v2,VEC_CLASSID,3);
2602   PetscValidHeaderSpecific(v3,VEC_CLASSID,4);
2603 
2604   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2605   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2606   if (v1 == v3) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"v1 and v3 must be different vectors");
2607   if (mat->rmap->N != v1->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v1: global dim %D %D",mat->rmap->N,v1->map->N);
2608   if (mat->cmap->N != v2->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %D %D",mat->cmap->N,v2->map->N);
2609   if (mat->cmap->N != v3->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %D %D",mat->cmap->N,v3->map->N);
2610   MatCheckPreallocated(mat,1);
2611 
2612   ierr = PetscLogEventBegin(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3);CHKERRQ(ierr);
2613   ierr = VecLockPush(v1);CHKERRQ(ierr);
2614   if (mat->ops->multhermitiantransposeadd) {
2615     ierr = (*mat->ops->multhermitiantransposeadd)(mat,v1,v2,v3);CHKERRQ(ierr);
2616    } else {
2617     Vec w,z;
2618     ierr = VecDuplicate(v1,&w);CHKERRQ(ierr);
2619     ierr = VecCopy(v1,w);CHKERRQ(ierr);
2620     ierr = VecConjugate(w);CHKERRQ(ierr);
2621     ierr = VecDuplicate(v3,&z);CHKERRQ(ierr);
2622     ierr = MatMultTranspose(mat,w,z);CHKERRQ(ierr);
2623     ierr = VecDestroy(&w);CHKERRQ(ierr);
2624     ierr = VecConjugate(z);CHKERRQ(ierr);
2625     ierr = VecWAXPY(v3,1.0,v2,z);CHKERRQ(ierr);
2626     ierr = VecDestroy(&z);CHKERRQ(ierr);
2627   }
2628   ierr = VecLockPop(v1);CHKERRQ(ierr);
2629   ierr = PetscLogEventEnd(MAT_MultHermitianTransposeAdd,mat,v1,v2,v3);CHKERRQ(ierr);
2630   ierr = PetscObjectStateIncrease((PetscObject)v3);CHKERRQ(ierr);
2631   PetscFunctionReturn(0);
2632 }
2633 
2634 /*@
2635    MatMultConstrained - The inner multiplication routine for a
2636    constrained matrix P^T A P.
2637 
2638    Neighbor-wise Collective on Mat and Vec
2639 
2640    Input Parameters:
2641 +  mat - the matrix
2642 -  x   - the vector to be multilplied
2643 
2644    Output Parameters:
2645 .  y - the result
2646 
2647    Notes:
2648    The vectors x and y cannot be the same.  I.e., one cannot
2649    call MatMult(A,y,y).
2650 
2651    Level: beginner
2652 
2653 .keywords: matrix, multiply, matrix-vector product, constraint
2654 .seealso: MatMult(), MatMultTranspose(), MatMultAdd(), MatMultTransposeAdd()
2655 @*/
2656 PetscErrorCode MatMultConstrained(Mat mat,Vec x,Vec y)
2657 {
2658   PetscErrorCode ierr;
2659 
2660   PetscFunctionBegin;
2661   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2662   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2663   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2664   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2665   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2666   if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2667   if (mat->cmap->N != x->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->cmap->N,x->map->N);
2668   if (mat->rmap->N != y->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %D %D",mat->rmap->N,y->map->N);
2669   if (mat->rmap->n != y->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: local dim %D %D",mat->rmap->n,y->map->n);
2670 
2671   ierr = PetscLogEventBegin(MAT_MultConstrained,mat,x,y,0);CHKERRQ(ierr);
2672   ierr = VecLockPush(x);CHKERRQ(ierr);
2673   ierr = (*mat->ops->multconstrained)(mat,x,y);CHKERRQ(ierr);
2674   ierr = VecLockPop(x);CHKERRQ(ierr);
2675   ierr = PetscLogEventEnd(MAT_MultConstrained,mat,x,y,0);CHKERRQ(ierr);
2676   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
2677   PetscFunctionReturn(0);
2678 }
2679 
2680 /*@
2681    MatMultTransposeConstrained - The inner multiplication routine for a
2682    constrained matrix P^T A^T P.
2683 
2684    Neighbor-wise Collective on Mat and Vec
2685 
2686    Input Parameters:
2687 +  mat - the matrix
2688 -  x   - the vector to be multilplied
2689 
2690    Output Parameters:
2691 .  y - the result
2692 
2693    Notes:
2694    The vectors x and y cannot be the same.  I.e., one cannot
2695    call MatMult(A,y,y).
2696 
2697    Level: beginner
2698 
2699 .keywords: matrix, multiply, matrix-vector product, constraint
2700 .seealso: MatMult(), MatMultTranspose(), MatMultAdd(), MatMultTransposeAdd()
2701 @*/
2702 PetscErrorCode MatMultTransposeConstrained(Mat mat,Vec x,Vec y)
2703 {
2704   PetscErrorCode ierr;
2705 
2706   PetscFunctionBegin;
2707   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2708   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
2709   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2710   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2711   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2712   if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"x and y must be different vectors");
2713   if (mat->rmap->N != x->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->cmap->N,x->map->N);
2714   if (mat->cmap->N != y->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %D %D",mat->rmap->N,y->map->N);
2715 
2716   ierr = PetscLogEventBegin(MAT_MultConstrained,mat,x,y,0);CHKERRQ(ierr);
2717   ierr = (*mat->ops->multtransposeconstrained)(mat,x,y);CHKERRQ(ierr);
2718   ierr = PetscLogEventEnd(MAT_MultConstrained,mat,x,y,0);CHKERRQ(ierr);
2719   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
2720   PetscFunctionReturn(0);
2721 }
2722 
2723 /*@C
2724    MatGetFactorType - gets the type of factorization it is
2725 
2726    Note Collective
2727    as the flag
2728 
2729    Input Parameters:
2730 .  mat - the matrix
2731 
2732    Output Parameters:
2733 .  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2734 
2735     Level: intermediate
2736 
2737 .seealso:    MatFactorType, MatGetFactor()
2738 @*/
2739 PetscErrorCode MatGetFactorType(Mat mat,MatFactorType *t)
2740 {
2741   PetscFunctionBegin;
2742   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2743   PetscValidType(mat,1);
2744   *t = mat->factortype;
2745   PetscFunctionReturn(0);
2746 }
2747 
2748 /* ------------------------------------------------------------*/
2749 /*@C
2750    MatGetInfo - Returns information about matrix storage (number of
2751    nonzeros, memory, etc.).
2752 
2753    Collective on Mat if MAT_GLOBAL_MAX or MAT_GLOBAL_SUM is used as the flag
2754 
2755    Input Parameters:
2756 .  mat - the matrix
2757 
2758    Output Parameters:
2759 +  flag - flag indicating the type of parameters to be returned
2760    (MAT_LOCAL - local matrix, MAT_GLOBAL_MAX - maximum over all processors,
2761    MAT_GLOBAL_SUM - sum over all processors)
2762 -  info - matrix information context
2763 
2764    Notes:
2765    The MatInfo context contains a variety of matrix data, including
2766    number of nonzeros allocated and used, number of mallocs during
2767    matrix assembly, etc.  Additional information for factored matrices
2768    is provided (such as the fill ratio, number of mallocs during
2769    factorization, etc.).  Much of this info is printed to PETSC_STDOUT
2770    when using the runtime options
2771 $       -info -mat_view ::ascii_info
2772 
2773    Example for C/C++ Users:
2774    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2775    data within the MatInfo context.  For example,
2776 .vb
2777       MatInfo info;
2778       Mat     A;
2779       double  mal, nz_a, nz_u;
2780 
2781       MatGetInfo(A,MAT_LOCAL,&info);
2782       mal  = info.mallocs;
2783       nz_a = info.nz_allocated;
2784 .ve
2785 
2786    Example for Fortran Users:
2787    Fortran users should declare info as a double precision
2788    array of dimension MAT_INFO_SIZE, and then extract the parameters
2789    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2790    a complete list of parameter names.
2791 .vb
2792       double  precision info(MAT_INFO_SIZE)
2793       double  precision mal, nz_a
2794       Mat     A
2795       integer ierr
2796 
2797       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2798       mal = info(MAT_INFO_MALLOCS)
2799       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2800 .ve
2801 
2802     Level: intermediate
2803 
2804     Concepts: matrices^getting information on
2805 
2806     Developer Note: fortran interface is not autogenerated as the f90
2807     interface defintion cannot be generated correctly [due to MatInfo]
2808 
2809 .seealso: MatStashGetInfo()
2810 
2811 @*/
2812 PetscErrorCode MatGetInfo(Mat mat,MatInfoType flag,MatInfo *info)
2813 {
2814   PetscErrorCode ierr;
2815 
2816   PetscFunctionBegin;
2817   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2818   PetscValidType(mat,1);
2819   PetscValidPointer(info,3);
2820   if (!mat->ops->getinfo) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2821   MatCheckPreallocated(mat,1);
2822   ierr = (*mat->ops->getinfo)(mat,flag,info);CHKERRQ(ierr);
2823   PetscFunctionReturn(0);
2824 }
2825 
2826 /*
2827    This is used by external packages where it is not easy to get the info from the actual
2828    matrix factorization.
2829 */
2830 PetscErrorCode MatGetInfo_External(Mat A,MatInfoType flag,MatInfo *info)
2831 {
2832   PetscErrorCode ierr;
2833 
2834   PetscFunctionBegin;
2835   ierr = PetscMemzero(info,sizeof(MatInfo));CHKERRQ(ierr);
2836   PetscFunctionReturn(0);
2837 }
2838 
2839 /* ----------------------------------------------------------*/
2840 
2841 /*@C
2842    MatLUFactor - Performs in-place LU factorization of matrix.
2843 
2844    Collective on Mat
2845 
2846    Input Parameters:
2847 +  mat - the matrix
2848 .  row - row permutation
2849 .  col - column permutation
2850 -  info - options for factorization, includes
2851 $          fill - expected fill as ratio of original fill.
2852 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2853 $                   Run with the option -info to determine an optimal value to use
2854 
2855    Notes:
2856    Most users should employ the simplified KSP interface for linear solvers
2857    instead of working directly with matrix algebra routines such as this.
2858    See, e.g., KSPCreate().
2859 
2860    This changes the state of the matrix to a factored matrix; it cannot be used
2861    for example with MatSetValues() unless one first calls MatSetUnfactored().
2862 
2863    Level: developer
2864 
2865    Concepts: matrices^LU factorization
2866 
2867 .seealso: MatLUFactorSymbolic(), MatLUFactorNumeric(), MatCholeskyFactor(),
2868           MatGetOrdering(), MatSetUnfactored(), MatFactorInfo, MatGetFactor()
2869 
2870     Developer Note: fortran interface is not autogenerated as the f90
2871     interface defintion cannot be generated correctly [due to MatFactorInfo]
2872 
2873 @*/
2874 PetscErrorCode MatLUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
2875 {
2876   PetscErrorCode ierr;
2877   MatFactorInfo  tinfo;
2878 
2879   PetscFunctionBegin;
2880   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2881   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
2882   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
2883   if (info) PetscValidPointer(info,4);
2884   PetscValidType(mat,1);
2885   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2886   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2887   if (!mat->ops->lufactor) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2888   MatCheckPreallocated(mat,1);
2889   if (!info) {
2890     ierr = MatFactorInfoInitialize(&tinfo);CHKERRQ(ierr);
2891     info = &tinfo;
2892   }
2893 
2894   ierr = PetscLogEventBegin(MAT_LUFactor,mat,row,col,0);CHKERRQ(ierr);
2895   ierr = (*mat->ops->lufactor)(mat,row,col,info);CHKERRQ(ierr);
2896   ierr = PetscLogEventEnd(MAT_LUFactor,mat,row,col,0);CHKERRQ(ierr);
2897   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
2898   PetscFunctionReturn(0);
2899 }
2900 
2901 /*@C
2902    MatILUFactor - Performs in-place ILU factorization of matrix.
2903 
2904    Collective on Mat
2905 
2906    Input Parameters:
2907 +  mat - the matrix
2908 .  row - row permutation
2909 .  col - column permutation
2910 -  info - structure containing
2911 $      levels - number of levels of fill.
2912 $      expected fill - as ratio of original fill.
2913 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
2914                 missing diagonal entries)
2915 
2916    Notes:
2917    Probably really in-place only when level of fill is zero, otherwise allocates
2918    new space to store factored matrix and deletes previous memory.
2919 
2920    Most users should employ the simplified KSP interface for linear solvers
2921    instead of working directly with matrix algebra routines such as this.
2922    See, e.g., KSPCreate().
2923 
2924    Level: developer
2925 
2926    Concepts: matrices^ILU factorization
2927 
2928 .seealso: MatILUFactorSymbolic(), MatLUFactorNumeric(), MatCholeskyFactor(), MatFactorInfo
2929 
2930     Developer Note: fortran interface is not autogenerated as the f90
2931     interface defintion cannot be generated correctly [due to MatFactorInfo]
2932 
2933 @*/
2934 PetscErrorCode MatILUFactor(Mat mat,IS row,IS col,const MatFactorInfo *info)
2935 {
2936   PetscErrorCode ierr;
2937 
2938   PetscFunctionBegin;
2939   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2940   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
2941   if (col) PetscValidHeaderSpecific(col,IS_CLASSID,3);
2942   PetscValidPointer(info,4);
2943   PetscValidType(mat,1);
2944   if (mat->rmap->N != mat->cmap->N) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
2945   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2946   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2947   if (!mat->ops->ilufactor) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
2948   MatCheckPreallocated(mat,1);
2949 
2950   ierr = PetscLogEventBegin(MAT_ILUFactor,mat,row,col,0);CHKERRQ(ierr);
2951   ierr = (*mat->ops->ilufactor)(mat,row,col,info);CHKERRQ(ierr);
2952   ierr = PetscLogEventEnd(MAT_ILUFactor,mat,row,col,0);CHKERRQ(ierr);
2953   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
2954   PetscFunctionReturn(0);
2955 }
2956 
2957 /*@C
2958    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
2959    Call this routine before calling MatLUFactorNumeric().
2960 
2961    Collective on Mat
2962 
2963    Input Parameters:
2964 +  fact - the factor matrix obtained with MatGetFactor()
2965 .  mat - the matrix
2966 .  row, col - row and column permutations
2967 -  info - options for factorization, includes
2968 $          fill - expected fill as ratio of original fill.
2969 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2970 $                   Run with the option -info to determine an optimal value to use
2971 
2972 
2973    Notes:
2974     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
2975 
2976    Most users should employ the simplified KSP interface for linear solvers
2977    instead of working directly with matrix algebra routines such as this.
2978    See, e.g., KSPCreate().
2979 
2980    Level: developer
2981 
2982    Concepts: matrices^LU symbolic factorization
2983 
2984 .seealso: MatLUFactor(), MatLUFactorNumeric(), MatCholeskyFactor(), MatFactorInfo, MatFactorInfoInitialize()
2985 
2986     Developer Note: fortran interface is not autogenerated as the f90
2987     interface defintion cannot be generated correctly [due to MatFactorInfo]
2988 
2989 @*/
2990 PetscErrorCode MatLUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
2991 {
2992   PetscErrorCode ierr;
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   PetscValidPointer(fact,5);
3001   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3002   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3003   if (!(fact)->ops->lufactorsymbolic) {
3004     MatSolverType spackage;
3005     ierr = MatFactorGetSolverType(fact,&spackage);CHKERRQ(ierr);
3006     SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic LU using solver package %s",((PetscObject)mat)->type_name,spackage);
3007   }
3008   MatCheckPreallocated(mat,2);
3009 
3010   ierr = PetscLogEventBegin(MAT_LUFactorSymbolic,mat,row,col,0);CHKERRQ(ierr);
3011   ierr = (fact->ops->lufactorsymbolic)(fact,mat,row,col,info);CHKERRQ(ierr);
3012   ierr = PetscLogEventEnd(MAT_LUFactorSymbolic,mat,row,col,0);CHKERRQ(ierr);
3013   ierr = PetscObjectStateIncrease((PetscObject)fact);CHKERRQ(ierr);
3014   PetscFunctionReturn(0);
3015 }
3016 
3017 /*@C
3018    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3019    Call this routine after first calling MatLUFactorSymbolic().
3020 
3021    Collective on Mat
3022 
3023    Input Parameters:
3024 +  fact - the factor matrix obtained with MatGetFactor()
3025 .  mat - the matrix
3026 -  info - options for factorization
3027 
3028    Notes:
3029    See MatLUFactor() for in-place factorization.  See
3030    MatCholeskyFactorNumeric() for the symmetric, positive definite case.
3031 
3032    Most users should employ the simplified KSP interface for linear solvers
3033    instead of working directly with matrix algebra routines such as this.
3034    See, e.g., KSPCreate().
3035 
3036    Level: developer
3037 
3038    Concepts: matrices^LU numeric factorization
3039 
3040 .seealso: MatLUFactorSymbolic(), MatLUFactor(), MatCholeskyFactor()
3041 
3042     Developer Note: fortran interface is not autogenerated as the f90
3043     interface defintion cannot be generated correctly [due to MatFactorInfo]
3044 
3045 @*/
3046 PetscErrorCode MatLUFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3047 {
3048   PetscErrorCode ierr;
3049 
3050   PetscFunctionBegin;
3051   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3052   PetscValidType(mat,1);
3053   PetscValidPointer(fact,2);
3054   PetscValidHeaderSpecific(fact,MAT_CLASSID,2);
3055   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3056   if (mat->rmap->N != (fact)->rmap->N || mat->cmap->N != (fact)->cmap->N) SETERRQ4(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dimensions are different %D should = %D %D should = %D",mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3057 
3058   if (!(fact)->ops->lufactornumeric) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric LU",((PetscObject)mat)->type_name);
3059   MatCheckPreallocated(mat,2);
3060   ierr = PetscLogEventBegin(MAT_LUFactorNumeric,mat,fact,0,0);CHKERRQ(ierr);
3061   ierr = (fact->ops->lufactornumeric)(fact,mat,info);CHKERRQ(ierr);
3062   ierr = PetscLogEventEnd(MAT_LUFactorNumeric,mat,fact,0,0);CHKERRQ(ierr);
3063   ierr = MatViewFromOptions(fact,NULL,"-mat_factor_view");CHKERRQ(ierr);
3064   ierr = PetscObjectStateIncrease((PetscObject)fact);CHKERRQ(ierr);
3065   PetscFunctionReturn(0);
3066 }
3067 
3068 /*@C
3069    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3070    symmetric matrix.
3071 
3072    Collective on Mat
3073 
3074    Input Parameters:
3075 +  mat - the matrix
3076 .  perm - row and column permutations
3077 -  f - expected fill as ratio of original fill
3078 
3079    Notes:
3080    See MatLUFactor() for the nonsymmetric case.  See also
3081    MatCholeskyFactorSymbolic(), and MatCholeskyFactorNumeric().
3082 
3083    Most users should employ the simplified KSP interface for linear solvers
3084    instead of working directly with matrix algebra routines such as this.
3085    See, e.g., KSPCreate().
3086 
3087    Level: developer
3088 
3089    Concepts: matrices^Cholesky factorization
3090 
3091 .seealso: MatLUFactor(), MatCholeskyFactorSymbolic(), MatCholeskyFactorNumeric()
3092           MatGetOrdering()
3093 
3094     Developer Note: fortran interface is not autogenerated as the f90
3095     interface defintion cannot be generated correctly [due to MatFactorInfo]
3096 
3097 @*/
3098 PetscErrorCode MatCholeskyFactor(Mat mat,IS perm,const MatFactorInfo *info)
3099 {
3100   PetscErrorCode ierr;
3101 
3102   PetscFunctionBegin;
3103   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3104   PetscValidType(mat,1);
3105   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,2);
3106   if (info) PetscValidPointer(info,3);
3107   if (mat->rmap->N != mat->cmap->N) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3108   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3109   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3110   if (!mat->ops->choleskyfactor) SETERRQ1(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);
3111   MatCheckPreallocated(mat,1);
3112 
3113   ierr = PetscLogEventBegin(MAT_CholeskyFactor,mat,perm,0,0);CHKERRQ(ierr);
3114   ierr = (*mat->ops->choleskyfactor)(mat,perm,info);CHKERRQ(ierr);
3115   ierr = PetscLogEventEnd(MAT_CholeskyFactor,mat,perm,0,0);CHKERRQ(ierr);
3116   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
3117   PetscFunctionReturn(0);
3118 }
3119 
3120 /*@C
3121    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3122    of a symmetric matrix.
3123 
3124    Collective on Mat
3125 
3126    Input Parameters:
3127 +  fact - the factor matrix obtained with MatGetFactor()
3128 .  mat - the matrix
3129 .  perm - row and column permutations
3130 -  info - options for factorization, includes
3131 $          fill - expected fill as ratio of original fill.
3132 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3133 $                   Run with the option -info to determine an optimal value to use
3134 
3135    Notes:
3136    See MatLUFactorSymbolic() for the nonsymmetric case.  See also
3137    MatCholeskyFactor() and MatCholeskyFactorNumeric().
3138 
3139    Most users should employ the simplified KSP interface for linear solvers
3140    instead of working directly with matrix algebra routines such as this.
3141    See, e.g., KSPCreate().
3142 
3143    Level: developer
3144 
3145    Concepts: matrices^Cholesky symbolic factorization
3146 
3147 .seealso: MatLUFactorSymbolic(), MatCholeskyFactor(), MatCholeskyFactorNumeric()
3148           MatGetOrdering()
3149 
3150     Developer Note: fortran interface is not autogenerated as the f90
3151     interface defintion cannot be generated correctly [due to MatFactorInfo]
3152 
3153 @*/
3154 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
3155 {
3156   PetscErrorCode ierr;
3157 
3158   PetscFunctionBegin;
3159   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3160   PetscValidType(mat,1);
3161   if (perm) PetscValidHeaderSpecific(perm,IS_CLASSID,2);
3162   if (info) PetscValidPointer(info,3);
3163   PetscValidPointer(fact,4);
3164   if (mat->rmap->N != mat->cmap->N) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Matrix must be square");
3165   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3166   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3167   if (!(fact)->ops->choleskyfactorsymbolic) {
3168     MatSolverType spackage;
3169     ierr = MatFactorGetSolverType(fact,&spackage);CHKERRQ(ierr);
3170     SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s symbolic factor Cholesky using solver package %s",((PetscObject)mat)->type_name,spackage);
3171   }
3172   MatCheckPreallocated(mat,2);
3173 
3174   ierr = PetscLogEventBegin(MAT_CholeskyFactorSymbolic,mat,perm,0,0);CHKERRQ(ierr);
3175   ierr = (fact->ops->choleskyfactorsymbolic)(fact,mat,perm,info);CHKERRQ(ierr);
3176   ierr = PetscLogEventEnd(MAT_CholeskyFactorSymbolic,mat,perm,0,0);CHKERRQ(ierr);
3177   ierr = PetscObjectStateIncrease((PetscObject)fact);CHKERRQ(ierr);
3178   PetscFunctionReturn(0);
3179 }
3180 
3181 /*@C
3182    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3183    of a symmetric matrix. Call this routine after first calling
3184    MatCholeskyFactorSymbolic().
3185 
3186    Collective on Mat
3187 
3188    Input Parameters:
3189 +  fact - the factor matrix obtained with MatGetFactor()
3190 .  mat - the initial matrix
3191 .  info - options for factorization
3192 -  fact - the symbolic factor of mat
3193 
3194 
3195    Notes:
3196    Most users should employ the simplified KSP interface for linear solvers
3197    instead of working directly with matrix algebra routines such as this.
3198    See, e.g., KSPCreate().
3199 
3200    Level: developer
3201 
3202    Concepts: matrices^Cholesky numeric factorization
3203 
3204 .seealso: MatCholeskyFactorSymbolic(), MatCholeskyFactor(), MatLUFactorNumeric()
3205 
3206     Developer Note: fortran interface is not autogenerated as the f90
3207     interface defintion cannot be generated correctly [due to MatFactorInfo]
3208 
3209 @*/
3210 PetscErrorCode MatCholeskyFactorNumeric(Mat fact,Mat mat,const MatFactorInfo *info)
3211 {
3212   PetscErrorCode ierr;
3213 
3214   PetscFunctionBegin;
3215   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3216   PetscValidType(mat,1);
3217   PetscValidPointer(fact,2);
3218   PetscValidHeaderSpecific(fact,MAT_CLASSID,2);
3219   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3220   if (!(fact)->ops->choleskyfactornumeric) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s numeric factor Cholesky",((PetscObject)mat)->type_name);
3221   if (mat->rmap->N != (fact)->rmap->N || mat->cmap->N != (fact)->cmap->N) SETERRQ4(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Mat fact: global dim %D should = %D %D should = %D",mat->rmap->N,(fact)->rmap->N,mat->cmap->N,(fact)->cmap->N);
3222   MatCheckPreallocated(mat,2);
3223 
3224   ierr = PetscLogEventBegin(MAT_CholeskyFactorNumeric,mat,fact,0,0);CHKERRQ(ierr);
3225   ierr = (fact->ops->choleskyfactornumeric)(fact,mat,info);CHKERRQ(ierr);
3226   ierr = PetscLogEventEnd(MAT_CholeskyFactorNumeric,mat,fact,0,0);CHKERRQ(ierr);
3227   ierr = MatViewFromOptions(fact,NULL,"-mat_factor_view");CHKERRQ(ierr);
3228   ierr = PetscObjectStateIncrease((PetscObject)fact);CHKERRQ(ierr);
3229   PetscFunctionReturn(0);
3230 }
3231 
3232 /* ----------------------------------------------------------------*/
3233 /*@
3234    MatSolve - Solves A x = b, given a factored matrix.
3235 
3236    Neighbor-wise Collective on Mat and Vec
3237 
3238    Input Parameters:
3239 +  mat - the factored matrix
3240 -  b - the right-hand-side vector
3241 
3242    Output Parameter:
3243 .  x - the result vector
3244 
3245    Notes:
3246    The vectors b and x cannot be the same.  I.e., one cannot
3247    call MatSolve(A,x,x).
3248 
3249    Notes:
3250    Most users should employ the simplified KSP interface for linear solvers
3251    instead of working directly with matrix algebra routines such as this.
3252    See, e.g., KSPCreate().
3253 
3254    Level: developer
3255 
3256    Concepts: matrices^triangular solves
3257 
3258 .seealso: MatSolveAdd(), MatSolveTranspose(), MatSolveTransposeAdd()
3259 @*/
3260 PetscErrorCode MatSolve(Mat mat,Vec b,Vec x)
3261 {
3262   PetscErrorCode ierr;
3263 
3264   PetscFunctionBegin;
3265   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3266   PetscValidType(mat,1);
3267   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3268   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3269   PetscCheckSameComm(mat,1,b,2);
3270   PetscCheckSameComm(mat,1,x,3);
3271   if (x == b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3272   if (mat->cmap->N != x->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->cmap->N,x->map->N);
3273   if (mat->rmap->N != b->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %D %D",mat->rmap->N,b->map->N);
3274   if (mat->rmap->n != b->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %D %D",mat->rmap->n,b->map->n);
3275   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3276   if (!mat->ops->solve) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3277   MatCheckPreallocated(mat,1);
3278 
3279   ierr = PetscLogEventBegin(MAT_Solve,mat,b,x,0);CHKERRQ(ierr);
3280   if (mat->factorerrortype) {
3281     ierr = PetscInfo1(mat,"MatFactorError %D\n",mat->factorerrortype);CHKERRQ(ierr);
3282     ierr = VecSetInf(x);CHKERRQ(ierr);
3283   } else {
3284     ierr = (*mat->ops->solve)(mat,b,x);CHKERRQ(ierr);
3285   }
3286   ierr = PetscLogEventEnd(MAT_Solve,mat,b,x,0);CHKERRQ(ierr);
3287   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
3288   PetscFunctionReturn(0);
3289 }
3290 
3291 static PetscErrorCode MatMatSolve_Basic(Mat A,Mat B,Mat X, PetscBool trans)
3292 {
3293   PetscErrorCode ierr;
3294   Vec            b,x;
3295   PetscInt       m,N,i;
3296   PetscScalar    *bb,*xx;
3297   PetscBool      flg;
3298 
3299   PetscFunctionBegin;
3300   ierr = PetscObjectTypeCompareAny((PetscObject)B,&flg,MATSEQDENSE,MATMPIDENSE,NULL);CHKERRQ(ierr);
3301   if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix B must be MATDENSE matrix");
3302   ierr = PetscObjectTypeCompareAny((PetscObject)X,&flg,MATSEQDENSE,MATMPIDENSE,NULL);CHKERRQ(ierr);
3303   if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix X must be MATDENSE matrix");
3304 
3305   ierr = MatDenseGetArray(B,&bb);CHKERRQ(ierr);
3306   ierr = MatDenseGetArray(X,&xx);CHKERRQ(ierr);
3307   ierr = MatGetLocalSize(B,&m,NULL);CHKERRQ(ierr);  /* number local rows */
3308   ierr = MatGetSize(B,NULL,&N);CHKERRQ(ierr);       /* total columns in dense matrix */
3309   ierr = MatCreateVecs(A,&x,&b);CHKERRQ(ierr);
3310   for (i=0; i<N; i++) {
3311     ierr = VecPlaceArray(b,bb + i*m);CHKERRQ(ierr);
3312     ierr = VecPlaceArray(x,xx + i*m);CHKERRQ(ierr);
3313     if (trans) {
3314       ierr = MatSolveTranspose(A,b,x);CHKERRQ(ierr);
3315     } else {
3316       ierr = MatSolve(A,b,x);CHKERRQ(ierr);
3317     }
3318     ierr = VecResetArray(x);CHKERRQ(ierr);
3319     ierr = VecResetArray(b);CHKERRQ(ierr);
3320   }
3321   ierr = VecDestroy(&b);CHKERRQ(ierr);
3322   ierr = VecDestroy(&x);CHKERRQ(ierr);
3323   ierr = MatDenseRestoreArray(B,&bb);CHKERRQ(ierr);
3324   ierr = MatDenseRestoreArray(X,&xx);CHKERRQ(ierr);
3325   PetscFunctionReturn(0);
3326 }
3327 
3328 /*@
3329    MatMatSolve - Solves A X = B, given a factored matrix.
3330 
3331    Neighbor-wise Collective on Mat
3332 
3333    Input Parameters:
3334 +  A - the factored matrix
3335 -  B - the right-hand-side matrix  (dense matrix)
3336 
3337    Output Parameter:
3338 .  X - the result matrix (dense matrix)
3339 
3340    Notes:
3341    The matrices b and x cannot be the same.  I.e., one cannot
3342    call MatMatSolve(A,x,x).
3343 
3344    Notes:
3345    Most users should usually employ the simplified KSP interface for linear solvers
3346    instead of working directly with matrix algebra routines such as this.
3347    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3348    at a time.
3349 
3350    When using SuperLU_Dist as a parallel solver PETSc will use the SuperLU_Dist functionality to solve multiple right hand sides simultaneously. For MUMPS
3351    it calls a separate solve for each right hand side since MUMPS does not yet support distributed right hand sides.
3352 
3353    Since the resulting matrix X must always be dense we do not support sparse representation of the matrix B.
3354 
3355    Level: developer
3356 
3357    Concepts: matrices^triangular solves
3358 
3359 .seealso: MatMatSolveTranspose(), MatLUFactor(), MatCholeskyFactor()
3360 @*/
3361 PetscErrorCode MatMatSolve(Mat A,Mat B,Mat X)
3362 {
3363   PetscErrorCode ierr;
3364 
3365   PetscFunctionBegin;
3366   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3367   PetscValidType(A,1);
3368   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3369   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3370   PetscCheckSameComm(A,1,B,2);
3371   PetscCheckSameComm(A,1,X,3);
3372   if (X == B) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3373   if (A->cmap->N != X->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %D %D",A->cmap->N,X->rmap->N);
3374   if (A->rmap->N != B->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %D %D",A->rmap->N,B->rmap->N);
3375   if (X->cmap->N < B->cmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as rhs matrix");
3376   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3377   if (!A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3378   MatCheckPreallocated(A,1);
3379 
3380   ierr = PetscLogEventBegin(MAT_MatSolve,A,B,X,0);CHKERRQ(ierr);
3381   if (!A->ops->matsolve) {
3382     ierr = PetscInfo1(A,"Mat type %s using basic MatMatSolve\n",((PetscObject)A)->type_name);CHKERRQ(ierr);
3383     ierr = MatMatSolve_Basic(A,B,X,PETSC_FALSE);CHKERRQ(ierr);
3384   } else {
3385     ierr = (*A->ops->matsolve)(A,B,X);CHKERRQ(ierr);
3386   }
3387   ierr = PetscLogEventEnd(MAT_MatSolve,A,B,X,0);CHKERRQ(ierr);
3388   ierr = PetscObjectStateIncrease((PetscObject)X);CHKERRQ(ierr);
3389   PetscFunctionReturn(0);
3390 }
3391 
3392 /*@
3393    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3394 
3395    Neighbor-wise Collective on Mat
3396 
3397    Input Parameters:
3398 +  A - the factored matrix
3399 -  B - the right-hand-side matrix  (dense matrix)
3400 
3401    Output Parameter:
3402 .  X - the result matrix (dense matrix)
3403 
3404    Notes:
3405    The matrices B and X cannot be the same.  I.e., one cannot
3406    call MatMatSolveTranspose(A,X,X).
3407 
3408    Notes:
3409    Most users should usually employ the simplified KSP interface for linear solvers
3410    instead of working directly with matrix algebra routines such as this.
3411    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3412    at a time.
3413 
3414    When using SuperLU_Dist or MUMPS as a parallel solver, PETSc will use their functionality to solve multiple right hand sides simultaneously.
3415 
3416    Level: developer
3417 
3418    Concepts: matrices^triangular solves
3419 
3420 .seealso: MatMatSolve(), MatLUFactor(), MatCholeskyFactor()
3421 @*/
3422 PetscErrorCode MatMatSolveTranspose(Mat A,Mat B,Mat X)
3423 {
3424   PetscErrorCode ierr;
3425 
3426   PetscFunctionBegin;
3427   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3428   PetscValidType(A,1);
3429   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3430   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3431   PetscCheckSameComm(A,1,B,2);
3432   PetscCheckSameComm(A,1,X,3);
3433   if (X == B) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3434   if (A->cmap->N != X->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %D %D",A->cmap->N,X->rmap->N);
3435   if (A->rmap->N != B->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %D %D",A->rmap->N,B->rmap->N);
3436   if (A->rmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A,Mat B: local dim %D %D",A->rmap->n,B->rmap->n);
3437   if (X->cmap->N < B->cmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as rhs matrix");
3438   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3439   if (!A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3440   MatCheckPreallocated(A,1);
3441 
3442   ierr = PetscLogEventBegin(MAT_MatSolve,A,B,X,0);CHKERRQ(ierr);
3443   if (!A->ops->matsolvetranspose) {
3444     ierr = PetscInfo1(A,"Mat type %s using basic MatMatSolveTranspose\n",((PetscObject)A)->type_name);CHKERRQ(ierr);
3445     ierr = MatMatSolve_Basic(A,B,X,PETSC_TRUE);CHKERRQ(ierr);
3446   } else {
3447     ierr = (*A->ops->matsolvetranspose)(A,B,X);CHKERRQ(ierr);
3448   }
3449   ierr = PetscLogEventEnd(MAT_MatSolve,A,B,X,0);CHKERRQ(ierr);
3450   ierr = PetscObjectStateIncrease((PetscObject)X);CHKERRQ(ierr);
3451   PetscFunctionReturn(0);
3452 }
3453 
3454 /*@
3455    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3456 
3457    Neighbor-wise Collective on Mat
3458 
3459    Input Parameters:
3460 +  A - the factored matrix
3461 -  Bt - the transpose of right-hand-side matrix
3462 
3463    Output Parameter:
3464 .  X - the result matrix (dense matrix)
3465 
3466    Notes:
3467    Most users should usually employ the simplified KSP interface for linear solvers
3468    instead of working directly with matrix algebra routines such as this.
3469    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3470    at a time.
3471 
3472    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().
3473 
3474    Level: developer
3475 
3476    Concepts: matrices^triangular solves
3477 
3478 .seealso: MatMatSolve(), MatMatSolveTranspose(), MatLUFactor(), MatCholeskyFactor()
3479 @*/
3480 PetscErrorCode MatMatTransposeSolve(Mat A,Mat Bt,Mat X)
3481 {
3482   PetscErrorCode ierr;
3483 
3484   PetscFunctionBegin;
3485   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3486   PetscValidType(A,1);
3487   PetscValidHeaderSpecific(Bt,MAT_CLASSID,2);
3488   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3489   PetscCheckSameComm(A,1,Bt,2);
3490   PetscCheckSameComm(A,1,X,3);
3491 
3492   if (X == Bt) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_IDN,"X and B must be different matrices");
3493   if (!A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3494   if (A->cmap->N != X->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat X: global dim %D %D",A->cmap->N,X->rmap->N);
3495   if (A->rmap->N != Bt->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat Bt: global dim %D %D",A->rmap->N,Bt->cmap->N);
3496   if (X->cmap->N < Bt->rmap->N) SETERRQ(PetscObjectComm((PetscObject)X),PETSC_ERR_ARG_SIZ,"Solution matrix must have same number of columns as row number of the rhs matrix");
3497   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3498   MatCheckPreallocated(A,1);
3499 
3500   ierr = PetscLogEventBegin(MAT_MatTrSolve,A,Bt,X,0);CHKERRQ(ierr);
3501   if (A->ops->mattransposesolve) {
3502     ierr = (*A->ops->mattransposesolve)(A,Bt,X);CHKERRQ(ierr);
3503   } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatMatTransposeSolve() is not supported for the input matrix types");
3504   ierr = PetscLogEventEnd(MAT_MatTrSolve,A,Bt,X,0);CHKERRQ(ierr);
3505   ierr = PetscObjectStateIncrease((PetscObject)X);CHKERRQ(ierr);
3506   PetscFunctionReturn(0);
3507 }
3508 
3509 /*@
3510    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3511                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3512 
3513    Neighbor-wise Collective on Mat and Vec
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    MatSolve() should be used for most applications, as it performs
3524    a forward solve followed by a backward solve.
3525 
3526    The vectors b and x cannot be the same,  i.e., one cannot
3527    call MatForwardSolve(A,x,x).
3528 
3529    For matrix in seqsbaij format with block size larger than 1,
3530    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3531    MatForwardSolve() solves U^T*D y = b, and
3532    MatBackwardSolve() solves U x = y.
3533    Thus they do not provide a symmetric preconditioner.
3534 
3535    Most users should employ the simplified KSP interface for linear solvers
3536    instead of working directly with matrix algebra routines such as this.
3537    See, e.g., KSPCreate().
3538 
3539    Level: developer
3540 
3541    Concepts: matrices^forward solves
3542 
3543 .seealso: MatSolve(), MatBackwardSolve()
3544 @*/
3545 PetscErrorCode MatForwardSolve(Mat mat,Vec b,Vec x)
3546 {
3547   PetscErrorCode ierr;
3548 
3549   PetscFunctionBegin;
3550   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3551   PetscValidType(mat,1);
3552   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3553   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3554   PetscCheckSameComm(mat,1,b,2);
3555   PetscCheckSameComm(mat,1,x,3);
3556   if (x == b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3557   if (!mat->ops->forwardsolve) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3558   if (mat->cmap->N != x->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->cmap->N,x->map->N);
3559   if (mat->rmap->N != b->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %D %D",mat->rmap->N,b->map->N);
3560   if (mat->rmap->n != b->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %D %D",mat->rmap->n,b->map->n);
3561   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3562   if (!mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3563   MatCheckPreallocated(mat,1);
3564   ierr = PetscLogEventBegin(MAT_ForwardSolve,mat,b,x,0);CHKERRQ(ierr);
3565   ierr = (*mat->ops->forwardsolve)(mat,b,x);CHKERRQ(ierr);
3566   ierr = PetscLogEventEnd(MAT_ForwardSolve,mat,b,x,0);CHKERRQ(ierr);
3567   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
3568   PetscFunctionReturn(0);
3569 }
3570 
3571 /*@
3572    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3573                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3574 
3575    Neighbor-wise Collective on Mat and Vec
3576 
3577    Input Parameters:
3578 +  mat - the factored matrix
3579 -  b - the right-hand-side vector
3580 
3581    Output Parameter:
3582 .  x - the result vector
3583 
3584    Notes:
3585    MatSolve() should be used for most applications, as it performs
3586    a forward solve followed by a backward solve.
3587 
3588    The vectors b and x cannot be the same.  I.e., one cannot
3589    call MatBackwardSolve(A,x,x).
3590 
3591    For matrix in seqsbaij format with block size larger than 1,
3592    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3593    MatForwardSolve() solves U^T*D y = b, and
3594    MatBackwardSolve() solves U x = y.
3595    Thus they do not provide a symmetric preconditioner.
3596 
3597    Most users should employ the simplified KSP interface for linear solvers
3598    instead of working directly with matrix algebra routines such as this.
3599    See, e.g., KSPCreate().
3600 
3601    Level: developer
3602 
3603    Concepts: matrices^backward solves
3604 
3605 .seealso: MatSolve(), MatForwardSolve()
3606 @*/
3607 PetscErrorCode MatBackwardSolve(Mat mat,Vec b,Vec x)
3608 {
3609   PetscErrorCode ierr;
3610 
3611   PetscFunctionBegin;
3612   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3613   PetscValidType(mat,1);
3614   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3615   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3616   PetscCheckSameComm(mat,1,b,2);
3617   PetscCheckSameComm(mat,1,x,3);
3618   if (x == b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3619   if (!mat->ops->backwardsolve) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3620   if (mat->cmap->N != x->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->cmap->N,x->map->N);
3621   if (mat->rmap->N != b->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %D %D",mat->rmap->N,b->map->N);
3622   if (mat->rmap->n != b->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %D %D",mat->rmap->n,b->map->n);
3623   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3624   if (!mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3625   MatCheckPreallocated(mat,1);
3626 
3627   ierr = PetscLogEventBegin(MAT_BackwardSolve,mat,b,x,0);CHKERRQ(ierr);
3628   ierr = (*mat->ops->backwardsolve)(mat,b,x);CHKERRQ(ierr);
3629   ierr = PetscLogEventEnd(MAT_BackwardSolve,mat,b,x,0);CHKERRQ(ierr);
3630   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
3631   PetscFunctionReturn(0);
3632 }
3633 
3634 /*@
3635    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3636 
3637    Neighbor-wise Collective on Mat and Vec
3638 
3639    Input Parameters:
3640 +  mat - the factored matrix
3641 .  b - the right-hand-side vector
3642 -  y - the vector to be added to
3643 
3644    Output Parameter:
3645 .  x - the result vector
3646 
3647    Notes:
3648    The vectors b and x cannot be the same.  I.e., one cannot
3649    call MatSolveAdd(A,x,y,x).
3650 
3651    Most users should employ the simplified KSP interface for linear solvers
3652    instead of working directly with matrix algebra routines such as this.
3653    See, e.g., KSPCreate().
3654 
3655    Level: developer
3656 
3657    Concepts: matrices^triangular solves
3658 
3659 .seealso: MatSolve(), MatSolveTranspose(), MatSolveTransposeAdd()
3660 @*/
3661 PetscErrorCode MatSolveAdd(Mat mat,Vec b,Vec y,Vec x)
3662 {
3663   PetscScalar    one = 1.0;
3664   Vec            tmp;
3665   PetscErrorCode ierr;
3666 
3667   PetscFunctionBegin;
3668   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3669   PetscValidType(mat,1);
3670   PetscValidHeaderSpecific(y,VEC_CLASSID,2);
3671   PetscValidHeaderSpecific(b,VEC_CLASSID,3);
3672   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
3673   PetscCheckSameComm(mat,1,b,2);
3674   PetscCheckSameComm(mat,1,y,2);
3675   PetscCheckSameComm(mat,1,x,3);
3676   if (x == b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3677   if (mat->cmap->N != x->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->cmap->N,x->map->N);
3678   if (mat->rmap->N != b->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %D %D",mat->rmap->N,b->map->N);
3679   if (mat->rmap->N != y->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %D %D",mat->rmap->N,y->map->N);
3680   if (mat->rmap->n != b->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %D %D",mat->rmap->n,b->map->n);
3681   if (x->map->n != y->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vec x,Vec y: local dim %D %D",x->map->n,y->map->n);
3682   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3683   if (!mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3684   MatCheckPreallocated(mat,1);
3685 
3686   ierr = PetscLogEventBegin(MAT_SolveAdd,mat,b,x,y);CHKERRQ(ierr);
3687   if (mat->ops->solveadd) {
3688     ierr = (*mat->ops->solveadd)(mat,b,y,x);CHKERRQ(ierr);
3689   } else {
3690     /* do the solve then the add manually */
3691     if (x != y) {
3692       ierr = MatSolve(mat,b,x);CHKERRQ(ierr);
3693       ierr = VecAXPY(x,one,y);CHKERRQ(ierr);
3694     } else {
3695       ierr = VecDuplicate(x,&tmp);CHKERRQ(ierr);
3696       ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp);CHKERRQ(ierr);
3697       ierr = VecCopy(x,tmp);CHKERRQ(ierr);
3698       ierr = MatSolve(mat,b,x);CHKERRQ(ierr);
3699       ierr = VecAXPY(x,one,tmp);CHKERRQ(ierr);
3700       ierr = VecDestroy(&tmp);CHKERRQ(ierr);
3701     }
3702   }
3703   ierr = PetscLogEventEnd(MAT_SolveAdd,mat,b,x,y);CHKERRQ(ierr);
3704   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
3705   PetscFunctionReturn(0);
3706 }
3707 
3708 /*@
3709    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3710 
3711    Neighbor-wise Collective on Mat and Vec
3712 
3713    Input Parameters:
3714 +  mat - the factored matrix
3715 -  b - the right-hand-side vector
3716 
3717    Output Parameter:
3718 .  x - the result vector
3719 
3720    Notes:
3721    The vectors b and x cannot be the same.  I.e., one cannot
3722    call MatSolveTranspose(A,x,x).
3723 
3724    Most users should employ the simplified KSP interface for linear solvers
3725    instead of working directly with matrix algebra routines such as this.
3726    See, e.g., KSPCreate().
3727 
3728    Level: developer
3729 
3730    Concepts: matrices^triangular solves
3731 
3732 .seealso: MatSolve(), MatSolveAdd(), MatSolveTransposeAdd()
3733 @*/
3734 PetscErrorCode MatSolveTranspose(Mat mat,Vec b,Vec x)
3735 {
3736   PetscErrorCode ierr;
3737 
3738   PetscFunctionBegin;
3739   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3740   PetscValidType(mat,1);
3741   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3742   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
3743   PetscCheckSameComm(mat,1,b,2);
3744   PetscCheckSameComm(mat,1,x,3);
3745   if (x == b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3746   if (!mat->ops->solvetranspose) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s",((PetscObject)mat)->type_name);
3747   if (mat->rmap->N != x->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->rmap->N,x->map->N);
3748   if (mat->cmap->N != b->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %D %D",mat->cmap->N,b->map->N);
3749   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3750   if (!mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3751   MatCheckPreallocated(mat,1);
3752   ierr = PetscLogEventBegin(MAT_SolveTranspose,mat,b,x,0);CHKERRQ(ierr);
3753   if (mat->factorerrortype) {
3754     ierr = PetscInfo1(mat,"MatFactorError %D\n",mat->factorerrortype);CHKERRQ(ierr);
3755     ierr = VecSetInf(x);CHKERRQ(ierr);
3756   } else {
3757     ierr = (*mat->ops->solvetranspose)(mat,b,x);CHKERRQ(ierr);
3758   }
3759   ierr = PetscLogEventEnd(MAT_SolveTranspose,mat,b,x,0);CHKERRQ(ierr);
3760   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
3761   PetscFunctionReturn(0);
3762 }
3763 
3764 /*@
3765    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3766                       factored matrix.
3767 
3768    Neighbor-wise Collective on Mat and Vec
3769 
3770    Input Parameters:
3771 +  mat - the factored matrix
3772 .  b - the right-hand-side vector
3773 -  y - the vector to be added to
3774 
3775    Output Parameter:
3776 .  x - the result vector
3777 
3778    Notes:
3779    The vectors b and x cannot be the same.  I.e., one cannot
3780    call MatSolveTransposeAdd(A,x,y,x).
3781 
3782    Most users should employ the simplified KSP interface for linear solvers
3783    instead of working directly with matrix algebra routines such as this.
3784    See, e.g., KSPCreate().
3785 
3786    Level: developer
3787 
3788    Concepts: matrices^triangular solves
3789 
3790 .seealso: MatSolve(), MatSolveAdd(), MatSolveTranspose()
3791 @*/
3792 PetscErrorCode MatSolveTransposeAdd(Mat mat,Vec b,Vec y,Vec x)
3793 {
3794   PetscScalar    one = 1.0;
3795   PetscErrorCode ierr;
3796   Vec            tmp;
3797 
3798   PetscFunctionBegin;
3799   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3800   PetscValidType(mat,1);
3801   PetscValidHeaderSpecific(y,VEC_CLASSID,2);
3802   PetscValidHeaderSpecific(b,VEC_CLASSID,3);
3803   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
3804   PetscCheckSameComm(mat,1,b,2);
3805   PetscCheckSameComm(mat,1,y,3);
3806   PetscCheckSameComm(mat,1,x,4);
3807   if (x == b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
3808   if (mat->rmap->N != x->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->rmap->N,x->map->N);
3809   if (mat->cmap->N != b->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %D %D",mat->cmap->N,b->map->N);
3810   if (mat->cmap->N != y->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec y: global dim %D %D",mat->cmap->N,y->map->N);
3811   if (x->map->n != y->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vec x,Vec y: local dim %D %D",x->map->n,y->map->n);
3812   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3813   if (!mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
3814   MatCheckPreallocated(mat,1);
3815 
3816   ierr = PetscLogEventBegin(MAT_SolveTransposeAdd,mat,b,x,y);CHKERRQ(ierr);
3817   if (mat->ops->solvetransposeadd) {
3818     if (mat->factorerrortype) {
3819       ierr = PetscInfo1(mat,"MatFactorError %D\n",mat->factorerrortype);CHKERRQ(ierr);
3820       ierr = VecSetInf(x);CHKERRQ(ierr);
3821     } else {
3822       ierr = (*mat->ops->solvetransposeadd)(mat,b,y,x);CHKERRQ(ierr);
3823     }
3824   } else {
3825     /* do the solve then the add manually */
3826     if (x != y) {
3827       ierr = MatSolveTranspose(mat,b,x);CHKERRQ(ierr);
3828       ierr = VecAXPY(x,one,y);CHKERRQ(ierr);
3829     } else {
3830       ierr = VecDuplicate(x,&tmp);CHKERRQ(ierr);
3831       ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)tmp);CHKERRQ(ierr);
3832       ierr = VecCopy(x,tmp);CHKERRQ(ierr);
3833       ierr = MatSolveTranspose(mat,b,x);CHKERRQ(ierr);
3834       ierr = VecAXPY(x,one,tmp);CHKERRQ(ierr);
3835       ierr = VecDestroy(&tmp);CHKERRQ(ierr);
3836     }
3837   }
3838   ierr = PetscLogEventEnd(MAT_SolveTransposeAdd,mat,b,x,y);CHKERRQ(ierr);
3839   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
3840   PetscFunctionReturn(0);
3841 }
3842 /* ----------------------------------------------------------------*/
3843 
3844 /*@
3845    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
3846 
3847    Neighbor-wise Collective on Mat and Vec
3848 
3849    Input Parameters:
3850 +  mat - the matrix
3851 .  b - the right hand side
3852 .  omega - the relaxation factor
3853 .  flag - flag indicating the type of SOR (see below)
3854 .  shift -  diagonal shift
3855 .  its - the number of iterations
3856 -  lits - the number of local iterations
3857 
3858    Output Parameters:
3859 .  x - the solution (can contain an initial guess, use option SOR_ZERO_INITIAL_GUESS to indicate no guess)
3860 
3861    SOR Flags:
3862 .     SOR_FORWARD_SWEEP - forward SOR
3863 .     SOR_BACKWARD_SWEEP - backward SOR
3864 .     SOR_SYMMETRIC_SWEEP - SSOR (symmetric SOR)
3865 .     SOR_LOCAL_FORWARD_SWEEP - local forward SOR
3866 .     SOR_LOCAL_BACKWARD_SWEEP - local forward SOR
3867 .     SOR_LOCAL_SYMMETRIC_SWEEP - local SSOR
3868 .     SOR_APPLY_UPPER, SOR_APPLY_LOWER - applies
3869          upper/lower triangular part of matrix to
3870          vector (with omega)
3871 .     SOR_ZERO_INITIAL_GUESS - zero initial guess
3872 
3873    Notes:
3874    SOR_LOCAL_FORWARD_SWEEP, SOR_LOCAL_BACKWARD_SWEEP, and
3875    SOR_LOCAL_SYMMETRIC_SWEEP perform separate independent smoothings
3876    on each processor.
3877 
3878    Application programmers will not generally use MatSOR() directly,
3879    but instead will employ the KSP/PC interface.
3880 
3881    Notes:
3882     for BAIJ, SBAIJ, and AIJ matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
3883 
3884    Notes for Advanced Users:
3885    The flags are implemented as bitwise inclusive or operations.
3886    For example, use (SOR_ZERO_INITIAL_GUESS | SOR_SYMMETRIC_SWEEP)
3887    to specify a zero initial guess for SSOR.
3888 
3889    Most users should employ the simplified KSP interface for linear solvers
3890    instead of working directly with matrix algebra routines such as this.
3891    See, e.g., KSPCreate().
3892 
3893    Vectors x and b CANNOT be the same
3894 
3895    Developer Note: We should add block SOR support for AIJ matrices with block size set to great than one and no inodes
3896 
3897    Level: developer
3898 
3899    Concepts: matrices^relaxation
3900    Concepts: matrices^SOR
3901    Concepts: matrices^Gauss-Seidel
3902 
3903 @*/
3904 PetscErrorCode MatSOR(Mat mat,Vec b,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec x)
3905 {
3906   PetscErrorCode ierr;
3907 
3908   PetscFunctionBegin;
3909   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3910   PetscValidType(mat,1);
3911   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
3912   PetscValidHeaderSpecific(x,VEC_CLASSID,8);
3913   PetscCheckSameComm(mat,1,b,2);
3914   PetscCheckSameComm(mat,1,x,8);
3915   if (!mat->ops->sor) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
3916   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3917   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3918   if (mat->cmap->N != x->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec x: global dim %D %D",mat->cmap->N,x->map->N);
3919   if (mat->rmap->N != b->map->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: global dim %D %D",mat->rmap->N,b->map->N);
3920   if (mat->rmap->n != b->map->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec b: local dim %D %D",mat->rmap->n,b->map->n);
3921   if (its <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D positive",its);
3922   if (lits <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires local its %D positive",lits);
3923   if (b == x) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"b and x vector cannot be the same");
3924 
3925   MatCheckPreallocated(mat,1);
3926   ierr = PetscLogEventBegin(MAT_SOR,mat,b,x,0);CHKERRQ(ierr);
3927   ierr =(*mat->ops->sor)(mat,b,omega,flag,shift,its,lits,x);CHKERRQ(ierr);
3928   ierr = PetscLogEventEnd(MAT_SOR,mat,b,x,0);CHKERRQ(ierr);
3929   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
3930   PetscFunctionReturn(0);
3931 }
3932 
3933 /*
3934       Default matrix copy routine.
3935 */
3936 PetscErrorCode MatCopy_Basic(Mat A,Mat B,MatStructure str)
3937 {
3938   PetscErrorCode    ierr;
3939   PetscInt          i,rstart = 0,rend = 0,nz;
3940   const PetscInt    *cwork;
3941   const PetscScalar *vwork;
3942 
3943   PetscFunctionBegin;
3944   if (B->assembled) {
3945     ierr = MatZeroEntries(B);CHKERRQ(ierr);
3946   }
3947   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
3948   for (i=rstart; i<rend; i++) {
3949     ierr = MatGetRow(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
3950     ierr = MatSetValues(B,1,&i,nz,cwork,vwork,INSERT_VALUES);CHKERRQ(ierr);
3951     ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
3952   }
3953   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3954   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3955   PetscFunctionReturn(0);
3956 }
3957 
3958 /*@
3959    MatCopy - Copys a matrix to another matrix.
3960 
3961    Collective on Mat
3962 
3963    Input Parameters:
3964 +  A - the matrix
3965 -  str - SAME_NONZERO_PATTERN or DIFFERENT_NONZERO_PATTERN
3966 
3967    Output Parameter:
3968 .  B - where the copy is put
3969 
3970    Notes:
3971    If you use SAME_NONZERO_PATTERN then the two matrices had better have the
3972    same nonzero pattern or the routine will crash.
3973 
3974    MatCopy() copies the matrix entries of a matrix to another existing
3975    matrix (after first zeroing the second matrix).  A related routine is
3976    MatConvert(), which first creates a new matrix and then copies the data.
3977 
3978    Level: intermediate
3979 
3980    Concepts: matrices^copying
3981 
3982 .seealso: MatConvert(), MatDuplicate()
3983 
3984 @*/
3985 PetscErrorCode MatCopy(Mat A,Mat B,MatStructure str)
3986 {
3987   PetscErrorCode ierr;
3988   PetscInt       i;
3989 
3990   PetscFunctionBegin;
3991   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3992   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3993   PetscValidType(A,1);
3994   PetscValidType(B,2);
3995   PetscCheckSameComm(A,1,B,2);
3996   MatCheckPreallocated(B,2);
3997   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3998   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3999   if (A->rmap->N != B->rmap->N || A->cmap->N != B->cmap->N) SETERRQ4(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim (%D,%D) (%D,%D)",A->rmap->N,B->rmap->N,A->cmap->N,B->cmap->N);
4000   MatCheckPreallocated(A,1);
4001   if (A == B) PetscFunctionReturn(0);
4002 
4003   ierr = PetscLogEventBegin(MAT_Copy,A,B,0,0);CHKERRQ(ierr);
4004   if (A->ops->copy) {
4005     ierr = (*A->ops->copy)(A,B,str);CHKERRQ(ierr);
4006   } else { /* generic conversion */
4007     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
4008   }
4009 
4010   B->stencil.dim = A->stencil.dim;
4011   B->stencil.noc = A->stencil.noc;
4012   for (i=0; i<=A->stencil.dim; i++) {
4013     B->stencil.dims[i]   = A->stencil.dims[i];
4014     B->stencil.starts[i] = A->stencil.starts[i];
4015   }
4016 
4017   ierr = PetscLogEventEnd(MAT_Copy,A,B,0,0);CHKERRQ(ierr);
4018   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
4019   PetscFunctionReturn(0);
4020 }
4021 
4022 /*@C
4023    MatConvert - Converts a matrix to another matrix, either of the same
4024    or different type.
4025 
4026    Collective on Mat
4027 
4028    Input Parameters:
4029 +  mat - the matrix
4030 .  newtype - new matrix type.  Use MATSAME to create a new matrix of the
4031    same type as the original matrix.
4032 -  reuse - denotes if the destination matrix is to be created or reused.
4033    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
4034    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).
4035 
4036    Output Parameter:
4037 .  M - pointer to place new matrix
4038 
4039    Notes:
4040    MatConvert() first creates a new matrix and then copies the data from
4041    the first matrix.  A related routine is MatCopy(), which copies the matrix
4042    entries of one matrix to another already existing matrix context.
4043 
4044    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4045    the MPI communicator of the generated matrix is always the same as the communicator
4046    of the input matrix.
4047 
4048    Level: intermediate
4049 
4050    Concepts: matrices^converting between storage formats
4051 
4052 .seealso: MatCopy(), MatDuplicate()
4053 @*/
4054 PetscErrorCode MatConvert(Mat mat, MatType newtype,MatReuse reuse,Mat *M)
4055 {
4056   PetscErrorCode ierr;
4057   PetscBool      sametype,issame,flg;
4058   char           convname[256],mtype[256];
4059   Mat            B;
4060 
4061   PetscFunctionBegin;
4062   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4063   PetscValidType(mat,1);
4064   PetscValidPointer(M,3);
4065   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4066   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4067   MatCheckPreallocated(mat,1);
4068 
4069   ierr = PetscOptionsGetString(((PetscObject)mat)->options,((PetscObject)mat)->prefix,"-matconvert_type",mtype,256,&flg);CHKERRQ(ierr);
4070   if (flg) {
4071     newtype = mtype;
4072   }
4073   ierr = PetscObjectTypeCompare((PetscObject)mat,newtype,&sametype);CHKERRQ(ierr);
4074   ierr = PetscStrcmp(newtype,"same",&issame);CHKERRQ(ierr);
4075   if ((reuse == MAT_INPLACE_MATRIX) && (mat != *M)) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires same input and output matrix");
4076   if ((reuse == MAT_REUSE_MATRIX) && (mat == *M)) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4077 
4078   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) PetscFunctionReturn(0);
4079 
4080   if ((sametype || issame) && (reuse==MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4081     ierr = (*mat->ops->duplicate)(mat,MAT_COPY_VALUES,M);CHKERRQ(ierr);
4082   } else {
4083     PetscErrorCode (*conv)(Mat, MatType,MatReuse,Mat*)=NULL;
4084     const char     *prefix[3] = {"seq","mpi",""};
4085     PetscInt       i;
4086     /*
4087        Order of precedence:
4088        1) See if a specialized converter is known to the current matrix.
4089        2) See if a specialized converter is known to the desired matrix class.
4090        3) See if a good general converter is registered for the desired class
4091           (as of 6/27/03 only MATMPIADJ falls into this category).
4092        4) See if a good general converter is known for the current matrix.
4093        5) Use a really basic converter.
4094     */
4095 
4096     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4097     for (i=0; i<3; i++) {
4098       ierr = PetscStrncpy(convname,"MatConvert_",sizeof(convname));CHKERRQ(ierr);
4099       ierr = PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname));CHKERRQ(ierr);
4100       ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr);
4101       ierr = PetscStrlcat(convname,prefix[i],sizeof(convname));CHKERRQ(ierr);
4102       ierr = PetscStrlcat(convname,issame ? ((PetscObject)mat)->type_name : newtype,sizeof(convname));CHKERRQ(ierr);
4103       ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr);
4104       ierr = PetscObjectQueryFunction((PetscObject)mat,convname,&conv);CHKERRQ(ierr);
4105       if (conv) goto foundconv;
4106     }
4107 
4108     /* 2)  See if a specialized converter is known to the desired matrix class. */
4109     ierr = MatCreate(PetscObjectComm((PetscObject)mat),&B);CHKERRQ(ierr);
4110     ierr = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->N,mat->cmap->N);CHKERRQ(ierr);
4111     ierr = MatSetType(B,newtype);CHKERRQ(ierr);
4112     for (i=0; i<3; i++) {
4113       ierr = PetscStrncpy(convname,"MatConvert_",sizeof(convname));CHKERRQ(ierr);
4114       ierr = PetscStrlcat(convname,((PetscObject)mat)->type_name,sizeof(convname));CHKERRQ(ierr);
4115       ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr);
4116       ierr = PetscStrlcat(convname,prefix[i],sizeof(convname));CHKERRQ(ierr);
4117       ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr);
4118       ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr);
4119       ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr);
4120       if (conv) {
4121         ierr = MatDestroy(&B);CHKERRQ(ierr);
4122         goto foundconv;
4123       }
4124     }
4125 
4126     /* 3) See if a good general converter is registered for the desired class */
4127     conv = B->ops->convertfrom;
4128     ierr = MatDestroy(&B);CHKERRQ(ierr);
4129     if (conv) goto foundconv;
4130 
4131     /* 4) See if a good general converter is known for the current matrix */
4132     if (mat->ops->convert) {
4133       conv = mat->ops->convert;
4134     }
4135     if (conv) goto foundconv;
4136 
4137     /* 5) Use a really basic converter. */
4138     conv = MatConvert_Basic;
4139 
4140 foundconv:
4141     ierr = PetscLogEventBegin(MAT_Convert,mat,0,0,0);CHKERRQ(ierr);
4142     ierr = (*conv)(mat,newtype,reuse,M);CHKERRQ(ierr);
4143     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4144       /* the block sizes must be same if the mappings are copied over */
4145       (*M)->rmap->bs = mat->rmap->bs;
4146       (*M)->cmap->bs = mat->cmap->bs;
4147       ierr = PetscObjectReference((PetscObject)mat->rmap->mapping);CHKERRQ(ierr);
4148       ierr = PetscObjectReference((PetscObject)mat->cmap->mapping);CHKERRQ(ierr);
4149       (*M)->rmap->mapping = mat->rmap->mapping;
4150       (*M)->cmap->mapping = mat->cmap->mapping;
4151     }
4152     (*M)->stencil.dim = mat->stencil.dim;
4153     (*M)->stencil.noc = mat->stencil.noc;
4154     for (i=0; i<=mat->stencil.dim; i++) {
4155       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4156       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4157     }
4158     ierr = PetscLogEventEnd(MAT_Convert,mat,0,0,0);CHKERRQ(ierr);
4159   }
4160   ierr = PetscObjectStateIncrease((PetscObject)*M);CHKERRQ(ierr);
4161 
4162   /* Copy Mat options */
4163   if (mat->symmetric) {ierr = MatSetOption(*M,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);}
4164   if (mat->hermitian) {ierr = MatSetOption(*M,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);}
4165   PetscFunctionReturn(0);
4166 }
4167 
4168 /*@C
4169    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4170 
4171    Not Collective
4172 
4173    Input Parameter:
4174 .  mat - the matrix, must be a factored matrix
4175 
4176    Output Parameter:
4177 .   type - the string name of the package (do not free this string)
4178 
4179    Notes:
4180       In Fortran you pass in a empty string and the package name will be copied into it.
4181     (Make sure the string is long enough)
4182 
4183    Level: intermediate
4184 
4185 .seealso: MatCopy(), MatDuplicate(), MatGetFactorAvailable(), MatGetFactor()
4186 @*/
4187 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4188 {
4189   PetscErrorCode ierr, (*conv)(Mat,MatSolverType*);
4190 
4191   PetscFunctionBegin;
4192   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4193   PetscValidType(mat,1);
4194   if (!mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
4195   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatFactorGetSolverType_C",&conv);CHKERRQ(ierr);
4196   if (!conv) {
4197     *type = MATSOLVERPETSC;
4198   } else {
4199     ierr = (*conv)(mat,type);CHKERRQ(ierr);
4200   }
4201   PetscFunctionReturn(0);
4202 }
4203 
4204 typedef struct _MatSolverTypeForSpecifcType* MatSolverTypeForSpecifcType;
4205 struct _MatSolverTypeForSpecifcType {
4206   MatType                        mtype;
4207   PetscErrorCode                 (*getfactor[4])(Mat,MatFactorType,Mat*);
4208   MatSolverTypeForSpecifcType next;
4209 };
4210 
4211 typedef struct _MatSolverTypeHolder* MatSolverTypeHolder;
4212 struct _MatSolverTypeHolder {
4213   char                           *name;
4214   MatSolverTypeForSpecifcType handlers;
4215   MatSolverTypeHolder         next;
4216 };
4217 
4218 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4219 
4220 /*@C
4221    MatSolvePackageRegister - Registers a MatSolverType that works for a particular matrix type
4222 
4223    Input Parameters:
4224 +    package - name of the package, for example petsc or superlu
4225 .    mtype - the matrix type that works with this package
4226 .    ftype - the type of factorization supported by the package
4227 -    getfactor - routine that will create the factored matrix ready to be used
4228 
4229     Level: intermediate
4230 
4231 .seealso: MatCopy(), MatDuplicate(), MatGetFactorAvailable()
4232 @*/
4233 PetscErrorCode MatSolverTypeRegister(MatSolverType package,MatType mtype,MatFactorType ftype,PetscErrorCode (*getfactor)(Mat,MatFactorType,Mat*))
4234 {
4235   PetscErrorCode              ierr;
4236   MatSolverTypeHolder         next = MatSolverTypeHolders,prev;
4237   PetscBool                   flg;
4238   MatSolverTypeForSpecifcType inext,iprev = NULL;
4239 
4240   PetscFunctionBegin;
4241   if (!next) {
4242     ierr = PetscNew(&MatSolverTypeHolders);CHKERRQ(ierr);
4243     ierr = PetscStrallocpy(package,&MatSolverTypeHolders->name);CHKERRQ(ierr);
4244     ierr = PetscNew(&MatSolverTypeHolders->handlers);CHKERRQ(ierr);
4245     ierr = PetscStrallocpy(mtype,(char **)&MatSolverTypeHolders->handlers->mtype);CHKERRQ(ierr);
4246     MatSolverTypeHolders->handlers->getfactor[(int)ftype-1] = getfactor;
4247     PetscFunctionReturn(0);
4248   }
4249   while (next) {
4250     ierr = PetscStrcasecmp(package,next->name,&flg);CHKERRQ(ierr);
4251     if (flg) {
4252       if (!next->handlers) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatSolverTypeHolder is missing handlers");
4253       inext = next->handlers;
4254       while (inext) {
4255         ierr = PetscStrcasecmp(mtype,inext->mtype,&flg);CHKERRQ(ierr);
4256         if (flg) {
4257           inext->getfactor[(int)ftype-1] = getfactor;
4258           PetscFunctionReturn(0);
4259         }
4260         iprev = inext;
4261         inext = inext->next;
4262       }
4263       ierr = PetscNew(&iprev->next);CHKERRQ(ierr);
4264       ierr = PetscStrallocpy(mtype,(char **)&iprev->next->mtype);CHKERRQ(ierr);
4265       iprev->next->getfactor[(int)ftype-1] = getfactor;
4266       PetscFunctionReturn(0);
4267     }
4268     prev = next;
4269     next = next->next;
4270   }
4271   ierr = PetscNew(&prev->next);CHKERRQ(ierr);
4272   ierr = PetscStrallocpy(package,&prev->next->name);CHKERRQ(ierr);
4273   ierr = PetscNew(&prev->next->handlers);CHKERRQ(ierr);
4274   ierr = PetscStrallocpy(mtype,(char **)&prev->next->handlers->mtype);CHKERRQ(ierr);
4275   prev->next->handlers->getfactor[(int)ftype-1] = getfactor;
4276   PetscFunctionReturn(0);
4277 }
4278 
4279 /*@C
4280    MatSolvePackageGet - Get's the function that creates the factor matrix if it exist
4281 
4282    Input Parameters:
4283 +    package - name of the package, for example petsc or superlu
4284 .    ftype - the type of factorization supported by the package
4285 -    mtype - the matrix type that works with this package
4286 
4287    Output Parameters:
4288 +   foundpackage - PETSC_TRUE if the package was registered
4289 .   foundmtype - PETSC_TRUE if the package supports the requested mtype
4290 -   getfactor - routine that will create the factored matrix ready to be used or NULL if not found
4291 
4292     Level: intermediate
4293 
4294 .seealso: MatCopy(), MatDuplicate(), MatGetFactorAvailable()
4295 @*/
4296 PetscErrorCode MatSolverTypeGet(MatSolverType package,MatType mtype,MatFactorType ftype,PetscBool *foundpackage,PetscBool *foundmtype,PetscErrorCode (**getfactor)(Mat,MatFactorType,Mat*))
4297 {
4298   PetscErrorCode                 ierr;
4299   MatSolverTypeHolder         next = MatSolverTypeHolders;
4300   PetscBool                      flg;
4301   MatSolverTypeForSpecifcType inext;
4302 
4303   PetscFunctionBegin;
4304   if (foundpackage) *foundpackage = PETSC_FALSE;
4305   if (foundmtype)   *foundmtype   = PETSC_FALSE;
4306   if (getfactor)    *getfactor    = NULL;
4307 
4308   if (package) {
4309     while (next) {
4310       ierr = PetscStrcasecmp(package,next->name,&flg);CHKERRQ(ierr);
4311       if (flg) {
4312         if (foundpackage) *foundpackage = PETSC_TRUE;
4313         inext = next->handlers;
4314         while (inext) {
4315           ierr = PetscStrbeginswith(mtype,inext->mtype,&flg);CHKERRQ(ierr);
4316           if (flg) {
4317             if (foundmtype) *foundmtype = PETSC_TRUE;
4318             if (getfactor)  *getfactor  = inext->getfactor[(int)ftype-1];
4319             PetscFunctionReturn(0);
4320           }
4321           inext = inext->next;
4322         }
4323       }
4324       next = next->next;
4325     }
4326   } else {
4327     while (next) {
4328       inext = next->handlers;
4329       while (inext) {
4330         ierr = PetscStrbeginswith(mtype,inext->mtype,&flg);CHKERRQ(ierr);
4331         if (flg && inext->getfactor[(int)ftype-1]) {
4332           if (foundpackage) *foundpackage = PETSC_TRUE;
4333           if (foundmtype)   *foundmtype   = PETSC_TRUE;
4334           if (getfactor)    *getfactor    = inext->getfactor[(int)ftype-1];
4335           PetscFunctionReturn(0);
4336         }
4337         inext = inext->next;
4338       }
4339       next = next->next;
4340     }
4341   }
4342   PetscFunctionReturn(0);
4343 }
4344 
4345 PetscErrorCode MatSolverTypeDestroy(void)
4346 {
4347   PetscErrorCode              ierr;
4348   MatSolverTypeHolder         next = MatSolverTypeHolders,prev;
4349   MatSolverTypeForSpecifcType inext,iprev;
4350 
4351   PetscFunctionBegin;
4352   while (next) {
4353     ierr = PetscFree(next->name);CHKERRQ(ierr);
4354     inext = next->handlers;
4355     while (inext) {
4356       ierr = PetscFree(inext->mtype);CHKERRQ(ierr);
4357       iprev = inext;
4358       inext = inext->next;
4359       ierr = PetscFree(iprev);CHKERRQ(ierr);
4360     }
4361     prev = next;
4362     next = next->next;
4363     ierr = PetscFree(prev);CHKERRQ(ierr);
4364   }
4365   MatSolverTypeHolders = NULL;
4366   PetscFunctionReturn(0);
4367 }
4368 
4369 /*@C
4370    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4371 
4372    Collective on Mat
4373 
4374    Input Parameters:
4375 +  mat - the matrix
4376 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4377 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4378 
4379    Output Parameters:
4380 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4381 
4382    Notes:
4383       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4384      such as pastix, superlu, mumps etc.
4385 
4386       PETSc must have been ./configure to use the external solver, using the option --download-package
4387 
4388    Level: intermediate
4389 
4390 .seealso: MatCopy(), MatDuplicate(), MatGetFactorAvailable()
4391 @*/
4392 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type,MatFactorType ftype,Mat *f)
4393 {
4394   PetscErrorCode ierr,(*conv)(Mat,MatFactorType,Mat*);
4395   PetscBool      foundpackage,foundmtype;
4396 
4397   PetscFunctionBegin;
4398   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4399   PetscValidType(mat,1);
4400 
4401   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4402   MatCheckPreallocated(mat,1);
4403 
4404   ierr = MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,&foundpackage,&foundmtype,&conv);CHKERRQ(ierr);
4405   if (!foundpackage) {
4406     if (type) {
4407       SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"Could not locate solver package %s. Perhaps you must ./configure with --download-%s",type,type);
4408     } else {
4409       SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"Could not locate a solver package. Perhaps you must ./configure with --download-<package>");
4410     }
4411   }
4412 
4413   if (!foundmtype) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_MISSING_FACTOR,"MatSolverType %s does not support matrix type %s",type,((PetscObject)mat)->type_name);
4414   if (!conv) SETERRQ3(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);
4415 
4416 #if defined(PETSC_USE_COMPLEX)
4417   if (mat->hermitian && !mat->symmetric && (ftype == MAT_FACTOR_CHOLESKY||ftype == MAT_FACTOR_ICC)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Hermitian CHOLESKY or ICC Factor is not supported");
4418 #endif
4419 
4420   ierr = (*conv)(mat,ftype,f);CHKERRQ(ierr);
4421   PetscFunctionReturn(0);
4422 }
4423 
4424 /*@C
4425    MatGetFactorAvailable - Returns a a flag if matrix supports particular package and factor type
4426 
4427    Not Collective
4428 
4429    Input Parameters:
4430 +  mat - the matrix
4431 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4432 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4433 
4434    Output Parameter:
4435 .    flg - PETSC_TRUE if the factorization is available
4436 
4437    Notes:
4438       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4439      such as pastix, superlu, mumps etc.
4440 
4441       PETSc must have been ./configure to use the external solver, using the option --download-package
4442 
4443    Level: intermediate
4444 
4445 .seealso: MatCopy(), MatDuplicate(), MatGetFactor()
4446 @*/
4447 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type,MatFactorType ftype,PetscBool  *flg)
4448 {
4449   PetscErrorCode ierr, (*gconv)(Mat,MatFactorType,Mat*);
4450 
4451   PetscFunctionBegin;
4452   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4453   PetscValidType(mat,1);
4454 
4455   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4456   MatCheckPreallocated(mat,1);
4457 
4458   *flg = PETSC_FALSE;
4459   ierr = MatSolverTypeGet(type,((PetscObject)mat)->type_name,ftype,NULL,NULL,&gconv);CHKERRQ(ierr);
4460   if (gconv) {
4461     *flg = PETSC_TRUE;
4462   }
4463   PetscFunctionReturn(0);
4464 }
4465 
4466 #include <petscdmtypes.h>
4467 
4468 /*@
4469    MatDuplicate - Duplicates a matrix including the non-zero structure.
4470 
4471    Collective on Mat
4472 
4473    Input Parameters:
4474 +  mat - the matrix
4475 -  op - One of MAT_DO_NOT_COPY_VALUES, MAT_COPY_VALUES, or MAT_SHARE_NONZERO_PATTERN.
4476         See the manual page for MatDuplicateOption for an explanation of these options.
4477 
4478    Output Parameter:
4479 .  M - pointer to place new matrix
4480 
4481    Level: intermediate
4482 
4483    Concepts: matrices^duplicating
4484 
4485    Notes:
4486     You cannot change the nonzero pattern for the parent or child matrix if you use MAT_SHARE_NONZERO_PATTERN.
4487 
4488 .seealso: MatCopy(), MatConvert(), MatDuplicateOption
4489 @*/
4490 PetscErrorCode MatDuplicate(Mat mat,MatDuplicateOption op,Mat *M)
4491 {
4492   PetscErrorCode ierr;
4493   Mat            B;
4494   PetscInt       i;
4495   DM             dm;
4496   void           (*viewf)(void);
4497 
4498   PetscFunctionBegin;
4499   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4500   PetscValidType(mat,1);
4501   PetscValidPointer(M,3);
4502   if (op == MAT_COPY_VALUES && !mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MAT_COPY_VALUES not allowed for unassembled matrix");
4503   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4504   MatCheckPreallocated(mat,1);
4505 
4506   *M = 0;
4507   if (!mat->ops->duplicate) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not written for this matrix type");
4508   ierr = PetscLogEventBegin(MAT_Convert,mat,0,0,0);CHKERRQ(ierr);
4509   ierr = (*mat->ops->duplicate)(mat,op,M);CHKERRQ(ierr);
4510   B    = *M;
4511 
4512   ierr = MatGetOperation(mat,MATOP_VIEW,&viewf);CHKERRQ(ierr);
4513   if (viewf) {
4514     ierr = MatSetOperation(B,MATOP_VIEW,viewf);CHKERRQ(ierr);
4515   }
4516 
4517   B->stencil.dim = mat->stencil.dim;
4518   B->stencil.noc = mat->stencil.noc;
4519   for (i=0; i<=mat->stencil.dim; i++) {
4520     B->stencil.dims[i]   = mat->stencil.dims[i];
4521     B->stencil.starts[i] = mat->stencil.starts[i];
4522   }
4523 
4524   B->nooffproczerorows = mat->nooffproczerorows;
4525   B->nooffprocentries  = mat->nooffprocentries;
4526 
4527   ierr = PetscObjectQuery((PetscObject) mat, "__PETSc_dm", (PetscObject*) &dm);CHKERRQ(ierr);
4528   if (dm) {
4529     ierr = PetscObjectCompose((PetscObject) B, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr);
4530   }
4531   ierr = PetscLogEventEnd(MAT_Convert,mat,0,0,0);CHKERRQ(ierr);
4532   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
4533   PetscFunctionReturn(0);
4534 }
4535 
4536 /*@
4537    MatGetDiagonal - Gets the diagonal of a matrix.
4538 
4539    Logically Collective on Mat and Vec
4540 
4541    Input Parameters:
4542 +  mat - the matrix
4543 -  v - the vector for storing the diagonal
4544 
4545    Output Parameter:
4546 .  v - the diagonal of the matrix
4547 
4548    Level: intermediate
4549 
4550    Note:
4551    Currently only correct in parallel for square matrices.
4552 
4553    Concepts: matrices^accessing diagonals
4554 
4555 .seealso: MatGetRow(), MatCreateSubMatrices(), MatCreateSubMatrix(), MatGetRowMaxAbs()
4556 @*/
4557 PetscErrorCode MatGetDiagonal(Mat mat,Vec v)
4558 {
4559   PetscErrorCode ierr;
4560 
4561   PetscFunctionBegin;
4562   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4563   PetscValidType(mat,1);
4564   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4565   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4566   if (!mat->ops->getdiagonal) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4567   MatCheckPreallocated(mat,1);
4568 
4569   ierr = (*mat->ops->getdiagonal)(mat,v);CHKERRQ(ierr);
4570   ierr = PetscObjectStateIncrease((PetscObject)v);CHKERRQ(ierr);
4571   PetscFunctionReturn(0);
4572 }
4573 
4574 /*@C
4575    MatGetRowMin - Gets the minimum value (of the real part) of each
4576         row of the matrix
4577 
4578    Logically Collective on Mat and Vec
4579 
4580    Input Parameters:
4581 .  mat - the matrix
4582 
4583    Output Parameter:
4584 +  v - the vector for storing the maximums
4585 -  idx - the indices of the column found for each row (optional)
4586 
4587    Level: intermediate
4588 
4589    Notes:
4590     The result of this call are the same as if one converted the matrix to dense format
4591       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4592 
4593     This code is only implemented for a couple of matrix formats.
4594 
4595    Concepts: matrices^getting row maximums
4596 
4597 .seealso: MatGetDiagonal(), MatCreateSubMatrices(), MatCreateSubMatrix(), MatGetRowMaxAbs(),
4598           MatGetRowMax()
4599 @*/
4600 PetscErrorCode MatGetRowMin(Mat mat,Vec v,PetscInt idx[])
4601 {
4602   PetscErrorCode ierr;
4603 
4604   PetscFunctionBegin;
4605   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4606   PetscValidType(mat,1);
4607   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4608   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4609   if (!mat->ops->getrowmax) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4610   MatCheckPreallocated(mat,1);
4611 
4612   ierr = (*mat->ops->getrowmin)(mat,v,idx);CHKERRQ(ierr);
4613   ierr = PetscObjectStateIncrease((PetscObject)v);CHKERRQ(ierr);
4614   PetscFunctionReturn(0);
4615 }
4616 
4617 /*@C
4618    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4619         row of the matrix
4620 
4621    Logically Collective on Mat and Vec
4622 
4623    Input Parameters:
4624 .  mat - the matrix
4625 
4626    Output Parameter:
4627 +  v - the vector for storing the minimums
4628 -  idx - the indices of the column found for each row (or NULL if not needed)
4629 
4630    Level: intermediate
4631 
4632    Notes:
4633     if a row is completely empty or has only 0.0 values then the idx[] value for that
4634     row is 0 (the first column).
4635 
4636     This code is only implemented for a couple of matrix formats.
4637 
4638    Concepts: matrices^getting row maximums
4639 
4640 .seealso: MatGetDiagonal(), MatCreateSubMatrices(), MatCreateSubMatrix(), MatGetRowMax(), MatGetRowMaxAbs(), MatGetRowMin()
4641 @*/
4642 PetscErrorCode MatGetRowMinAbs(Mat mat,Vec v,PetscInt idx[])
4643 {
4644   PetscErrorCode ierr;
4645 
4646   PetscFunctionBegin;
4647   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4648   PetscValidType(mat,1);
4649   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4650   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4651   if (!mat->ops->getrowminabs) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4652   MatCheckPreallocated(mat,1);
4653   if (idx) {ierr = PetscMemzero(idx,mat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);}
4654 
4655   ierr = (*mat->ops->getrowminabs)(mat,v,idx);CHKERRQ(ierr);
4656   ierr = PetscObjectStateIncrease((PetscObject)v);CHKERRQ(ierr);
4657   PetscFunctionReturn(0);
4658 }
4659 
4660 /*@C
4661    MatGetRowMax - Gets the maximum value (of the real part) of each
4662         row of the matrix
4663 
4664    Logically Collective on Mat and Vec
4665 
4666    Input Parameters:
4667 .  mat - the matrix
4668 
4669    Output Parameter:
4670 +  v - the vector for storing the maximums
4671 -  idx - the indices of the column found for each row (optional)
4672 
4673    Level: intermediate
4674 
4675    Notes:
4676     The result of this call are the same as if one converted the matrix to dense format
4677       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4678 
4679     This code is only implemented for a couple of matrix formats.
4680 
4681    Concepts: matrices^getting row maximums
4682 
4683 .seealso: MatGetDiagonal(), MatCreateSubMatrices(), MatCreateSubMatrix(), MatGetRowMaxAbs(), MatGetRowMin()
4684 @*/
4685 PetscErrorCode MatGetRowMax(Mat mat,Vec v,PetscInt idx[])
4686 {
4687   PetscErrorCode ierr;
4688 
4689   PetscFunctionBegin;
4690   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4691   PetscValidType(mat,1);
4692   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4693   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4694   if (!mat->ops->getrowmax) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4695   MatCheckPreallocated(mat,1);
4696 
4697   ierr = (*mat->ops->getrowmax)(mat,v,idx);CHKERRQ(ierr);
4698   ierr = PetscObjectStateIncrease((PetscObject)v);CHKERRQ(ierr);
4699   PetscFunctionReturn(0);
4700 }
4701 
4702 /*@C
4703    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4704         row of the matrix
4705 
4706    Logically Collective on Mat and Vec
4707 
4708    Input Parameters:
4709 .  mat - the matrix
4710 
4711    Output Parameter:
4712 +  v - the vector for storing the maximums
4713 -  idx - the indices of the column found for each row (or NULL if not needed)
4714 
4715    Level: intermediate
4716 
4717    Notes:
4718     if a row is completely empty or has only 0.0 values then the idx[] value for that
4719     row is 0 (the first column).
4720 
4721     This code is only implemented for a couple of matrix formats.
4722 
4723    Concepts: matrices^getting row maximums
4724 
4725 .seealso: MatGetDiagonal(), MatCreateSubMatrices(), MatCreateSubMatrix(), MatGetRowMax(), MatGetRowMin()
4726 @*/
4727 PetscErrorCode MatGetRowMaxAbs(Mat mat,Vec v,PetscInt idx[])
4728 {
4729   PetscErrorCode ierr;
4730 
4731   PetscFunctionBegin;
4732   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4733   PetscValidType(mat,1);
4734   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4735   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4736   if (!mat->ops->getrowmaxabs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4737   MatCheckPreallocated(mat,1);
4738   if (idx) {ierr = PetscMemzero(idx,mat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);}
4739 
4740   ierr = (*mat->ops->getrowmaxabs)(mat,v,idx);CHKERRQ(ierr);
4741   ierr = PetscObjectStateIncrease((PetscObject)v);CHKERRQ(ierr);
4742   PetscFunctionReturn(0);
4743 }
4744 
4745 /*@
4746    MatGetRowSum - Gets the sum of each row of the matrix
4747 
4748    Logically or Neighborhood Collective on Mat and Vec
4749 
4750    Input Parameters:
4751 .  mat - the matrix
4752 
4753    Output Parameter:
4754 .  v - the vector for storing the sum of rows
4755 
4756    Level: intermediate
4757 
4758    Notes:
4759     This code is slow since it is not currently specialized for different formats
4760 
4761    Concepts: matrices^getting row sums
4762 
4763 .seealso: MatGetDiagonal(), MatCreateSubMatrices(), MatCreateSubMatrix(), MatGetRowMax(), MatGetRowMin()
4764 @*/
4765 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
4766 {
4767   Vec            ones;
4768   PetscErrorCode ierr;
4769 
4770   PetscFunctionBegin;
4771   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4772   PetscValidType(mat,1);
4773   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4774   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4775   MatCheckPreallocated(mat,1);
4776   ierr = MatCreateVecs(mat,&ones,NULL);CHKERRQ(ierr);
4777   ierr = VecSet(ones,1.);CHKERRQ(ierr);
4778   ierr = MatMult(mat,ones,v);CHKERRQ(ierr);
4779   ierr = VecDestroy(&ones);CHKERRQ(ierr);
4780   PetscFunctionReturn(0);
4781 }
4782 
4783 /*@
4784    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
4785 
4786    Collective on Mat
4787 
4788    Input Parameter:
4789 +  mat - the matrix to transpose
4790 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
4791 
4792    Output Parameters:
4793 .  B - the transpose
4794 
4795    Notes:
4796      If you use MAT_INPLACE_MATRIX then you must pass in &mat for B
4797 
4798      MAT_REUSE_MATRIX causes the B matrix from a previous call to this function with MAT_INITIAL_MATRIX to be used
4799 
4800      Consider using MatCreateTranspose() instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
4801 
4802    Level: intermediate
4803 
4804    Concepts: matrices^transposing
4805 
4806 .seealso: MatMultTranspose(), MatMultTransposeAdd(), MatIsTranspose(), MatReuse
4807 @*/
4808 PetscErrorCode MatTranspose(Mat mat,MatReuse reuse,Mat *B)
4809 {
4810   PetscErrorCode ierr;
4811 
4812   PetscFunctionBegin;
4813   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4814   PetscValidType(mat,1);
4815   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4816   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4817   if (!mat->ops->transpose) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
4818   if (reuse == MAT_INPLACE_MATRIX && mat != *B) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX requires last matrix to match first");
4819   if (reuse == MAT_REUSE_MATRIX && mat == *B) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Perhaps you mean MAT_INPLACE_MATRIX");
4820   MatCheckPreallocated(mat,1);
4821 
4822   ierr = PetscLogEventBegin(MAT_Transpose,mat,0,0,0);CHKERRQ(ierr);
4823   ierr = (*mat->ops->transpose)(mat,reuse,B);CHKERRQ(ierr);
4824   ierr = PetscLogEventEnd(MAT_Transpose,mat,0,0,0);CHKERRQ(ierr);
4825   if (B) {ierr = PetscObjectStateIncrease((PetscObject)*B);CHKERRQ(ierr);}
4826   PetscFunctionReturn(0);
4827 }
4828 
4829 /*@
4830    MatIsTranspose - Test whether a matrix is another one's transpose,
4831         or its own, in which case it tests symmetry.
4832 
4833    Collective on Mat
4834 
4835    Input Parameter:
4836 +  A - the matrix to test
4837 -  B - the matrix to test against, this can equal the first parameter
4838 
4839    Output Parameters:
4840 .  flg - the result
4841 
4842    Notes:
4843    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
4844    has a running time of the order of the number of nonzeros; the parallel
4845    test involves parallel copies of the block-offdiagonal parts of the matrix.
4846 
4847    Level: intermediate
4848 
4849    Concepts: matrices^transposing, matrix^symmetry
4850 
4851 .seealso: MatTranspose(), MatIsSymmetric(), MatIsHermitian()
4852 @*/
4853 PetscErrorCode MatIsTranspose(Mat A,Mat B,PetscReal tol,PetscBool  *flg)
4854 {
4855   PetscErrorCode ierr,(*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
4856 
4857   PetscFunctionBegin;
4858   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4859   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4860   PetscValidPointer(flg,3);
4861   ierr = PetscObjectQueryFunction((PetscObject)A,"MatIsTranspose_C",&f);CHKERRQ(ierr);
4862   ierr = PetscObjectQueryFunction((PetscObject)B,"MatIsTranspose_C",&g);CHKERRQ(ierr);
4863   *flg = PETSC_FALSE;
4864   if (f && g) {
4865     if (f == g) {
4866       ierr = (*f)(A,B,tol,flg);CHKERRQ(ierr);
4867     } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for symmetry test");
4868   } else {
4869     MatType mattype;
4870     if (!f) {
4871       ierr = MatGetType(A,&mattype);CHKERRQ(ierr);
4872     } else {
4873       ierr = MatGetType(B,&mattype);CHKERRQ(ierr);
4874     }
4875     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type <%s> does not support checking for transpose",mattype);
4876   }
4877   PetscFunctionReturn(0);
4878 }
4879 
4880 /*@
4881    MatHermitianTranspose - Computes an in-place or out-of-place transpose of a matrix in complex conjugate.
4882 
4883    Collective on Mat
4884 
4885    Input Parameter:
4886 +  mat - the matrix to transpose and complex conjugate
4887 -  reuse - MAT_INITIAL_MATRIX to create a new matrix, MAT_INPLACE_MATRIX to reuse the first argument to store the transpose
4888 
4889    Output Parameters:
4890 .  B - the Hermitian
4891 
4892    Level: intermediate
4893 
4894    Concepts: matrices^transposing, complex conjugatex
4895 
4896 .seealso: MatTranspose(), MatMultTranspose(), MatMultTransposeAdd(), MatIsTranspose(), MatReuse
4897 @*/
4898 PetscErrorCode MatHermitianTranspose(Mat mat,MatReuse reuse,Mat *B)
4899 {
4900   PetscErrorCode ierr;
4901 
4902   PetscFunctionBegin;
4903   ierr = MatTranspose(mat,reuse,B);CHKERRQ(ierr);
4904 #if defined(PETSC_USE_COMPLEX)
4905   ierr = MatConjugate(*B);CHKERRQ(ierr);
4906 #endif
4907   PetscFunctionReturn(0);
4908 }
4909 
4910 /*@
4911    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
4912 
4913    Collective on Mat
4914 
4915    Input Parameter:
4916 +  A - the matrix to test
4917 -  B - the matrix to test against, this can equal the first parameter
4918 
4919    Output Parameters:
4920 .  flg - the result
4921 
4922    Notes:
4923    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
4924    has a running time of the order of the number of nonzeros; the parallel
4925    test involves parallel copies of the block-offdiagonal parts of the matrix.
4926 
4927    Level: intermediate
4928 
4929    Concepts: matrices^transposing, matrix^symmetry
4930 
4931 .seealso: MatTranspose(), MatIsSymmetric(), MatIsHermitian(), MatIsTranspose()
4932 @*/
4933 PetscErrorCode MatIsHermitianTranspose(Mat A,Mat B,PetscReal tol,PetscBool  *flg)
4934 {
4935   PetscErrorCode ierr,(*f)(Mat,Mat,PetscReal,PetscBool*),(*g)(Mat,Mat,PetscReal,PetscBool*);
4936 
4937   PetscFunctionBegin;
4938   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4939   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4940   PetscValidPointer(flg,3);
4941   ierr = PetscObjectQueryFunction((PetscObject)A,"MatIsHermitianTranspose_C",&f);CHKERRQ(ierr);
4942   ierr = PetscObjectQueryFunction((PetscObject)B,"MatIsHermitianTranspose_C",&g);CHKERRQ(ierr);
4943   if (f && g) {
4944     if (f==g) {
4945       ierr = (*f)(A,B,tol,flg);CHKERRQ(ierr);
4946     } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_NOTSAMETYPE,"Matrices do not have the same comparator for Hermitian test");
4947   }
4948   PetscFunctionReturn(0);
4949 }
4950 
4951 /*@
4952    MatPermute - Creates a new matrix with rows and columns permuted from the
4953    original.
4954 
4955    Collective on Mat
4956 
4957    Input Parameters:
4958 +  mat - the matrix to permute
4959 .  row - row permutation, each processor supplies only the permutation for its rows
4960 -  col - column permutation, each processor supplies only the permutation for its columns
4961 
4962    Output Parameters:
4963 .  B - the permuted matrix
4964 
4965    Level: advanced
4966 
4967    Note:
4968    The index sets map from row/col of permuted matrix to row/col of original matrix.
4969    The index sets should be on the same communicator as Mat and have the same local sizes.
4970 
4971    Concepts: matrices^permuting
4972 
4973 .seealso: MatGetOrdering(), ISAllGather()
4974 
4975 @*/
4976 PetscErrorCode MatPermute(Mat mat,IS row,IS col,Mat *B)
4977 {
4978   PetscErrorCode ierr;
4979 
4980   PetscFunctionBegin;
4981   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4982   PetscValidType(mat,1);
4983   PetscValidHeaderSpecific(row,IS_CLASSID,2);
4984   PetscValidHeaderSpecific(col,IS_CLASSID,3);
4985   PetscValidPointer(B,4);
4986   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4987   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4988   if (!mat->ops->permute) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatPermute not available for Mat type %s",((PetscObject)mat)->type_name);
4989   MatCheckPreallocated(mat,1);
4990 
4991   ierr = (*mat->ops->permute)(mat,row,col,B);CHKERRQ(ierr);
4992   ierr = PetscObjectStateIncrease((PetscObject)*B);CHKERRQ(ierr);
4993   PetscFunctionReturn(0);
4994 }
4995 
4996 /*@
4997    MatEqual - Compares two matrices.
4998 
4999    Collective on Mat
5000 
5001    Input Parameters:
5002 +  A - the first matrix
5003 -  B - the second matrix
5004 
5005    Output Parameter:
5006 .  flg - PETSC_TRUE if the matrices are equal; PETSC_FALSE otherwise.
5007 
5008    Level: intermediate
5009 
5010    Concepts: matrices^equality between
5011 @*/
5012 PetscErrorCode MatEqual(Mat A,Mat B,PetscBool  *flg)
5013 {
5014   PetscErrorCode ierr;
5015 
5016   PetscFunctionBegin;
5017   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
5018   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
5019   PetscValidType(A,1);
5020   PetscValidType(B,2);
5021   PetscValidIntPointer(flg,3);
5022   PetscCheckSameComm(A,1,B,2);
5023   MatCheckPreallocated(B,2);
5024   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5025   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5026   if (A->rmap->N != B->rmap->N || A->cmap->N != B->cmap->N) SETERRQ4(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Mat A,Mat B: global dim %D %D %D %D",A->rmap->N,B->rmap->N,A->cmap->N,B->cmap->N);
5027   if (!A->ops->equal) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)A)->type_name);
5028   if (!B->ops->equal) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type %s",((PetscObject)B)->type_name);
5029   if (A->ops->equal != B->ops->equal) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"A is type: %s\nB is type: %s",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
5030   MatCheckPreallocated(A,1);
5031 
5032   ierr = (*A->ops->equal)(A,B,flg);CHKERRQ(ierr);
5033   PetscFunctionReturn(0);
5034 }
5035 
5036 /*@C
5037    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5038    matrices that are stored as vectors.  Either of the two scaling
5039    matrices can be NULL.
5040 
5041    Collective on Mat
5042 
5043    Input Parameters:
5044 +  mat - the matrix to be scaled
5045 .  l - the left scaling vector (or NULL)
5046 -  r - the right scaling vector (or NULL)
5047 
5048    Notes:
5049    MatDiagonalScale() computes A = LAR, where
5050    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5051    The L scales the rows of the matrix, the R scales the columns of the matrix.
5052 
5053    Level: intermediate
5054 
5055    Concepts: matrices^diagonal scaling
5056    Concepts: diagonal scaling of matrices
5057 
5058 .seealso: MatScale(), MatShift(), MatDiagonalSet()
5059 @*/
5060 PetscErrorCode MatDiagonalScale(Mat mat,Vec l,Vec r)
5061 {
5062   PetscErrorCode ierr;
5063 
5064   PetscFunctionBegin;
5065   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5066   PetscValidType(mat,1);
5067   if (!mat->ops->diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5068   if (l) {PetscValidHeaderSpecific(l,VEC_CLASSID,2);PetscCheckSameComm(mat,1,l,2);}
5069   if (r) {PetscValidHeaderSpecific(r,VEC_CLASSID,3);PetscCheckSameComm(mat,1,r,3);}
5070   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5071   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5072   MatCheckPreallocated(mat,1);
5073 
5074   ierr = PetscLogEventBegin(MAT_Scale,mat,0,0,0);CHKERRQ(ierr);
5075   ierr = (*mat->ops->diagonalscale)(mat,l,r);CHKERRQ(ierr);
5076   ierr = PetscLogEventEnd(MAT_Scale,mat,0,0,0);CHKERRQ(ierr);
5077   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
5078 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
5079   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
5080     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
5081   }
5082 #endif
5083   PetscFunctionReturn(0);
5084 }
5085 
5086 /*@
5087     MatScale - Scales all elements of a matrix by a given number.
5088 
5089     Logically Collective on Mat
5090 
5091     Input Parameters:
5092 +   mat - the matrix to be scaled
5093 -   a  - the scaling value
5094 
5095     Output Parameter:
5096 .   mat - the scaled matrix
5097 
5098     Level: intermediate
5099 
5100     Concepts: matrices^scaling all entries
5101 
5102 .seealso: MatDiagonalScale()
5103 @*/
5104 PetscErrorCode MatScale(Mat mat,PetscScalar a)
5105 {
5106   PetscErrorCode ierr;
5107 
5108   PetscFunctionBegin;
5109   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5110   PetscValidType(mat,1);
5111   if (a != (PetscScalar)1.0 && !mat->ops->scale) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5112   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5113   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5114   PetscValidLogicalCollectiveScalar(mat,a,2);
5115   MatCheckPreallocated(mat,1);
5116 
5117   ierr = PetscLogEventBegin(MAT_Scale,mat,0,0,0);CHKERRQ(ierr);
5118   if (a != (PetscScalar)1.0) {
5119     ierr = (*mat->ops->scale)(mat,a);CHKERRQ(ierr);
5120     ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
5121 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
5122     if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
5123       mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
5124     }
5125 #endif
5126   }
5127   ierr = PetscLogEventEnd(MAT_Scale,mat,0,0,0);CHKERRQ(ierr);
5128   PetscFunctionReturn(0);
5129 }
5130 
5131 static PetscErrorCode MatNorm_Basic(Mat A,NormType type,PetscReal *nrm)
5132 {
5133   PetscErrorCode ierr;
5134 
5135   PetscFunctionBegin;
5136   if (type == NORM_1 || type == NORM_INFINITY) {
5137     Vec l,r;
5138 
5139     ierr = MatCreateVecs(A,&r,&l);CHKERRQ(ierr);
5140     if (type == NORM_INFINITY) {
5141       ierr = VecSet(r,1.);CHKERRQ(ierr);
5142       ierr = MatMult(A,r,l);CHKERRQ(ierr);
5143       ierr = VecNorm(l,NORM_INFINITY,nrm);CHKERRQ(ierr);
5144     } else {
5145       ierr = VecSet(l,1.);CHKERRQ(ierr);
5146       ierr = MatMultTranspose(A,l,r);CHKERRQ(ierr);
5147       ierr = VecNorm(r,NORM_INFINITY,nrm);CHKERRQ(ierr);
5148     }
5149     ierr = VecDestroy(&l);CHKERRQ(ierr);
5150     ierr = VecDestroy(&r);CHKERRQ(ierr);
5151   } else SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Matrix class %s, norm type %d",((PetscObject)A)->type_name,type);
5152   PetscFunctionReturn(0);
5153 }
5154 
5155 /*@
5156    MatNorm - Calculates various norms of a matrix.
5157 
5158    Collective on Mat
5159 
5160    Input Parameters:
5161 +  mat - the matrix
5162 -  type - the type of norm, NORM_1, NORM_FROBENIUS, NORM_INFINITY
5163 
5164    Output Parameters:
5165 .  nrm - the resulting norm
5166 
5167    Level: intermediate
5168 
5169    Concepts: matrices^norm
5170    Concepts: norm^of matrix
5171 @*/
5172 PetscErrorCode MatNorm(Mat mat,NormType type,PetscReal *nrm)
5173 {
5174   PetscErrorCode ierr;
5175 
5176   PetscFunctionBegin;
5177   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5178   PetscValidType(mat,1);
5179   PetscValidLogicalCollectiveEnum(mat,type,2);
5180   PetscValidScalarPointer(nrm,3);
5181 
5182   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5183   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5184   MatCheckPreallocated(mat,1);
5185 
5186   if (!mat->ops->norm) {
5187     ierr = MatNorm_Basic(mat,type,nrm);CHKERRQ(ierr);
5188   } else {
5189     ierr = (*mat->ops->norm)(mat,type,nrm);CHKERRQ(ierr);
5190   }
5191   PetscFunctionReturn(0);
5192 }
5193 
5194 /*
5195      This variable is used to prevent counting of MatAssemblyBegin() that
5196    are called from within a MatAssemblyEnd().
5197 */
5198 static PetscInt MatAssemblyEnd_InUse = 0;
5199 /*@
5200    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5201    be called after completing all calls to MatSetValues().
5202 
5203    Collective on Mat
5204 
5205    Input Parameters:
5206 +  mat - the matrix
5207 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5208 
5209    Notes:
5210    MatSetValues() generally caches the values.  The matrix is ready to
5211    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5212    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5213    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5214    using the matrix.
5215 
5216    ALL processes that share a matrix MUST call MatAssemblyBegin() and MatAssemblyEnd() the SAME NUMBER of times, and each time with the
5217    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
5218    a global collective operation requring all processes that share the matrix.
5219 
5220    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5221    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5222    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5223 
5224    Level: beginner
5225 
5226    Concepts: matrices^assembling
5227 
5228 .seealso: MatAssemblyEnd(), MatSetValues(), MatAssembled()
5229 @*/
5230 PetscErrorCode MatAssemblyBegin(Mat mat,MatAssemblyType type)
5231 {
5232   PetscErrorCode ierr;
5233 
5234   PetscFunctionBegin;
5235   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5236   PetscValidType(mat,1);
5237   MatCheckPreallocated(mat,1);
5238   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5239   if (mat->assembled) {
5240     mat->was_assembled = PETSC_TRUE;
5241     mat->assembled     = PETSC_FALSE;
5242   }
5243   if (!MatAssemblyEnd_InUse) {
5244     ierr = PetscLogEventBegin(MAT_AssemblyBegin,mat,0,0,0);CHKERRQ(ierr);
5245     if (mat->ops->assemblybegin) {ierr = (*mat->ops->assemblybegin)(mat,type);CHKERRQ(ierr);}
5246     ierr = PetscLogEventEnd(MAT_AssemblyBegin,mat,0,0,0);CHKERRQ(ierr);
5247   } else if (mat->ops->assemblybegin) {
5248     ierr = (*mat->ops->assemblybegin)(mat,type);CHKERRQ(ierr);
5249   }
5250   PetscFunctionReturn(0);
5251 }
5252 
5253 /*@
5254    MatAssembled - Indicates if a matrix has been assembled and is ready for
5255      use; for example, in matrix-vector product.
5256 
5257    Not Collective
5258 
5259    Input Parameter:
5260 .  mat - the matrix
5261 
5262    Output Parameter:
5263 .  assembled - PETSC_TRUE or PETSC_FALSE
5264 
5265    Level: advanced
5266 
5267    Concepts: matrices^assembled?
5268 
5269 .seealso: MatAssemblyEnd(), MatSetValues(), MatAssemblyBegin()
5270 @*/
5271 PetscErrorCode MatAssembled(Mat mat,PetscBool  *assembled)
5272 {
5273   PetscFunctionBegin;
5274   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5275   PetscValidType(mat,1);
5276   PetscValidPointer(assembled,2);
5277   *assembled = mat->assembled;
5278   PetscFunctionReturn(0);
5279 }
5280 
5281 /*@
5282    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5283    be called after MatAssemblyBegin().
5284 
5285    Collective on Mat
5286 
5287    Input Parameters:
5288 +  mat - the matrix
5289 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5290 
5291    Options Database Keys:
5292 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatEndAssembly()
5293 .  -mat_view ::ascii_info_detail - Prints more detailed info
5294 .  -mat_view - Prints matrix in ASCII format
5295 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5296 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
5297 .  -display <name> - Sets display name (default is host)
5298 .  -draw_pause <sec> - Sets number of seconds to pause after display
5299 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab )
5300 .  -viewer_socket_machine <machine> - Machine to use for socket
5301 .  -viewer_socket_port <port> - Port number to use for socket
5302 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5303 
5304    Notes:
5305    MatSetValues() generally caches the values.  The matrix is ready to
5306    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5307    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5308    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5309    using the matrix.
5310 
5311    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5312    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5313    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5314 
5315    Level: beginner
5316 
5317 .seealso: MatAssemblyBegin(), MatSetValues(), PetscDrawOpenX(), PetscDrawCreate(), MatView(), MatAssembled(), PetscViewerSocketOpen()
5318 @*/
5319 PetscErrorCode MatAssemblyEnd(Mat mat,MatAssemblyType type)
5320 {
5321   PetscErrorCode  ierr;
5322   static PetscInt inassm = 0;
5323   PetscBool       flg    = PETSC_FALSE;
5324 
5325   PetscFunctionBegin;
5326   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5327   PetscValidType(mat,1);
5328 
5329   inassm++;
5330   MatAssemblyEnd_InUse++;
5331   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5332     ierr = PetscLogEventBegin(MAT_AssemblyEnd,mat,0,0,0);CHKERRQ(ierr);
5333     if (mat->ops->assemblyend) {
5334       ierr = (*mat->ops->assemblyend)(mat,type);CHKERRQ(ierr);
5335     }
5336     ierr = PetscLogEventEnd(MAT_AssemblyEnd,mat,0,0,0);CHKERRQ(ierr);
5337   } else if (mat->ops->assemblyend) {
5338     ierr = (*mat->ops->assemblyend)(mat,type);CHKERRQ(ierr);
5339   }
5340 
5341   /* Flush assembly is not a true assembly */
5342   if (type != MAT_FLUSH_ASSEMBLY) {
5343     mat->assembled = PETSC_TRUE; mat->num_ass++;
5344   }
5345   mat->insertmode = NOT_SET_VALUES;
5346   MatAssemblyEnd_InUse--;
5347   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
5348   if (!mat->symmetric_eternal) {
5349     mat->symmetric_set              = PETSC_FALSE;
5350     mat->hermitian_set              = PETSC_FALSE;
5351     mat->structurally_symmetric_set = PETSC_FALSE;
5352   }
5353 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
5354   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
5355     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
5356   }
5357 #endif
5358   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5359     ierr = MatViewFromOptions(mat,NULL,"-mat_view");CHKERRQ(ierr);
5360 
5361     if (mat->checksymmetryonassembly) {
5362       ierr = MatIsSymmetric(mat,mat->checksymmetrytol,&flg);CHKERRQ(ierr);
5363       if (flg) {
5364         ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is symmetric (tolerance %g)\n",(double)mat->checksymmetrytol);CHKERRQ(ierr);
5365       } else {
5366         ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Matrix is not symmetric (tolerance %g)\n",(double)mat->checksymmetrytol);CHKERRQ(ierr);
5367       }
5368     }
5369     if (mat->nullsp && mat->checknullspaceonassembly) {
5370       ierr = MatNullSpaceTest(mat->nullsp,mat,NULL);CHKERRQ(ierr);
5371     }
5372   }
5373   inassm--;
5374   PetscFunctionReturn(0);
5375 }
5376 
5377 /*@
5378    MatSetOption - Sets a parameter option for a matrix. Some options
5379    may be specific to certain storage formats.  Some options
5380    determine how values will be inserted (or added). Sorted,
5381    row-oriented input will generally assemble the fastest. The default
5382    is row-oriented.
5383 
5384    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5385 
5386    Input Parameters:
5387 +  mat - the matrix
5388 .  option - the option, one of those listed below (and possibly others),
5389 -  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5390 
5391   Options Describing Matrix Structure:
5392 +    MAT_SPD - symmetric positive definite
5393 .    MAT_SYMMETRIC - symmetric in terms of both structure and value
5394 .    MAT_HERMITIAN - transpose is the complex conjugation
5395 .    MAT_STRUCTURALLY_SYMMETRIC - symmetric nonzero structure
5396 -    MAT_SYMMETRY_ETERNAL - if you would like the symmetry/Hermitian flag
5397                             you set to be kept with all future use of the matrix
5398                             including after MatAssemblyBegin/End() which could
5399                             potentially change the symmetry structure, i.e. you
5400                             KNOW the matrix will ALWAYS have the property you set.
5401 
5402 
5403    Options For Use with MatSetValues():
5404    Insert a logically dense subblock, which can be
5405 .    MAT_ROW_ORIENTED - row-oriented (default)
5406 
5407    Note these options reflect the data you pass in with MatSetValues(); it has
5408    nothing to do with how the data is stored internally in the matrix
5409    data structure.
5410 
5411    When (re)assembling a matrix, we can restrict the input for
5412    efficiency/debugging purposes.  These options include:
5413 +    MAT_NEW_NONZERO_LOCATIONS - additional insertions will be allowed if they generate a new nonzero (slow)
5414 .    MAT_NEW_DIAGONALS - new diagonals will be allowed (for block diagonal format only)
5415 .    MAT_IGNORE_OFF_PROC_ENTRIES - drops off-processor entries
5416 .    MAT_NEW_NONZERO_LOCATION_ERR - generates an error for new matrix entry
5417 .    MAT_USE_HASH_TABLE - uses a hash table to speed up matrix assembly
5418 .    MAT_NO_OFF_PROC_ENTRIES - you know each process will only set values for its own rows, will generate an error if
5419         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5420         performance for very large process counts.
5421 -    MAT_SUBSET_OFF_PROC_ENTRIES - you know that the first assembly after setting this flag will set a superset
5422         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5423         functions, instead sending only neighbor messages.
5424 
5425    Notes:
5426    Except for MAT_UNUSED_NONZERO_LOCATION_ERR and  MAT_ROW_ORIENTED all processes that share the matrix must pass the same value in flg!
5427 
5428    Some options are relevant only for particular matrix types and
5429    are thus ignored by others.  Other options are not supported by
5430    certain matrix types and will generate an error message if set.
5431 
5432    If using a Fortran 77 module to compute a matrix, one may need to
5433    use the column-oriented option (or convert to the row-oriented
5434    format).
5435 
5436    MAT_NEW_NONZERO_LOCATIONS set to PETSC_FALSE indicates that any add or insertion
5437    that would generate a new entry in the nonzero structure is instead
5438    ignored.  Thus, if memory has not alredy been allocated for this particular
5439    data, then the insertion is ignored. For dense matrices, in which
5440    the entire array is allocated, no entries are ever ignored.
5441    Set after the first MatAssemblyEnd(). If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5442 
5443    MAT_NEW_NONZERO_LOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5444    that would generate a new entry in the nonzero structure instead produces
5445    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
5446 
5447    MAT_NEW_NONZERO_ALLOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5448    that would generate a new entry that has not been preallocated will
5449    instead produce an error. (Currently supported for AIJ and BAIJ formats
5450    only.) This is a useful flag when debugging matrix memory preallocation.
5451    If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5452 
5453    MAT_IGNORE_OFF_PROC_ENTRIES set to PETSC_TRUE indicates entries destined for
5454    other processors should be dropped, rather than stashed.
5455    This is useful if you know that the "owning" processor is also
5456    always generating the correct matrix entries, so that PETSc need
5457    not transfer duplicate entries generated on another processor.
5458 
5459    MAT_USE_HASH_TABLE indicates that a hash table be used to improve the
5460    searches during matrix assembly. When this flag is set, the hash table
5461    is created during the first Matrix Assembly. This hash table is
5462    used the next time through, during MatSetVaules()/MatSetVaulesBlocked()
5463    to improve the searching of indices. MAT_NEW_NONZERO_LOCATIONS flag
5464    should be used with MAT_USE_HASH_TABLE flag. This option is currently
5465    supported by MATMPIBAIJ format only.
5466 
5467    MAT_KEEP_NONZERO_PATTERN indicates when MatZeroRows() is called the zeroed entries
5468    are kept in the nonzero structure
5469 
5470    MAT_IGNORE_ZERO_ENTRIES - for AIJ/IS matrices this will stop zero values from creating
5471    a zero location in the matrix
5472 
5473    MAT_USE_INODES - indicates using inode version of the code - works with AIJ matrix types
5474 
5475    MAT_NO_OFF_PROC_ZERO_ROWS - you know each process will only zero its own rows. This avoids all reductions in the
5476         zero row routines and thus improves performance for very large process counts.
5477 
5478    MAT_IGNORE_LOWER_TRIANGULAR - For SBAIJ matrices will ignore any insertions you make in the lower triangular
5479         part of the matrix (since they should match the upper triangular part).
5480 
5481    Notes:
5482     Can only be called after MatSetSizes() and MatSetType() have been set.
5483 
5484    Level: intermediate
5485 
5486    Concepts: matrices^setting options
5487 
5488 .seealso:  MatOption, Mat
5489 
5490 @*/
5491 PetscErrorCode MatSetOption(Mat mat,MatOption op,PetscBool flg)
5492 {
5493   PetscErrorCode ierr;
5494 
5495   PetscFunctionBegin;
5496   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5497   PetscValidType(mat,1);
5498   if (op > 0) {
5499     PetscValidLogicalCollectiveEnum(mat,op,2);
5500     PetscValidLogicalCollectiveBool(mat,flg,3);
5501   }
5502 
5503   if (((int) op) <= MAT_OPTION_MIN || ((int) op) >= MAT_OPTION_MAX) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Options %d is out of range",(int)op);
5504   if (!((PetscObject)mat)->type_name) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_TYPENOTSET,"Cannot set options until type and size have been set, see MatSetType() and MatSetSizes()");
5505 
5506   switch (op) {
5507   case MAT_NO_OFF_PROC_ENTRIES:
5508     mat->nooffprocentries = flg;
5509     PetscFunctionReturn(0);
5510     break;
5511   case MAT_SUBSET_OFF_PROC_ENTRIES:
5512     mat->subsetoffprocentries = flg;
5513     PetscFunctionReturn(0);
5514   case MAT_NO_OFF_PROC_ZERO_ROWS:
5515     mat->nooffproczerorows = flg;
5516     PetscFunctionReturn(0);
5517     break;
5518   case MAT_SPD:
5519     mat->spd_set = PETSC_TRUE;
5520     mat->spd     = flg;
5521     if (flg) {
5522       mat->symmetric                  = PETSC_TRUE;
5523       mat->structurally_symmetric     = PETSC_TRUE;
5524       mat->symmetric_set              = PETSC_TRUE;
5525       mat->structurally_symmetric_set = PETSC_TRUE;
5526     }
5527     break;
5528   case MAT_SYMMETRIC:
5529     mat->symmetric = flg;
5530     if (flg) mat->structurally_symmetric = PETSC_TRUE;
5531     mat->symmetric_set              = PETSC_TRUE;
5532     mat->structurally_symmetric_set = flg;
5533 #if !defined(PETSC_USE_COMPLEX)
5534     mat->hermitian     = flg;
5535     mat->hermitian_set = PETSC_TRUE;
5536 #endif
5537     break;
5538   case MAT_HERMITIAN:
5539     mat->hermitian = flg;
5540     if (flg) mat->structurally_symmetric = PETSC_TRUE;
5541     mat->hermitian_set              = PETSC_TRUE;
5542     mat->structurally_symmetric_set = flg;
5543 #if !defined(PETSC_USE_COMPLEX)
5544     mat->symmetric     = flg;
5545     mat->symmetric_set = PETSC_TRUE;
5546 #endif
5547     break;
5548   case MAT_STRUCTURALLY_SYMMETRIC:
5549     mat->structurally_symmetric     = flg;
5550     mat->structurally_symmetric_set = PETSC_TRUE;
5551     break;
5552   case MAT_SYMMETRY_ETERNAL:
5553     mat->symmetric_eternal = flg;
5554     break;
5555   case MAT_STRUCTURE_ONLY:
5556     mat->structure_only = flg;
5557     break;
5558   default:
5559     break;
5560   }
5561   if (mat->ops->setoption) {
5562     ierr = (*mat->ops->setoption)(mat,op,flg);CHKERRQ(ierr);
5563   }
5564   PetscFunctionReturn(0);
5565 }
5566 
5567 /*@
5568    MatGetOption - Gets a parameter option that has been set for a matrix.
5569 
5570    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5571 
5572    Input Parameters:
5573 +  mat - the matrix
5574 -  option - the option, this only responds to certain options, check the code for which ones
5575 
5576    Output Parameter:
5577 .  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5578 
5579     Notes:
5580     Can only be called after MatSetSizes() and MatSetType() have been set.
5581 
5582    Level: intermediate
5583 
5584    Concepts: matrices^setting options
5585 
5586 .seealso:  MatOption, MatSetOption()
5587 
5588 @*/
5589 PetscErrorCode MatGetOption(Mat mat,MatOption op,PetscBool *flg)
5590 {
5591   PetscFunctionBegin;
5592   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5593   PetscValidType(mat,1);
5594 
5595   if (((int) op) <= MAT_OPTION_MIN || ((int) op) >= MAT_OPTION_MAX) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Options %d is out of range",(int)op);
5596   if (!((PetscObject)mat)->type_name) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_TYPENOTSET,"Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()");
5597 
5598   switch (op) {
5599   case MAT_NO_OFF_PROC_ENTRIES:
5600     *flg = mat->nooffprocentries;
5601     break;
5602   case MAT_NO_OFF_PROC_ZERO_ROWS:
5603     *flg = mat->nooffproczerorows;
5604     break;
5605   case MAT_SYMMETRIC:
5606     *flg = mat->symmetric;
5607     break;
5608   case MAT_HERMITIAN:
5609     *flg = mat->hermitian;
5610     break;
5611   case MAT_STRUCTURALLY_SYMMETRIC:
5612     *flg = mat->structurally_symmetric;
5613     break;
5614   case MAT_SYMMETRY_ETERNAL:
5615     *flg = mat->symmetric_eternal;
5616     break;
5617   case MAT_SPD:
5618     *flg = mat->spd;
5619     break;
5620   default:
5621     break;
5622   }
5623   PetscFunctionReturn(0);
5624 }
5625 
5626 /*@
5627    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5628    this routine retains the old nonzero structure.
5629 
5630    Logically Collective on Mat
5631 
5632    Input Parameters:
5633 .  mat - the matrix
5634 
5635    Level: intermediate
5636 
5637    Notes:
5638     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.
5639    See the Performance chapter of the users manual for information on preallocating matrices.
5640 
5641    Concepts: matrices^zeroing
5642 
5643 .seealso: MatZeroRows()
5644 @*/
5645 PetscErrorCode MatZeroEntries(Mat mat)
5646 {
5647   PetscErrorCode ierr;
5648 
5649   PetscFunctionBegin;
5650   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5651   PetscValidType(mat,1);
5652   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5653   if (mat->insertmode != NOT_SET_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for matrices where you have set values but not yet assembled");
5654   if (!mat->ops->zeroentries) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5655   MatCheckPreallocated(mat,1);
5656 
5657   ierr = PetscLogEventBegin(MAT_ZeroEntries,mat,0,0,0);CHKERRQ(ierr);
5658   ierr = (*mat->ops->zeroentries)(mat);CHKERRQ(ierr);
5659   ierr = PetscLogEventEnd(MAT_ZeroEntries,mat,0,0,0);CHKERRQ(ierr);
5660   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
5661 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
5662   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
5663     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
5664   }
5665 #endif
5666   PetscFunctionReturn(0);
5667 }
5668 
5669 /*@C
5670    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5671    of a set of rows and columns of a matrix.
5672 
5673    Collective on Mat
5674 
5675    Input Parameters:
5676 +  mat - the matrix
5677 .  numRows - the number of rows to remove
5678 .  rows - the global row indices
5679 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5680 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5681 -  b - optional vector of right hand side, that will be adjusted by provided solution
5682 
5683    Notes:
5684    This does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5685 
5686    The user can set a value in the diagonal entry (or for the AIJ and
5687    row formats can optionally remove the main diagonal entry from the
5688    nonzero structure as well, by passing 0.0 as the final argument).
5689 
5690    For the parallel case, all processes that share the matrix (i.e.,
5691    those in the communicator used for matrix creation) MUST call this
5692    routine, regardless of whether any rows being zeroed are owned by
5693    them.
5694 
5695    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5696    list only rows local to itself).
5697 
5698    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
5699 
5700    Level: intermediate
5701 
5702    Concepts: matrices^zeroing rows
5703 
5704 .seealso: MatZeroRowsIS(), MatZeroRows(), MatZeroRowsLocalIS(), MatZeroRowsStencil(), MatZeroEntries(), MatZeroRowsLocal(), MatSetOption(),
5705           MatZeroRowsColumnsLocal(), MatZeroRowsColumnsLocalIS(), MatZeroRowsColumnsIS(), MatZeroRowsColumnsStencil()
5706 @*/
5707 PetscErrorCode MatZeroRowsColumns(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
5708 {
5709   PetscErrorCode ierr;
5710 
5711   PetscFunctionBegin;
5712   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5713   PetscValidType(mat,1);
5714   if (numRows) PetscValidIntPointer(rows,3);
5715   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5716   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5717   if (!mat->ops->zerorowscolumns) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5718   MatCheckPreallocated(mat,1);
5719 
5720   ierr = (*mat->ops->zerorowscolumns)(mat,numRows,rows,diag,x,b);CHKERRQ(ierr);
5721   ierr = MatViewFromOptions(mat,NULL,"-mat_view");CHKERRQ(ierr);
5722   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
5723 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
5724   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
5725     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
5726   }
5727 #endif
5728   PetscFunctionReturn(0);
5729 }
5730 
5731 /*@C
5732    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5733    of a set of rows and columns of a matrix.
5734 
5735    Collective on Mat
5736 
5737    Input Parameters:
5738 +  mat - the matrix
5739 .  is - the rows to zero
5740 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5741 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5742 -  b - optional vector of right hand side, that will be adjusted by provided solution
5743 
5744    Notes:
5745    This does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5746 
5747    The user can set a value in the diagonal entry (or for the AIJ and
5748    row formats can optionally remove the main diagonal entry from the
5749    nonzero structure as well, by passing 0.0 as the final argument).
5750 
5751    For the parallel case, all processes that share the matrix (i.e.,
5752    those in the communicator used for matrix creation) MUST call this
5753    routine, regardless of whether any rows being zeroed are owned by
5754    them.
5755 
5756    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5757    list only rows local to itself).
5758 
5759    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
5760 
5761    Level: intermediate
5762 
5763    Concepts: matrices^zeroing rows
5764 
5765 .seealso: MatZeroRowsIS(), MatZeroRowsColumns(), MatZeroRowsLocalIS(), MatZeroRowsStencil(), MatZeroEntries(), MatZeroRowsLocal(), MatSetOption(),
5766           MatZeroRowsColumnsLocal(), MatZeroRowsColumnsLocalIS(), MatZeroRows(), MatZeroRowsColumnsStencil()
5767 @*/
5768 PetscErrorCode MatZeroRowsColumnsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
5769 {
5770   PetscErrorCode ierr;
5771   PetscInt       numRows;
5772   const PetscInt *rows;
5773 
5774   PetscFunctionBegin;
5775   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5776   PetscValidHeaderSpecific(is,IS_CLASSID,2);
5777   PetscValidType(mat,1);
5778   PetscValidType(is,2);
5779   ierr = ISGetLocalSize(is,&numRows);CHKERRQ(ierr);
5780   ierr = ISGetIndices(is,&rows);CHKERRQ(ierr);
5781   ierr = MatZeroRowsColumns(mat,numRows,rows,diag,x,b);CHKERRQ(ierr);
5782   ierr = ISRestoreIndices(is,&rows);CHKERRQ(ierr);
5783   PetscFunctionReturn(0);
5784 }
5785 
5786 /*@C
5787    MatZeroRows - Zeros all entries (except possibly the main diagonal)
5788    of a set of rows of a matrix.
5789 
5790    Collective on Mat
5791 
5792    Input Parameters:
5793 +  mat - the matrix
5794 .  numRows - the number of rows to remove
5795 .  rows - the global row indices
5796 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5797 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5798 -  b - optional vector of right hand side, that will be adjusted by provided solution
5799 
5800    Notes:
5801    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
5802    but does not release memory.  For the dense and block diagonal
5803    formats this does not alter the nonzero structure.
5804 
5805    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
5806    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
5807    merely zeroed.
5808 
5809    The user can set a value in the diagonal entry (or for the AIJ and
5810    row formats can optionally remove the main diagonal entry from the
5811    nonzero structure as well, by passing 0.0 as the final argument).
5812 
5813    For the parallel case, all processes that share the matrix (i.e.,
5814    those in the communicator used for matrix creation) MUST call this
5815    routine, regardless of whether any rows being zeroed are owned by
5816    them.
5817 
5818    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5819    list only rows local to itself).
5820 
5821    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
5822    owns that are to be zeroed. This saves a global synchronization in the implementation.
5823 
5824    Level: intermediate
5825 
5826    Concepts: matrices^zeroing rows
5827 
5828 .seealso: MatZeroRowsIS(), MatZeroRowsColumns(), MatZeroRowsLocalIS(), MatZeroRowsStencil(), MatZeroEntries(), MatZeroRowsLocal(), MatSetOption(),
5829           MatZeroRowsColumnsLocal(), MatZeroRowsColumnsLocalIS(), MatZeroRowsColumnsIS(), MatZeroRowsColumnsStencil()
5830 @*/
5831 PetscErrorCode MatZeroRows(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
5832 {
5833   PetscErrorCode ierr;
5834 
5835   PetscFunctionBegin;
5836   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5837   PetscValidType(mat,1);
5838   if (numRows) PetscValidIntPointer(rows,3);
5839   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
5840   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
5841   if (!mat->ops->zerorows) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
5842   MatCheckPreallocated(mat,1);
5843 
5844   ierr = (*mat->ops->zerorows)(mat,numRows,rows,diag,x,b);CHKERRQ(ierr);
5845   ierr = MatViewFromOptions(mat,NULL,"-mat_view");CHKERRQ(ierr);
5846   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
5847 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
5848   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
5849     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
5850   }
5851 #endif
5852   PetscFunctionReturn(0);
5853 }
5854 
5855 /*@C
5856    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
5857    of a set of rows of a matrix.
5858 
5859    Collective on Mat
5860 
5861    Input Parameters:
5862 +  mat - the matrix
5863 .  is - index set of rows to remove
5864 .  diag - value put in all diagonals of eliminated rows
5865 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5866 -  b - optional vector of right hand side, that will be adjusted by provided solution
5867 
5868    Notes:
5869    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
5870    but does not release memory.  For the dense and block diagonal
5871    formats this does not alter the nonzero structure.
5872 
5873    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
5874    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
5875    merely zeroed.
5876 
5877    The user can set a value in the diagonal entry (or for the AIJ and
5878    row formats can optionally remove the main diagonal entry from the
5879    nonzero structure as well, by passing 0.0 as the final argument).
5880 
5881    For the parallel case, all processes that share the matrix (i.e.,
5882    those in the communicator used for matrix creation) MUST call this
5883    routine, regardless of whether any rows being zeroed are owned by
5884    them.
5885 
5886    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5887    list only rows local to itself).
5888 
5889    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
5890    owns that are to be zeroed. This saves a global synchronization in the implementation.
5891 
5892    Level: intermediate
5893 
5894    Concepts: matrices^zeroing rows
5895 
5896 .seealso: MatZeroRows(), MatZeroRowsColumns(), MatZeroRowsLocalIS(), MatZeroRowsStencil(), MatZeroEntries(), MatZeroRowsLocal(), MatSetOption(),
5897           MatZeroRowsColumnsLocal(), MatZeroRowsColumnsLocalIS(), MatZeroRowsColumnsIS(), MatZeroRowsColumnsStencil()
5898 @*/
5899 PetscErrorCode MatZeroRowsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
5900 {
5901   PetscInt       numRows;
5902   const PetscInt *rows;
5903   PetscErrorCode ierr;
5904 
5905   PetscFunctionBegin;
5906   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5907   PetscValidType(mat,1);
5908   PetscValidHeaderSpecific(is,IS_CLASSID,2);
5909   ierr = ISGetLocalSize(is,&numRows);CHKERRQ(ierr);
5910   ierr = ISGetIndices(is,&rows);CHKERRQ(ierr);
5911   ierr = MatZeroRows(mat,numRows,rows,diag,x,b);CHKERRQ(ierr);
5912   ierr = ISRestoreIndices(is,&rows);CHKERRQ(ierr);
5913   PetscFunctionReturn(0);
5914 }
5915 
5916 /*@C
5917    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
5918    of a set of rows of a matrix. These rows must be local to the process.
5919 
5920    Collective on Mat
5921 
5922    Input Parameters:
5923 +  mat - the matrix
5924 .  numRows - the number of rows to remove
5925 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
5926 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5927 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5928 -  b - optional vector of right hand side, that will be adjusted by provided solution
5929 
5930    Notes:
5931    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
5932    but does not release memory.  For the dense and block diagonal
5933    formats this does not alter the nonzero structure.
5934 
5935    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
5936    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
5937    merely zeroed.
5938 
5939    The user can set a value in the diagonal entry (or for the AIJ and
5940    row formats can optionally remove the main diagonal entry from the
5941    nonzero structure as well, by passing 0.0 as the final argument).
5942 
5943    For the parallel case, all processes that share the matrix (i.e.,
5944    those in the communicator used for matrix creation) MUST call this
5945    routine, regardless of whether any rows being zeroed are owned by
5946    them.
5947 
5948    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5949    list only rows local to itself).
5950 
5951    The grid coordinates are across the entire grid, not just the local portion
5952 
5953    In Fortran idxm and idxn should be declared as
5954 $     MatStencil idxm(4,m)
5955    and the values inserted using
5956 $    idxm(MatStencil_i,1) = i
5957 $    idxm(MatStencil_j,1) = j
5958 $    idxm(MatStencil_k,1) = k
5959 $    idxm(MatStencil_c,1) = c
5960    etc
5961 
5962    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
5963    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
5964    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
5965    DM_BOUNDARY_PERIODIC boundary type.
5966 
5967    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
5968    a single value per point) you can skip filling those indices.
5969 
5970    Level: intermediate
5971 
5972    Concepts: matrices^zeroing rows
5973 
5974 .seealso: MatZeroRowsIS(), MatZeroRowsColumns(), MatZeroRowsLocalIS(), MatZeroRowsl(), MatZeroEntries(), MatZeroRowsLocal(), MatSetOption(),
5975           MatZeroRowsColumnsLocal(), MatZeroRowsColumnsLocalIS(), MatZeroRowsColumnsIS(), MatZeroRowsColumnsStencil()
5976 @*/
5977 PetscErrorCode MatZeroRowsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
5978 {
5979   PetscInt       dim     = mat->stencil.dim;
5980   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
5981   PetscInt       *dims   = mat->stencil.dims+1;
5982   PetscInt       *starts = mat->stencil.starts;
5983   PetscInt       *dxm    = (PetscInt*) rows;
5984   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
5985   PetscErrorCode ierr;
5986 
5987   PetscFunctionBegin;
5988   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5989   PetscValidType(mat,1);
5990   if (numRows) PetscValidIntPointer(rows,3);
5991 
5992   ierr = PetscMalloc1(numRows, &jdxm);CHKERRQ(ierr);
5993   for (i = 0; i < numRows; ++i) {
5994     /* Skip unused dimensions (they are ordered k, j, i, c) */
5995     for (j = 0; j < 3-sdim; ++j) dxm++;
5996     /* Local index in X dir */
5997     tmp = *dxm++ - starts[0];
5998     /* Loop over remaining dimensions */
5999     for (j = 0; j < dim-1; ++j) {
6000       /* If nonlocal, set index to be negative */
6001       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6002       /* Update local index */
6003       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6004     }
6005     /* Skip component slot if necessary */
6006     if (mat->stencil.noc) dxm++;
6007     /* Local row number */
6008     if (tmp >= 0) {
6009       jdxm[numNewRows++] = tmp;
6010     }
6011   }
6012   ierr = MatZeroRowsLocal(mat,numNewRows,jdxm,diag,x,b);CHKERRQ(ierr);
6013   ierr = PetscFree(jdxm);CHKERRQ(ierr);
6014   PetscFunctionReturn(0);
6015 }
6016 
6017 /*@C
6018    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6019    of a set of rows and columns of a matrix.
6020 
6021    Collective on Mat
6022 
6023    Input Parameters:
6024 +  mat - the matrix
6025 .  numRows - the number of rows/columns to remove
6026 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6027 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6028 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6029 -  b - optional vector of right hand side, that will be adjusted by provided solution
6030 
6031    Notes:
6032    For the AIJ and BAIJ matrix formats this removes the old nonzero structure,
6033    but does not release memory.  For the dense and block diagonal
6034    formats this does not alter the nonzero structure.
6035 
6036    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6037    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6038    merely zeroed.
6039 
6040    The user can set a value in the diagonal entry (or for the AIJ and
6041    row formats can optionally remove the main diagonal entry from the
6042    nonzero structure as well, by passing 0.0 as the final argument).
6043 
6044    For the parallel case, all processes that share the matrix (i.e.,
6045    those in the communicator used for matrix creation) MUST call this
6046    routine, regardless of whether any rows being zeroed are owned by
6047    them.
6048 
6049    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6050    list only rows local to itself, but the row/column numbers are given in local numbering).
6051 
6052    The grid coordinates are across the entire grid, not just the local portion
6053 
6054    In Fortran idxm and idxn should be declared as
6055 $     MatStencil idxm(4,m)
6056    and the values inserted using
6057 $    idxm(MatStencil_i,1) = i
6058 $    idxm(MatStencil_j,1) = j
6059 $    idxm(MatStencil_k,1) = k
6060 $    idxm(MatStencil_c,1) = c
6061    etc
6062 
6063    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6064    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6065    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6066    DM_BOUNDARY_PERIODIC boundary type.
6067 
6068    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
6069    a single value per point) you can skip filling those indices.
6070 
6071    Level: intermediate
6072 
6073    Concepts: matrices^zeroing rows
6074 
6075 .seealso: MatZeroRowsIS(), MatZeroRowsColumns(), MatZeroRowsLocalIS(), MatZeroRowsStencil(), MatZeroEntries(), MatZeroRowsLocal(), MatSetOption(),
6076           MatZeroRowsColumnsLocal(), MatZeroRowsColumnsLocalIS(), MatZeroRowsColumnsIS(), MatZeroRows()
6077 @*/
6078 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)
6079 {
6080   PetscInt       dim     = mat->stencil.dim;
6081   PetscInt       sdim    = dim - (1 - (PetscInt) mat->stencil.noc);
6082   PetscInt       *dims   = mat->stencil.dims+1;
6083   PetscInt       *starts = mat->stencil.starts;
6084   PetscInt       *dxm    = (PetscInt*) rows;
6085   PetscInt       *jdxm, i, j, tmp, numNewRows = 0;
6086   PetscErrorCode ierr;
6087 
6088   PetscFunctionBegin;
6089   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6090   PetscValidType(mat,1);
6091   if (numRows) PetscValidIntPointer(rows,3);
6092 
6093   ierr = PetscMalloc1(numRows, &jdxm);CHKERRQ(ierr);
6094   for (i = 0; i < numRows; ++i) {
6095     /* Skip unused dimensions (they are ordered k, j, i, c) */
6096     for (j = 0; j < 3-sdim; ++j) dxm++;
6097     /* Local index in X dir */
6098     tmp = *dxm++ - starts[0];
6099     /* Loop over remaining dimensions */
6100     for (j = 0; j < dim-1; ++j) {
6101       /* If nonlocal, set index to be negative */
6102       if ((*dxm++ - starts[j+1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6103       /* Update local index */
6104       else tmp = tmp*dims[j] + *(dxm-1) - starts[j+1];
6105     }
6106     /* Skip component slot if necessary */
6107     if (mat->stencil.noc) dxm++;
6108     /* Local row number */
6109     if (tmp >= 0) {
6110       jdxm[numNewRows++] = tmp;
6111     }
6112   }
6113   ierr = MatZeroRowsColumnsLocal(mat,numNewRows,jdxm,diag,x,b);CHKERRQ(ierr);
6114   ierr = PetscFree(jdxm);CHKERRQ(ierr);
6115   PetscFunctionReturn(0);
6116 }
6117 
6118 /*@C
6119    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6120    of a set of rows of a matrix; using local numbering of rows.
6121 
6122    Collective on Mat
6123 
6124    Input Parameters:
6125 +  mat - the matrix
6126 .  numRows - the number of rows to remove
6127 .  rows - the global row indices
6128 .  diag - value put in all diagonals of eliminated rows
6129 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6130 -  b - optional vector of right hand side, that will be adjusted by provided solution
6131 
6132    Notes:
6133    Before calling MatZeroRowsLocal(), the user must first set the
6134    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6135 
6136    For the AIJ matrix formats this removes the old nonzero structure,
6137    but does not release memory.  For the dense and block diagonal
6138    formats this does not alter the nonzero structure.
6139 
6140    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6141    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6142    merely zeroed.
6143 
6144    The user can set a value in the diagonal entry (or for the AIJ and
6145    row formats can optionally remove the main diagonal entry from the
6146    nonzero structure as well, by passing 0.0 as the final argument).
6147 
6148    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6149    owns that are to be zeroed. This saves a global synchronization in the implementation.
6150 
6151    Level: intermediate
6152 
6153    Concepts: matrices^zeroing
6154 
6155 .seealso: MatZeroRowsIS(), MatZeroRowsColumns(), MatZeroRowsLocalIS(), MatZeroRowsStencil(), MatZeroEntries(), MatZeroRows(), MatSetOption(),
6156           MatZeroRowsColumnsLocal(), MatZeroRowsColumnsLocalIS(), MatZeroRowsColumnsIS(), MatZeroRowsColumnsStencil()
6157 @*/
6158 PetscErrorCode MatZeroRowsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6159 {
6160   PetscErrorCode ierr;
6161 
6162   PetscFunctionBegin;
6163   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6164   PetscValidType(mat,1);
6165   if (numRows) PetscValidIntPointer(rows,3);
6166   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6167   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6168   MatCheckPreallocated(mat,1);
6169 
6170   if (mat->ops->zerorowslocal) {
6171     ierr = (*mat->ops->zerorowslocal)(mat,numRows,rows,diag,x,b);CHKERRQ(ierr);
6172   } else {
6173     IS             is, newis;
6174     const PetscInt *newRows;
6175 
6176     if (!mat->rmap->mapping) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6177     ierr = ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is);CHKERRQ(ierr);
6178     ierr = ISLocalToGlobalMappingApplyIS(mat->rmap->mapping,is,&newis);CHKERRQ(ierr);
6179     ierr = ISGetIndices(newis,&newRows);CHKERRQ(ierr);
6180     ierr = (*mat->ops->zerorows)(mat,numRows,newRows,diag,x,b);CHKERRQ(ierr);
6181     ierr = ISRestoreIndices(newis,&newRows);CHKERRQ(ierr);
6182     ierr = ISDestroy(&newis);CHKERRQ(ierr);
6183     ierr = ISDestroy(&is);CHKERRQ(ierr);
6184   }
6185   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
6186 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
6187   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
6188     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
6189   }
6190 #endif
6191   PetscFunctionReturn(0);
6192 }
6193 
6194 /*@C
6195    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6196    of a set of rows of a matrix; using local numbering of rows.
6197 
6198    Collective on Mat
6199 
6200    Input Parameters:
6201 +  mat - the matrix
6202 .  is - index set of rows to remove
6203 .  diag - value put in all diagonals of eliminated rows
6204 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6205 -  b - optional vector of right hand side, that will be adjusted by provided solution
6206 
6207    Notes:
6208    Before calling MatZeroRowsLocalIS(), the user must first set the
6209    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6210 
6211    For the AIJ matrix formats this removes the old nonzero structure,
6212    but does not release memory.  For the dense and block diagonal
6213    formats this does not alter the nonzero structure.
6214 
6215    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6216    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6217    merely zeroed.
6218 
6219    The user can set a value in the diagonal entry (or for the AIJ and
6220    row formats can optionally remove the main diagonal entry from the
6221    nonzero structure as well, by passing 0.0 as the final argument).
6222 
6223    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6224    owns that are to be zeroed. This saves a global synchronization in the implementation.
6225 
6226    Level: intermediate
6227 
6228    Concepts: matrices^zeroing
6229 
6230 .seealso: MatZeroRowsIS(), MatZeroRowsColumns(), MatZeroRows(), MatZeroRowsStencil(), MatZeroEntries(), MatZeroRowsLocal(), MatSetOption(),
6231           MatZeroRowsColumnsLocal(), MatZeroRowsColumnsLocalIS(), MatZeroRowsColumnsIS(), MatZeroRowsColumnsStencil()
6232 @*/
6233 PetscErrorCode MatZeroRowsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6234 {
6235   PetscErrorCode ierr;
6236   PetscInt       numRows;
6237   const PetscInt *rows;
6238 
6239   PetscFunctionBegin;
6240   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6241   PetscValidType(mat,1);
6242   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6243   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6244   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6245   MatCheckPreallocated(mat,1);
6246 
6247   ierr = ISGetLocalSize(is,&numRows);CHKERRQ(ierr);
6248   ierr = ISGetIndices(is,&rows);CHKERRQ(ierr);
6249   ierr = MatZeroRowsLocal(mat,numRows,rows,diag,x,b);CHKERRQ(ierr);
6250   ierr = ISRestoreIndices(is,&rows);CHKERRQ(ierr);
6251   PetscFunctionReturn(0);
6252 }
6253 
6254 /*@C
6255    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6256    of a set of rows and columns of a matrix; using local numbering of rows.
6257 
6258    Collective on Mat
6259 
6260    Input Parameters:
6261 +  mat - the matrix
6262 .  numRows - the number of rows to remove
6263 .  rows - the global row indices
6264 .  diag - value put in all diagonals of eliminated rows
6265 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6266 -  b - optional vector of right hand side, that will be adjusted by provided solution
6267 
6268    Notes:
6269    Before calling MatZeroRowsColumnsLocal(), the user must first set the
6270    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6271 
6272    The user can set a value in the diagonal entry (or for the AIJ and
6273    row formats can optionally remove the main diagonal entry from the
6274    nonzero structure as well, by passing 0.0 as the final argument).
6275 
6276    Level: intermediate
6277 
6278    Concepts: matrices^zeroing
6279 
6280 .seealso: MatZeroRowsIS(), MatZeroRowsColumns(), MatZeroRowsLocalIS(), MatZeroRowsStencil(), MatZeroEntries(), MatZeroRowsLocal(), MatSetOption(),
6281           MatZeroRows(), MatZeroRowsColumnsLocalIS(), MatZeroRowsColumnsIS(), MatZeroRowsColumnsStencil()
6282 @*/
6283 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
6284 {
6285   PetscErrorCode ierr;
6286   IS             is, newis;
6287   const PetscInt *newRows;
6288 
6289   PetscFunctionBegin;
6290   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6291   PetscValidType(mat,1);
6292   if (numRows) PetscValidIntPointer(rows,3);
6293   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6294   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6295   MatCheckPreallocated(mat,1);
6296 
6297   if (!mat->cmap->mapping) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Need to provide local to global mapping to matrix first");
6298   ierr = ISCreateGeneral(PETSC_COMM_SELF,numRows,rows,PETSC_COPY_VALUES,&is);CHKERRQ(ierr);
6299   ierr = ISLocalToGlobalMappingApplyIS(mat->cmap->mapping,is,&newis);CHKERRQ(ierr);
6300   ierr = ISGetIndices(newis,&newRows);CHKERRQ(ierr);
6301   ierr = (*mat->ops->zerorowscolumns)(mat,numRows,newRows,diag,x,b);CHKERRQ(ierr);
6302   ierr = ISRestoreIndices(newis,&newRows);CHKERRQ(ierr);
6303   ierr = ISDestroy(&newis);CHKERRQ(ierr);
6304   ierr = ISDestroy(&is);CHKERRQ(ierr);
6305   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
6306 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_VECCUDA)
6307   if (mat->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
6308     mat->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
6309   }
6310 #endif
6311   PetscFunctionReturn(0);
6312 }
6313 
6314 /*@C
6315    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6316    of a set of rows and columns of a matrix; using local numbering of rows.
6317 
6318    Collective on Mat
6319 
6320    Input Parameters:
6321 +  mat - the matrix
6322 .  is - index set of rows to remove
6323 .  diag - value put in all diagonals of eliminated rows
6324 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6325 -  b - optional vector of right hand side, that will be adjusted by provided solution
6326 
6327    Notes:
6328    Before calling MatZeroRowsColumnsLocalIS(), the user must first set the
6329    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6330 
6331    The user can set a value in the diagonal entry (or for the AIJ and
6332    row formats can optionally remove the main diagonal entry from the
6333    nonzero structure as well, by passing 0.0 as the final argument).
6334 
6335    Level: intermediate
6336 
6337    Concepts: matrices^zeroing
6338 
6339 .seealso: MatZeroRowsIS(), MatZeroRowsColumns(), MatZeroRowsLocalIS(), MatZeroRowsStencil(), MatZeroEntries(), MatZeroRowsLocal(), MatSetOption(),
6340           MatZeroRowsColumnsLocal(), MatZeroRows(), MatZeroRowsColumnsIS(), MatZeroRowsColumnsStencil()
6341 @*/
6342 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)
6343 {
6344   PetscErrorCode ierr;
6345   PetscInt       numRows;
6346   const PetscInt *rows;
6347 
6348   PetscFunctionBegin;
6349   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6350   PetscValidType(mat,1);
6351   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6352   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6353   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6354   MatCheckPreallocated(mat,1);
6355 
6356   ierr = ISGetLocalSize(is,&numRows);CHKERRQ(ierr);
6357   ierr = ISGetIndices(is,&rows);CHKERRQ(ierr);
6358   ierr = MatZeroRowsColumnsLocal(mat,numRows,rows,diag,x,b);CHKERRQ(ierr);
6359   ierr = ISRestoreIndices(is,&rows);CHKERRQ(ierr);
6360   PetscFunctionReturn(0);
6361 }
6362 
6363 /*@C
6364    MatGetSize - Returns the numbers of rows and columns in a matrix.
6365 
6366    Not Collective
6367 
6368    Input Parameter:
6369 .  mat - the matrix
6370 
6371    Output Parameters:
6372 +  m - the number of global rows
6373 -  n - the number of global columns
6374 
6375    Note: both output parameters can be NULL on input.
6376 
6377    Level: beginner
6378 
6379    Concepts: matrices^size
6380 
6381 .seealso: MatGetLocalSize()
6382 @*/
6383 PetscErrorCode MatGetSize(Mat mat,PetscInt *m,PetscInt *n)
6384 {
6385   PetscFunctionBegin;
6386   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6387   if (m) *m = mat->rmap->N;
6388   if (n) *n = mat->cmap->N;
6389   PetscFunctionReturn(0);
6390 }
6391 
6392 /*@C
6393    MatGetLocalSize - Returns the number of rows and columns in a matrix
6394    stored locally.  This information may be implementation dependent, so
6395    use with care.
6396 
6397    Not Collective
6398 
6399    Input Parameters:
6400 .  mat - the matrix
6401 
6402    Output Parameters:
6403 +  m - the number of local rows
6404 -  n - the number of local columns
6405 
6406    Note: both output parameters can be NULL on input.
6407 
6408    Level: beginner
6409 
6410    Concepts: matrices^local size
6411 
6412 .seealso: MatGetSize()
6413 @*/
6414 PetscErrorCode MatGetLocalSize(Mat mat,PetscInt *m,PetscInt *n)
6415 {
6416   PetscFunctionBegin;
6417   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6418   if (m) PetscValidIntPointer(m,2);
6419   if (n) PetscValidIntPointer(n,3);
6420   if (m) *m = mat->rmap->n;
6421   if (n) *n = mat->cmap->n;
6422   PetscFunctionReturn(0);
6423 }
6424 
6425 /*@C
6426    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies by that owned by
6427    this processor. (The columns of the "diagonal block")
6428 
6429    Not Collective, unless matrix has not been allocated, then collective on Mat
6430 
6431    Input Parameters:
6432 .  mat - the matrix
6433 
6434    Output Parameters:
6435 +  m - the global index of the first local column
6436 -  n - one more than the global index of the last local column
6437 
6438    Notes:
6439     both output parameters can be NULL on input.
6440 
6441    Level: developer
6442 
6443    Concepts: matrices^column ownership
6444 
6445 .seealso:  MatGetOwnershipRange(), MatGetOwnershipRanges(), MatGetOwnershipRangesColumn()
6446 
6447 @*/
6448 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat,PetscInt *m,PetscInt *n)
6449 {
6450   PetscFunctionBegin;
6451   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6452   PetscValidType(mat,1);
6453   if (m) PetscValidIntPointer(m,2);
6454   if (n) PetscValidIntPointer(n,3);
6455   MatCheckPreallocated(mat,1);
6456   if (m) *m = mat->cmap->rstart;
6457   if (n) *n = mat->cmap->rend;
6458   PetscFunctionReturn(0);
6459 }
6460 
6461 /*@C
6462    MatGetOwnershipRange - Returns the range of matrix rows owned by
6463    this processor, assuming that the matrix is laid out with the first
6464    n1 rows on the first processor, the next n2 rows on the second, etc.
6465    For certain parallel layouts this range may not be well defined.
6466 
6467    Not Collective
6468 
6469    Input Parameters:
6470 .  mat - the matrix
6471 
6472    Output Parameters:
6473 +  m - the global index of the first local row
6474 -  n - one more than the global index of the last local row
6475 
6476    Note: Both output parameters can be NULL on input.
6477 $  This function requires that the matrix be preallocated. If you have not preallocated, consider using
6478 $    PetscSplitOwnership(MPI_Comm comm, PetscInt *n, PetscInt *N)
6479 $  and then MPI_Scan() to calculate prefix sums of the local sizes.
6480 
6481    Level: beginner
6482 
6483    Concepts: matrices^row ownership
6484 
6485 .seealso:   MatGetOwnershipRanges(), MatGetOwnershipRangeColumn(), MatGetOwnershipRangesColumn(), PetscSplitOwnership(), PetscSplitOwnershipBlock()
6486 
6487 @*/
6488 PetscErrorCode MatGetOwnershipRange(Mat mat,PetscInt *m,PetscInt *n)
6489 {
6490   PetscFunctionBegin;
6491   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6492   PetscValidType(mat,1);
6493   if (m) PetscValidIntPointer(m,2);
6494   if (n) PetscValidIntPointer(n,3);
6495   MatCheckPreallocated(mat,1);
6496   if (m) *m = mat->rmap->rstart;
6497   if (n) *n = mat->rmap->rend;
6498   PetscFunctionReturn(0);
6499 }
6500 
6501 /*@C
6502    MatGetOwnershipRanges - Returns the range of matrix rows owned by
6503    each process
6504 
6505    Not Collective, unless matrix has not been allocated, then collective on Mat
6506 
6507    Input Parameters:
6508 .  mat - the matrix
6509 
6510    Output Parameters:
6511 .  ranges - start of each processors portion plus one more than the total length at the end
6512 
6513    Level: beginner
6514 
6515    Concepts: matrices^row ownership
6516 
6517 .seealso:   MatGetOwnershipRange(), MatGetOwnershipRangeColumn(), MatGetOwnershipRangesColumn()
6518 
6519 @*/
6520 PetscErrorCode MatGetOwnershipRanges(Mat mat,const PetscInt **ranges)
6521 {
6522   PetscErrorCode ierr;
6523 
6524   PetscFunctionBegin;
6525   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6526   PetscValidType(mat,1);
6527   MatCheckPreallocated(mat,1);
6528   ierr = PetscLayoutGetRanges(mat->rmap,ranges);CHKERRQ(ierr);
6529   PetscFunctionReturn(0);
6530 }
6531 
6532 /*@C
6533    MatGetOwnershipRangesColumn - Returns the range of matrix columns associated with rows of a vector one multiplies by that owned by
6534    this processor. (The columns of the "diagonal blocks" for each process)
6535 
6536    Not Collective, unless matrix has not been allocated, then collective on Mat
6537 
6538    Input Parameters:
6539 .  mat - the matrix
6540 
6541    Output Parameters:
6542 .  ranges - start of each processors portion plus one more then the total length at the end
6543 
6544    Level: beginner
6545 
6546    Concepts: matrices^column ownership
6547 
6548 .seealso:   MatGetOwnershipRange(), MatGetOwnershipRangeColumn(), MatGetOwnershipRanges()
6549 
6550 @*/
6551 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat,const PetscInt **ranges)
6552 {
6553   PetscErrorCode ierr;
6554 
6555   PetscFunctionBegin;
6556   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6557   PetscValidType(mat,1);
6558   MatCheckPreallocated(mat,1);
6559   ierr = PetscLayoutGetRanges(mat->cmap,ranges);CHKERRQ(ierr);
6560   PetscFunctionReturn(0);
6561 }
6562 
6563 /*@C
6564    MatGetOwnershipIS - Get row and column ownership as index sets
6565 
6566    Not Collective
6567 
6568    Input Arguments:
6569 .  A - matrix of type Elemental
6570 
6571    Output Arguments:
6572 +  rows - rows in which this process owns elements
6573 .  cols - columns in which this process owns elements
6574 
6575    Level: intermediate
6576 
6577 .seealso: MatGetOwnershipRange(), MatGetOwnershipRangeColumn(), MatSetValues(), MATELEMENTAL
6578 @*/
6579 PetscErrorCode MatGetOwnershipIS(Mat A,IS *rows,IS *cols)
6580 {
6581   PetscErrorCode ierr,(*f)(Mat,IS*,IS*);
6582 
6583   PetscFunctionBegin;
6584   MatCheckPreallocated(A,1);
6585   ierr = PetscObjectQueryFunction((PetscObject)A,"MatGetOwnershipIS_C",&f);CHKERRQ(ierr);
6586   if (f) {
6587     ierr = (*f)(A,rows,cols);CHKERRQ(ierr);
6588   } else {   /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6589     if (rows) {ierr = ISCreateStride(PETSC_COMM_SELF,A->rmap->n,A->rmap->rstart,1,rows);CHKERRQ(ierr);}
6590     if (cols) {ierr = ISCreateStride(PETSC_COMM_SELF,A->cmap->N,0,1,cols);CHKERRQ(ierr);}
6591   }
6592   PetscFunctionReturn(0);
6593 }
6594 
6595 /*@C
6596    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix.
6597    Uses levels of fill only, not drop tolerance. Use MatLUFactorNumeric()
6598    to complete the factorization.
6599 
6600    Collective on Mat
6601 
6602    Input Parameters:
6603 +  mat - the matrix
6604 .  row - row permutation
6605 .  column - column permutation
6606 -  info - structure containing
6607 $      levels - number of levels of fill.
6608 $      expected fill - as ratio of original fill.
6609 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6610                 missing diagonal entries)
6611 
6612    Output Parameters:
6613 .  fact - new matrix that has been symbolically factored
6614 
6615    Notes:
6616     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
6617 
6618    Most users should employ the simplified KSP interface for linear solvers
6619    instead of working directly with matrix algebra routines such as this.
6620    See, e.g., KSPCreate().
6621 
6622    Level: developer
6623 
6624   Concepts: matrices^symbolic LU factorization
6625   Concepts: matrices^factorization
6626   Concepts: LU^symbolic factorization
6627 
6628 .seealso: MatLUFactorSymbolic(), MatLUFactorNumeric(), MatCholeskyFactor()
6629           MatGetOrdering(), MatFactorInfo
6630 
6631     Developer Note: fortran interface is not autogenerated as the f90
6632     interface defintion cannot be generated correctly [due to MatFactorInfo]
6633 
6634 @*/
6635 PetscErrorCode MatILUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo *info)
6636 {
6637   PetscErrorCode ierr;
6638 
6639   PetscFunctionBegin;
6640   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6641   PetscValidType(mat,1);
6642   PetscValidHeaderSpecific(row,IS_CLASSID,2);
6643   PetscValidHeaderSpecific(col,IS_CLASSID,3);
6644   PetscValidPointer(info,4);
6645   PetscValidPointer(fact,5);
6646   if (info->levels < 0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels of fill negative %D",(PetscInt)info->levels);
6647   if (info->fill < 1.0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6648   if (!(fact)->ops->ilufactorsymbolic) {
6649     MatSolverType spackage;
6650     ierr = MatFactorGetSolverType(fact,&spackage);CHKERRQ(ierr);
6651     SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ILU using solver package %s",((PetscObject)mat)->type_name,spackage);
6652   }
6653   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6654   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6655   MatCheckPreallocated(mat,2);
6656 
6657   ierr = PetscLogEventBegin(MAT_ILUFactorSymbolic,mat,row,col,0);CHKERRQ(ierr);
6658   ierr = (fact->ops->ilufactorsymbolic)(fact,mat,row,col,info);CHKERRQ(ierr);
6659   ierr = PetscLogEventEnd(MAT_ILUFactorSymbolic,mat,row,col,0);CHKERRQ(ierr);
6660   PetscFunctionReturn(0);
6661 }
6662 
6663 /*@C
6664    MatICCFactorSymbolic - Performs symbolic incomplete
6665    Cholesky factorization for a symmetric matrix.  Use
6666    MatCholeskyFactorNumeric() to complete the factorization.
6667 
6668    Collective on Mat
6669 
6670    Input Parameters:
6671 +  mat - the matrix
6672 .  perm - row and column permutation
6673 -  info - structure containing
6674 $      levels - number of levels of fill.
6675 $      expected fill - as ratio of original fill.
6676 
6677    Output Parameter:
6678 .  fact - the factored matrix
6679 
6680    Notes:
6681    Most users should employ the KSP interface for linear solvers
6682    instead of working directly with matrix algebra routines such as this.
6683    See, e.g., KSPCreate().
6684 
6685    Level: developer
6686 
6687   Concepts: matrices^symbolic incomplete Cholesky factorization
6688   Concepts: matrices^factorization
6689   Concepts: Cholsky^symbolic factorization
6690 
6691 .seealso: MatCholeskyFactorNumeric(), MatCholeskyFactor(), MatFactorInfo
6692 
6693     Developer Note: fortran interface is not autogenerated as the f90
6694     interface defintion cannot be generated correctly [due to MatFactorInfo]
6695 
6696 @*/
6697 PetscErrorCode MatICCFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo *info)
6698 {
6699   PetscErrorCode ierr;
6700 
6701   PetscFunctionBegin;
6702   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6703   PetscValidType(mat,1);
6704   PetscValidHeaderSpecific(perm,IS_CLASSID,2);
6705   PetscValidPointer(info,3);
6706   PetscValidPointer(fact,4);
6707   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6708   if (info->levels < 0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Levels negative %D",(PetscInt) info->levels);
6709   if (info->fill < 1.0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Expected fill less than 1.0 %g",(double)info->fill);
6710   if (!(fact)->ops->iccfactorsymbolic) {
6711     MatSolverType spackage;
6712     ierr = MatFactorGetSolverType(fact,&spackage);CHKERRQ(ierr);
6713     SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Matrix type %s symbolic ICC using solver package %s",((PetscObject)mat)->type_name,spackage);
6714   }
6715   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6716   MatCheckPreallocated(mat,2);
6717 
6718   ierr = PetscLogEventBegin(MAT_ICCFactorSymbolic,mat,perm,0,0);CHKERRQ(ierr);
6719   ierr = (fact->ops->iccfactorsymbolic)(fact,mat,perm,info);CHKERRQ(ierr);
6720   ierr = PetscLogEventEnd(MAT_ICCFactorSymbolic,mat,perm,0,0);CHKERRQ(ierr);
6721   PetscFunctionReturn(0);
6722 }
6723 
6724 /*@C
6725    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6726    points to an array of valid matrices, they may be reused to store the new
6727    submatrices.
6728 
6729    Collective on Mat
6730 
6731    Input Parameters:
6732 +  mat - the matrix
6733 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6734 .  irow, icol - index sets of rows and columns to extract
6735 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6736 
6737    Output Parameter:
6738 .  submat - the array of submatrices
6739 
6740    Notes:
6741    MatCreateSubMatrices() can extract ONLY sequential submatrices
6742    (from both sequential and parallel matrices). Use MatCreateSubMatrix()
6743    to extract a parallel submatrix.
6744 
6745    Some matrix types place restrictions on the row and column
6746    indices, such as that they be sorted or that they be equal to each other.
6747 
6748    The index sets may not have duplicate entries.
6749 
6750    When extracting submatrices from a parallel matrix, each processor can
6751    form a different submatrix by setting the rows and columns of its
6752    individual index sets according to the local submatrix desired.
6753 
6754    When finished using the submatrices, the user should destroy
6755    them with MatDestroySubMatrices().
6756 
6757    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
6758    original matrix has not changed from that last call to MatCreateSubMatrices().
6759 
6760    This routine creates the matrices in submat; you should NOT create them before
6761    calling it. It also allocates the array of matrix pointers submat.
6762 
6763    For BAIJ matrices the index sets must respect the block structure, that is if they
6764    request one row/column in a block, they must request all rows/columns that are in
6765    that block. For example, if the block size is 2 you cannot request just row 0 and
6766    column 0.
6767 
6768    Fortran Note:
6769    The Fortran interface is slightly different from that given below; it
6770    requires one to pass in  as submat a Mat (integer) array of size at least n+1.
6771 
6772    Level: advanced
6773 
6774    Concepts: matrices^accessing submatrices
6775    Concepts: submatrices
6776 
6777 .seealso: MatDestroySubMatrices(), MatCreateSubMatrix(), MatGetRow(), MatGetDiagonal(), MatReuse
6778 @*/
6779 PetscErrorCode MatCreateSubMatrices(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
6780 {
6781   PetscErrorCode ierr;
6782   PetscInt       i;
6783   PetscBool      eq;
6784 
6785   PetscFunctionBegin;
6786   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6787   PetscValidType(mat,1);
6788   if (n) {
6789     PetscValidPointer(irow,3);
6790     PetscValidHeaderSpecific(*irow,IS_CLASSID,3);
6791     PetscValidPointer(icol,4);
6792     PetscValidHeaderSpecific(*icol,IS_CLASSID,4);
6793   }
6794   PetscValidPointer(submat,6);
6795   if (n && scall == MAT_REUSE_MATRIX) {
6796     PetscValidPointer(*submat,6);
6797     PetscValidHeaderSpecific(**submat,MAT_CLASSID,6);
6798   }
6799   if (!mat->ops->createsubmatrices) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6800   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6801   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6802   MatCheckPreallocated(mat,1);
6803 
6804   ierr = PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0);CHKERRQ(ierr);
6805   ierr = (*mat->ops->createsubmatrices)(mat,n,irow,icol,scall,submat);CHKERRQ(ierr);
6806   ierr = PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0);CHKERRQ(ierr);
6807   for (i=0; i<n; i++) {
6808     (*submat)[i]->factortype = MAT_FACTOR_NONE;  /* in case in place factorization was previously done on submatrix */
6809     if (mat->symmetric || mat->structurally_symmetric || mat->hermitian) {
6810       ierr = ISEqual(irow[i],icol[i],&eq);CHKERRQ(ierr);
6811       if (eq) {
6812         if (mat->symmetric) {
6813           ierr = MatSetOption((*submat)[i],MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
6814         } else if (mat->hermitian) {
6815           ierr = MatSetOption((*submat)[i],MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);
6816         } else if (mat->structurally_symmetric) {
6817           ierr = MatSetOption((*submat)[i],MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
6818         }
6819       }
6820     }
6821   }
6822   PetscFunctionReturn(0);
6823 }
6824 
6825 /*@C
6826    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of IS that may live on subcomms).
6827 
6828    Collective on Mat
6829 
6830    Input Parameters:
6831 +  mat - the matrix
6832 .  n   - the number of submatrixes to be extracted
6833 .  irow, icol - index sets of rows and columns to extract
6834 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6835 
6836    Output Parameter:
6837 .  submat - the array of submatrices
6838 
6839    Level: advanced
6840 
6841    Concepts: matrices^accessing submatrices
6842    Concepts: submatrices
6843 
6844 .seealso: MatCreateSubMatrices(), MatCreateSubMatrix(), MatGetRow(), MatGetDiagonal(), MatReuse
6845 @*/
6846 PetscErrorCode MatCreateSubMatricesMPI(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
6847 {
6848   PetscErrorCode ierr;
6849   PetscInt       i;
6850   PetscBool      eq;
6851 
6852   PetscFunctionBegin;
6853   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6854   PetscValidType(mat,1);
6855   if (n) {
6856     PetscValidPointer(irow,3);
6857     PetscValidHeaderSpecific(*irow,IS_CLASSID,3);
6858     PetscValidPointer(icol,4);
6859     PetscValidHeaderSpecific(*icol,IS_CLASSID,4);
6860   }
6861   PetscValidPointer(submat,6);
6862   if (n && scall == MAT_REUSE_MATRIX) {
6863     PetscValidPointer(*submat,6);
6864     PetscValidHeaderSpecific(**submat,MAT_CLASSID,6);
6865   }
6866   if (!mat->ops->createsubmatricesmpi) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
6867   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
6868   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6869   MatCheckPreallocated(mat,1);
6870 
6871   ierr = PetscLogEventBegin(MAT_CreateSubMats,mat,0,0,0);CHKERRQ(ierr);
6872   ierr = (*mat->ops->createsubmatricesmpi)(mat,n,irow,icol,scall,submat);CHKERRQ(ierr);
6873   ierr = PetscLogEventEnd(MAT_CreateSubMats,mat,0,0,0);CHKERRQ(ierr);
6874   for (i=0; i<n; i++) {
6875     if (mat->symmetric || mat->structurally_symmetric || mat->hermitian) {
6876       ierr = ISEqual(irow[i],icol[i],&eq);CHKERRQ(ierr);
6877       if (eq) {
6878         if (mat->symmetric) {
6879           ierr = MatSetOption((*submat)[i],MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
6880         } else if (mat->hermitian) {
6881           ierr = MatSetOption((*submat)[i],MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);
6882         } else if (mat->structurally_symmetric) {
6883           ierr = MatSetOption((*submat)[i],MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
6884         }
6885       }
6886     }
6887   }
6888   PetscFunctionReturn(0);
6889 }
6890 
6891 /*@C
6892    MatDestroyMatrices - Destroys an array of matrices.
6893 
6894    Collective on Mat
6895 
6896    Input Parameters:
6897 +  n - the number of local matrices
6898 -  mat - the matrices (note that this is a pointer to the array of matrices)
6899 
6900    Level: advanced
6901 
6902     Notes:
6903     Frees not only the matrices, but also the array that contains the matrices
6904            In Fortran will not free the array.
6905 
6906 .seealso: MatCreateSubMatrices() MatDestroySubMatrices()
6907 @*/
6908 PetscErrorCode MatDestroyMatrices(PetscInt n,Mat *mat[])
6909 {
6910   PetscErrorCode ierr;
6911   PetscInt       i;
6912 
6913   PetscFunctionBegin;
6914   if (!*mat) PetscFunctionReturn(0);
6915   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %D",n);
6916   PetscValidPointer(mat,2);
6917 
6918   for (i=0; i<n; i++) {
6919     ierr = MatDestroy(&(*mat)[i]);CHKERRQ(ierr);
6920   }
6921 
6922   /* memory is allocated even if n = 0 */
6923   ierr = PetscFree(*mat);CHKERRQ(ierr);
6924   PetscFunctionReturn(0);
6925 }
6926 
6927 /*@C
6928    MatDestroySubMatrices - Destroys a set of matrices obtained with MatCreateSubMatrices().
6929 
6930    Collective on Mat
6931 
6932    Input Parameters:
6933 +  n - the number of local matrices
6934 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6935                        sequence of MatCreateSubMatrices())
6936 
6937    Level: advanced
6938 
6939     Notes:
6940     Frees not only the matrices, but also the array that contains the matrices
6941            In Fortran will not free the array.
6942 
6943 .seealso: MatCreateSubMatrices()
6944 @*/
6945 PetscErrorCode MatDestroySubMatrices(PetscInt n,Mat *mat[])
6946 {
6947   PetscErrorCode ierr;
6948   Mat            mat0;
6949 
6950   PetscFunctionBegin;
6951   if (!*mat) PetscFunctionReturn(0);
6952   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
6953   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy negative number of matrices %D",n);
6954   PetscValidPointer(mat,2);
6955 
6956   mat0 = (*mat)[0];
6957   if (mat0 && mat0->ops->destroysubmatrices) {
6958     ierr = (mat0->ops->destroysubmatrices)(n,mat);CHKERRQ(ierr);
6959   } else {
6960     ierr = MatDestroyMatrices(n,mat);CHKERRQ(ierr);
6961   }
6962   PetscFunctionReturn(0);
6963 }
6964 
6965 /*@C
6966    MatGetSeqNonzeroStructure - Extracts the sequential nonzero structure from a matrix.
6967 
6968    Collective on Mat
6969 
6970    Input Parameters:
6971 .  mat - the matrix
6972 
6973    Output Parameter:
6974 .  matstruct - the sequential matrix with the nonzero structure of mat
6975 
6976   Level: intermediate
6977 
6978 .seealso: MatDestroySeqNonzeroStructure(), MatCreateSubMatrices(), MatDestroyMatrices()
6979 @*/
6980 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat,Mat *matstruct)
6981 {
6982   PetscErrorCode ierr;
6983 
6984   PetscFunctionBegin;
6985   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6986   PetscValidPointer(matstruct,2);
6987 
6988   PetscValidType(mat,1);
6989   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
6990   MatCheckPreallocated(mat,1);
6991 
6992   if (!mat->ops->getseqnonzerostructure) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not for matrix type %s\n",((PetscObject)mat)->type_name);
6993   ierr = PetscLogEventBegin(MAT_GetSeqNonzeroStructure,mat,0,0,0);CHKERRQ(ierr);
6994   ierr = (*mat->ops->getseqnonzerostructure)(mat,matstruct);CHKERRQ(ierr);
6995   ierr = PetscLogEventEnd(MAT_GetSeqNonzeroStructure,mat,0,0,0);CHKERRQ(ierr);
6996   PetscFunctionReturn(0);
6997 }
6998 
6999 /*@C
7000    MatDestroySeqNonzeroStructure - Destroys matrix obtained with MatGetSeqNonzeroStructure().
7001 
7002    Collective on Mat
7003 
7004    Input Parameters:
7005 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7006                        sequence of MatGetSequentialNonzeroStructure())
7007 
7008    Level: advanced
7009 
7010     Notes:
7011     Frees not only the matrices, but also the array that contains the matrices
7012 
7013 .seealso: MatGetSeqNonzeroStructure()
7014 @*/
7015 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7016 {
7017   PetscErrorCode ierr;
7018 
7019   PetscFunctionBegin;
7020   PetscValidPointer(mat,1);
7021   ierr = MatDestroy(mat);CHKERRQ(ierr);
7022   PetscFunctionReturn(0);
7023 }
7024 
7025 /*@
7026    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7027    replaces the index sets by larger ones that represent submatrices with
7028    additional overlap.
7029 
7030    Collective on Mat
7031 
7032    Input Parameters:
7033 +  mat - the matrix
7034 .  n   - the number of index sets
7035 .  is  - the array of index sets (these index sets will changed during the call)
7036 -  ov  - the additional overlap requested
7037 
7038    Options Database:
7039 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7040 
7041    Level: developer
7042 
7043    Concepts: overlap
7044    Concepts: ASM^computing overlap
7045 
7046 .seealso: MatCreateSubMatrices()
7047 @*/
7048 PetscErrorCode MatIncreaseOverlap(Mat mat,PetscInt n,IS is[],PetscInt ov)
7049 {
7050   PetscErrorCode ierr;
7051 
7052   PetscFunctionBegin;
7053   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7054   PetscValidType(mat,1);
7055   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %D",n);
7056   if (n) {
7057     PetscValidPointer(is,3);
7058     PetscValidHeaderSpecific(*is,IS_CLASSID,3);
7059   }
7060   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7061   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7062   MatCheckPreallocated(mat,1);
7063 
7064   if (!ov) PetscFunctionReturn(0);
7065   if (!mat->ops->increaseoverlap) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7066   ierr = PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0);CHKERRQ(ierr);
7067   ierr = (*mat->ops->increaseoverlap)(mat,n,is,ov);CHKERRQ(ierr);
7068   ierr = PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0);CHKERRQ(ierr);
7069   PetscFunctionReturn(0);
7070 }
7071 
7072 
7073 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat,IS*,PetscInt);
7074 
7075 /*@
7076    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7077    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7078    additional overlap.
7079 
7080    Collective on Mat
7081 
7082    Input Parameters:
7083 +  mat - the matrix
7084 .  n   - the number of index sets
7085 .  is  - the array of index sets (these index sets will changed during the call)
7086 -  ov  - the additional overlap requested
7087 
7088    Options Database:
7089 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7090 
7091    Level: developer
7092 
7093    Concepts: overlap
7094    Concepts: ASM^computing overlap
7095 
7096 .seealso: MatCreateSubMatrices()
7097 @*/
7098 PetscErrorCode MatIncreaseOverlapSplit(Mat mat,PetscInt n,IS is[],PetscInt ov)
7099 {
7100   PetscInt       i;
7101   PetscErrorCode ierr;
7102 
7103   PetscFunctionBegin;
7104   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7105   PetscValidType(mat,1);
7106   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more domains, you have %D",n);
7107   if (n) {
7108     PetscValidPointer(is,3);
7109     PetscValidHeaderSpecific(*is,IS_CLASSID,3);
7110   }
7111   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
7112   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7113   MatCheckPreallocated(mat,1);
7114   if (!ov) PetscFunctionReturn(0);
7115   ierr = PetscLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0);CHKERRQ(ierr);
7116   for(i=0; i<n; i++){
7117 	ierr =  MatIncreaseOverlapSplit_Single(mat,&is[i],ov);CHKERRQ(ierr);
7118   }
7119   ierr = PetscLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0);CHKERRQ(ierr);
7120   PetscFunctionReturn(0);
7121 }
7122 
7123 
7124 
7125 
7126 /*@
7127    MatGetBlockSize - Returns the matrix block size.
7128 
7129    Not Collective
7130 
7131    Input Parameter:
7132 .  mat - the matrix
7133 
7134    Output Parameter:
7135 .  bs - block size
7136 
7137    Notes:
7138     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7139 
7140    If the block size has not been set yet this routine returns 1.
7141 
7142    Level: intermediate
7143 
7144    Concepts: matrices^block size
7145 
7146 .seealso: MatCreateSeqBAIJ(), MatCreateBAIJ(), MatGetBlockSizes()
7147 @*/
7148 PetscErrorCode MatGetBlockSize(Mat mat,PetscInt *bs)
7149 {
7150   PetscFunctionBegin;
7151   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7152   PetscValidIntPointer(bs,2);
7153   *bs = PetscAbs(mat->rmap->bs);
7154   PetscFunctionReturn(0);
7155 }
7156 
7157 /*@
7158    MatGetBlockSizes - Returns the matrix block row and column sizes.
7159 
7160    Not Collective
7161 
7162    Input Parameter:
7163 .  mat - the matrix
7164 
7165    Output Parameter:
7166 .  rbs - row block size
7167 .  cbs - column block size
7168 
7169    Notes:
7170     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7171     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7172 
7173    If a block size has not been set yet this routine returns 1.
7174 
7175    Level: intermediate
7176 
7177    Concepts: matrices^block size
7178 
7179 .seealso: MatCreateSeqBAIJ(), MatCreateBAIJ(), MatGetBlockSize(), MatSetBlockSize(), MatSetBlockSizes()
7180 @*/
7181 PetscErrorCode MatGetBlockSizes(Mat mat,PetscInt *rbs, PetscInt *cbs)
7182 {
7183   PetscFunctionBegin;
7184   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7185   if (rbs) PetscValidIntPointer(rbs,2);
7186   if (cbs) PetscValidIntPointer(cbs,3);
7187   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7188   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7189   PetscFunctionReturn(0);
7190 }
7191 
7192 /*@
7193    MatSetBlockSize - Sets the matrix block size.
7194 
7195    Logically Collective on Mat
7196 
7197    Input Parameters:
7198 +  mat - the matrix
7199 -  bs - block size
7200 
7201    Notes:
7202     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7203     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7204 
7205     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block size
7206     is compatible with the matrix local sizes.
7207 
7208    Level: intermediate
7209 
7210    Concepts: matrices^block size
7211 
7212 .seealso: MatCreateSeqBAIJ(), MatCreateBAIJ(), MatGetBlockSize(), MatSetBlockSizes(), MatGetBlockSizes()
7213 @*/
7214 PetscErrorCode MatSetBlockSize(Mat mat,PetscInt bs)
7215 {
7216   PetscErrorCode ierr;
7217 
7218   PetscFunctionBegin;
7219   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7220   PetscValidLogicalCollectiveInt(mat,bs,2);
7221   ierr = MatSetBlockSizes(mat,bs,bs);CHKERRQ(ierr);
7222   PetscFunctionReturn(0);
7223 }
7224 
7225 /*@
7226    MatSetBlockSizes - Sets the matrix block row and column sizes.
7227 
7228    Logically Collective on Mat
7229 
7230    Input Parameters:
7231 +  mat - the matrix
7232 -  rbs - row block size
7233 -  cbs - column block size
7234 
7235    Notes:
7236     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7237     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7238     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later
7239 
7240     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block sizes
7241     are compatible with the matrix local sizes.
7242 
7243     The row and column block size determine the blocksize of the "row" and "column" vectors returned by MatCreateVecs().
7244 
7245    Level: intermediate
7246 
7247    Concepts: matrices^block size
7248 
7249 .seealso: MatCreateSeqBAIJ(), MatCreateBAIJ(), MatGetBlockSize(), MatSetBlockSize(), MatGetBlockSizes()
7250 @*/
7251 PetscErrorCode MatSetBlockSizes(Mat mat,PetscInt rbs,PetscInt cbs)
7252 {
7253   PetscErrorCode ierr;
7254 
7255   PetscFunctionBegin;
7256   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7257   PetscValidLogicalCollectiveInt(mat,rbs,2);
7258   PetscValidLogicalCollectiveInt(mat,cbs,3);
7259   if (mat->ops->setblocksizes) {
7260     ierr = (*mat->ops->setblocksizes)(mat,rbs,cbs);CHKERRQ(ierr);
7261   }
7262   if (mat->rmap->refcnt) {
7263     ISLocalToGlobalMapping l2g = NULL;
7264     PetscLayout            nmap = NULL;
7265 
7266     ierr = PetscLayoutDuplicate(mat->rmap,&nmap);CHKERRQ(ierr);
7267     if (mat->rmap->mapping) {
7268       ierr = ISLocalToGlobalMappingDuplicate(mat->rmap->mapping,&l2g);CHKERRQ(ierr);
7269     }
7270     ierr = PetscLayoutDestroy(&mat->rmap);CHKERRQ(ierr);
7271     mat->rmap = nmap;
7272     mat->rmap->mapping = l2g;
7273   }
7274   if (mat->cmap->refcnt) {
7275     ISLocalToGlobalMapping l2g = NULL;
7276     PetscLayout            nmap = NULL;
7277 
7278     ierr = PetscLayoutDuplicate(mat->cmap,&nmap);CHKERRQ(ierr);
7279     if (mat->cmap->mapping) {
7280       ierr = ISLocalToGlobalMappingDuplicate(mat->cmap->mapping,&l2g);CHKERRQ(ierr);
7281     }
7282     ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
7283     mat->cmap = nmap;
7284     mat->cmap->mapping = l2g;
7285   }
7286   ierr = PetscLayoutSetBlockSize(mat->rmap,rbs);CHKERRQ(ierr);
7287   ierr = PetscLayoutSetBlockSize(mat->cmap,cbs);CHKERRQ(ierr);
7288   PetscFunctionReturn(0);
7289 }
7290 
7291 /*@
7292    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7293 
7294    Logically Collective on Mat
7295 
7296    Input Parameters:
7297 +  mat - the matrix
7298 .  fromRow - matrix from which to copy row block size
7299 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7300 
7301    Level: developer
7302 
7303    Concepts: matrices^block size
7304 
7305 .seealso: MatCreateSeqBAIJ(), MatCreateBAIJ(), MatGetBlockSize(), MatSetBlockSizes()
7306 @*/
7307 PetscErrorCode MatSetBlockSizesFromMats(Mat mat,Mat fromRow,Mat fromCol)
7308 {
7309   PetscErrorCode ierr;
7310 
7311   PetscFunctionBegin;
7312   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7313   PetscValidHeaderSpecific(fromRow,MAT_CLASSID,2);
7314   PetscValidHeaderSpecific(fromCol,MAT_CLASSID,3);
7315   if (fromRow->rmap->bs > 0) {ierr = PetscLayoutSetBlockSize(mat->rmap,fromRow->rmap->bs);CHKERRQ(ierr);}
7316   if (fromCol->cmap->bs > 0) {ierr = PetscLayoutSetBlockSize(mat->cmap,fromCol->cmap->bs);CHKERRQ(ierr);}
7317   PetscFunctionReturn(0);
7318 }
7319 
7320 /*@
7321    MatResidual - Default routine to calculate the residual.
7322 
7323    Collective on Mat and Vec
7324 
7325    Input Parameters:
7326 +  mat - the matrix
7327 .  b   - the right-hand-side
7328 -  x   - the approximate solution
7329 
7330    Output Parameter:
7331 .  r - location to store the residual
7332 
7333    Level: developer
7334 
7335 .keywords: MG, default, multigrid, residual
7336 
7337 .seealso: PCMGSetResidual()
7338 @*/
7339 PetscErrorCode MatResidual(Mat mat,Vec b,Vec x,Vec r)
7340 {
7341   PetscErrorCode ierr;
7342 
7343   PetscFunctionBegin;
7344   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7345   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
7346   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
7347   PetscValidHeaderSpecific(r,VEC_CLASSID,4);
7348   PetscValidType(mat,1);
7349   MatCheckPreallocated(mat,1);
7350   ierr  = PetscLogEventBegin(MAT_Residual,mat,0,0,0);CHKERRQ(ierr);
7351   if (!mat->ops->residual) {
7352     ierr = MatMult(mat,x,r);CHKERRQ(ierr);
7353     ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr);
7354   } else {
7355     ierr  = (*mat->ops->residual)(mat,b,x,r);CHKERRQ(ierr);
7356   }
7357   ierr  = PetscLogEventEnd(MAT_Residual,mat,0,0,0);CHKERRQ(ierr);
7358   PetscFunctionReturn(0);
7359 }
7360 
7361 /*@C
7362     MatGetRowIJ - Returns the compressed row storage i and j indices for sequential matrices.
7363 
7364    Collective on Mat
7365 
7366     Input Parameters:
7367 +   mat - the matrix
7368 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7369 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be   symmetrized
7370 -   inodecompressed - PETSC_TRUE or PETSC_FALSE  indicating if the nonzero structure of the
7371                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7372                  always used.
7373 
7374     Output Parameters:
7375 +   n - number of rows in the (possibly compressed) matrix
7376 .   ia - the row pointers [of length n+1]
7377 .   ja - the column indices
7378 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7379            are responsible for handling the case when done == PETSC_FALSE and ia and ja are not set
7380 
7381     Level: developer
7382 
7383     Notes:
7384     You CANNOT change any of the ia[] or ja[] values.
7385 
7386     Use MatRestoreRowIJ() when you are finished accessing the ia[] and ja[] values.
7387 
7388     Fortran Notes:
7389     In Fortran use
7390 $
7391 $      PetscInt ia(1), ja(1)
7392 $      PetscOffset iia, jja
7393 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7394 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7395 
7396      or
7397 $
7398 $    PetscInt, pointer :: ia(:),ja(:)
7399 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7400 $    ! Access the ith and jth entries via ia(i) and ja(j)
7401 
7402 .seealso: MatGetColumnIJ(), MatRestoreRowIJ(), MatSeqAIJGetArray()
7403 @*/
7404 PetscErrorCode MatGetRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7405 {
7406   PetscErrorCode ierr;
7407 
7408   PetscFunctionBegin;
7409   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7410   PetscValidType(mat,1);
7411   PetscValidIntPointer(n,5);
7412   if (ia) PetscValidIntPointer(ia,6);
7413   if (ja) PetscValidIntPointer(ja,7);
7414   PetscValidIntPointer(done,8);
7415   MatCheckPreallocated(mat,1);
7416   if (!mat->ops->getrowij) *done = PETSC_FALSE;
7417   else {
7418     *done = PETSC_TRUE;
7419     ierr  = PetscLogEventBegin(MAT_GetRowIJ,mat,0,0,0);CHKERRQ(ierr);
7420     ierr  = (*mat->ops->getrowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
7421     ierr  = PetscLogEventEnd(MAT_GetRowIJ,mat,0,0,0);CHKERRQ(ierr);
7422   }
7423   PetscFunctionReturn(0);
7424 }
7425 
7426 /*@C
7427     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7428 
7429     Collective on Mat
7430 
7431     Input Parameters:
7432 +   mat - the matrix
7433 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7434 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7435                 symmetrized
7436 .   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7437                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7438                  always used.
7439 .   n - number of columns in the (possibly compressed) matrix
7440 .   ia - the column pointers
7441 -   ja - the row indices
7442 
7443     Output Parameters:
7444 .   done - PETSC_TRUE or PETSC_FALSE, indicating whether the values have been returned
7445 
7446     Note:
7447     This routine zeros out n, ia, and ja. This is to prevent accidental
7448     us of the array after it has been restored. If you pass NULL, it will
7449     not zero the pointers.  Use of ia or ja after MatRestoreColumnIJ() is invalid.
7450 
7451     Level: developer
7452 
7453 .seealso: MatGetRowIJ(), MatRestoreColumnIJ()
7454 @*/
7455 PetscErrorCode MatGetColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7456 {
7457   PetscErrorCode ierr;
7458 
7459   PetscFunctionBegin;
7460   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7461   PetscValidType(mat,1);
7462   PetscValidIntPointer(n,4);
7463   if (ia) PetscValidIntPointer(ia,5);
7464   if (ja) PetscValidIntPointer(ja,6);
7465   PetscValidIntPointer(done,7);
7466   MatCheckPreallocated(mat,1);
7467   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7468   else {
7469     *done = PETSC_TRUE;
7470     ierr  = (*mat->ops->getcolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
7471   }
7472   PetscFunctionReturn(0);
7473 }
7474 
7475 /*@C
7476     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with
7477     MatGetRowIJ().
7478 
7479     Collective on Mat
7480 
7481     Input Parameters:
7482 +   mat - the matrix
7483 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7484 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7485                 symmetrized
7486 .   inodecompressed -  PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7487                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7488                  always used.
7489 .   n - size of (possibly compressed) matrix
7490 .   ia - the row pointers
7491 -   ja - the column indices
7492 
7493     Output Parameters:
7494 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7495 
7496     Note:
7497     This routine zeros out n, ia, and ja. This is to prevent accidental
7498     us of the array after it has been restored. If you pass NULL, it will
7499     not zero the pointers.  Use of ia or ja after MatRestoreRowIJ() is invalid.
7500 
7501     Level: developer
7502 
7503 .seealso: MatGetRowIJ(), MatRestoreColumnIJ()
7504 @*/
7505 PetscErrorCode MatRestoreRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7506 {
7507   PetscErrorCode ierr;
7508 
7509   PetscFunctionBegin;
7510   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7511   PetscValidType(mat,1);
7512   if (ia) PetscValidIntPointer(ia,6);
7513   if (ja) PetscValidIntPointer(ja,7);
7514   PetscValidIntPointer(done,8);
7515   MatCheckPreallocated(mat,1);
7516 
7517   if (!mat->ops->restorerowij) *done = PETSC_FALSE;
7518   else {
7519     *done = PETSC_TRUE;
7520     ierr  = (*mat->ops->restorerowij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
7521     if (n)  *n = 0;
7522     if (ia) *ia = NULL;
7523     if (ja) *ja = NULL;
7524   }
7525   PetscFunctionReturn(0);
7526 }
7527 
7528 /*@C
7529     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with
7530     MatGetColumnIJ().
7531 
7532     Collective on Mat
7533 
7534     Input Parameters:
7535 +   mat - the matrix
7536 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7537 -   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7538                 symmetrized
7539 -   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7540                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7541                  always used.
7542 
7543     Output Parameters:
7544 +   n - size of (possibly compressed) matrix
7545 .   ia - the column pointers
7546 .   ja - the row indices
7547 -   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7548 
7549     Level: developer
7550 
7551 .seealso: MatGetColumnIJ(), MatRestoreRowIJ()
7552 @*/
7553 PetscErrorCode MatRestoreColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
7554 {
7555   PetscErrorCode ierr;
7556 
7557   PetscFunctionBegin;
7558   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7559   PetscValidType(mat,1);
7560   if (ia) PetscValidIntPointer(ia,5);
7561   if (ja) PetscValidIntPointer(ja,6);
7562   PetscValidIntPointer(done,7);
7563   MatCheckPreallocated(mat,1);
7564 
7565   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7566   else {
7567     *done = PETSC_TRUE;
7568     ierr  = (*mat->ops->restorecolumnij)(mat,shift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
7569     if (n)  *n = 0;
7570     if (ia) *ia = NULL;
7571     if (ja) *ja = NULL;
7572   }
7573   PetscFunctionReturn(0);
7574 }
7575 
7576 /*@C
7577     MatColoringPatch -Used inside matrix coloring routines that
7578     use MatGetRowIJ() and/or MatGetColumnIJ().
7579 
7580     Collective on Mat
7581 
7582     Input Parameters:
7583 +   mat - the matrix
7584 .   ncolors - max color value
7585 .   n   - number of entries in colorarray
7586 -   colorarray - array indicating color for each column
7587 
7588     Output Parameters:
7589 .   iscoloring - coloring generated using colorarray information
7590 
7591     Level: developer
7592 
7593 .seealso: MatGetRowIJ(), MatGetColumnIJ()
7594 
7595 @*/
7596 PetscErrorCode MatColoringPatch(Mat mat,PetscInt ncolors,PetscInt n,ISColoringValue colorarray[],ISColoring *iscoloring)
7597 {
7598   PetscErrorCode ierr;
7599 
7600   PetscFunctionBegin;
7601   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7602   PetscValidType(mat,1);
7603   PetscValidIntPointer(colorarray,4);
7604   PetscValidPointer(iscoloring,5);
7605   MatCheckPreallocated(mat,1);
7606 
7607   if (!mat->ops->coloringpatch) {
7608     ierr = ISColoringCreate(PetscObjectComm((PetscObject)mat),ncolors,n,colorarray,PETSC_OWN_POINTER,iscoloring);CHKERRQ(ierr);
7609   } else {
7610     ierr = (*mat->ops->coloringpatch)(mat,ncolors,n,colorarray,iscoloring);CHKERRQ(ierr);
7611   }
7612   PetscFunctionReturn(0);
7613 }
7614 
7615 
7616 /*@
7617    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7618 
7619    Logically Collective on Mat
7620 
7621    Input Parameter:
7622 .  mat - the factored matrix to be reset
7623 
7624    Notes:
7625    This routine should be used only with factored matrices formed by in-place
7626    factorization via ILU(0) (or by in-place LU factorization for the MATSEQDENSE
7627    format).  This option can save memory, for example, when solving nonlinear
7628    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7629    ILU(0) preconditioner.
7630 
7631    Note that one can specify in-place ILU(0) factorization by calling
7632 .vb
7633      PCType(pc,PCILU);
7634      PCFactorSeUseInPlace(pc);
7635 .ve
7636    or by using the options -pc_type ilu -pc_factor_in_place
7637 
7638    In-place factorization ILU(0) can also be used as a local
7639    solver for the blocks within the block Jacobi or additive Schwarz
7640    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7641    for details on setting local solver options.
7642 
7643    Most users should employ the simplified KSP interface for linear solvers
7644    instead of working directly with matrix algebra routines such as this.
7645    See, e.g., KSPCreate().
7646 
7647    Level: developer
7648 
7649 .seealso: PCFactorSetUseInPlace(), PCFactorGetUseInPlace()
7650 
7651    Concepts: matrices^unfactored
7652 
7653 @*/
7654 PetscErrorCode MatSetUnfactored(Mat mat)
7655 {
7656   PetscErrorCode ierr;
7657 
7658   PetscFunctionBegin;
7659   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7660   PetscValidType(mat,1);
7661   MatCheckPreallocated(mat,1);
7662   mat->factortype = MAT_FACTOR_NONE;
7663   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
7664   ierr = (*mat->ops->setunfactored)(mat);CHKERRQ(ierr);
7665   PetscFunctionReturn(0);
7666 }
7667 
7668 /*MC
7669     MatDenseGetArrayF90 - Accesses a matrix array from Fortran90.
7670 
7671     Synopsis:
7672     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7673 
7674     Not collective
7675 
7676     Input Parameter:
7677 .   x - matrix
7678 
7679     Output Parameters:
7680 +   xx_v - the Fortran90 pointer to the array
7681 -   ierr - error code
7682 
7683     Example of Usage:
7684 .vb
7685       PetscScalar, pointer xx_v(:,:)
7686       ....
7687       call MatDenseGetArrayF90(x,xx_v,ierr)
7688       a = xx_v(3)
7689       call MatDenseRestoreArrayF90(x,xx_v,ierr)
7690 .ve
7691 
7692     Level: advanced
7693 
7694 .seealso:  MatDenseRestoreArrayF90(), MatDenseGetArray(), MatDenseRestoreArray(), MatSeqAIJGetArrayF90()
7695 
7696     Concepts: matrices^accessing array
7697 
7698 M*/
7699 
7700 /*MC
7701     MatDenseRestoreArrayF90 - Restores a matrix array that has been
7702     accessed with MatDenseGetArrayF90().
7703 
7704     Synopsis:
7705     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7706 
7707     Not collective
7708 
7709     Input Parameters:
7710 +   x - matrix
7711 -   xx_v - the Fortran90 pointer to the array
7712 
7713     Output Parameter:
7714 .   ierr - error code
7715 
7716     Example of Usage:
7717 .vb
7718        PetscScalar, pointer xx_v(:,:)
7719        ....
7720        call MatDenseGetArrayF90(x,xx_v,ierr)
7721        a = xx_v(3)
7722        call MatDenseRestoreArrayF90(x,xx_v,ierr)
7723 .ve
7724 
7725     Level: advanced
7726 
7727 .seealso:  MatDenseGetArrayF90(), MatDenseGetArray(), MatDenseRestoreArray(), MatSeqAIJRestoreArrayF90()
7728 
7729 M*/
7730 
7731 
7732 /*MC
7733     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran90.
7734 
7735     Synopsis:
7736     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7737 
7738     Not collective
7739 
7740     Input Parameter:
7741 .   x - matrix
7742 
7743     Output Parameters:
7744 +   xx_v - the Fortran90 pointer to the array
7745 -   ierr - error code
7746 
7747     Example of Usage:
7748 .vb
7749       PetscScalar, pointer xx_v(:)
7750       ....
7751       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7752       a = xx_v(3)
7753       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7754 .ve
7755 
7756     Level: advanced
7757 
7758 .seealso:  MatSeqAIJRestoreArrayF90(), MatSeqAIJGetArray(), MatSeqAIJRestoreArray(), MatDenseGetArrayF90()
7759 
7760     Concepts: matrices^accessing array
7761 
7762 M*/
7763 
7764 /*MC
7765     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
7766     accessed with MatSeqAIJGetArrayF90().
7767 
7768     Synopsis:
7769     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7770 
7771     Not collective
7772 
7773     Input Parameters:
7774 +   x - matrix
7775 -   xx_v - the Fortran90 pointer to the array
7776 
7777     Output Parameter:
7778 .   ierr - error code
7779 
7780     Example of Usage:
7781 .vb
7782        PetscScalar, pointer xx_v(:)
7783        ....
7784        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7785        a = xx_v(3)
7786        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7787 .ve
7788 
7789     Level: advanced
7790 
7791 .seealso:  MatSeqAIJGetArrayF90(), MatSeqAIJGetArray(), MatSeqAIJRestoreArray(), MatDenseRestoreArrayF90()
7792 
7793 M*/
7794 
7795 
7796 /*@
7797     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
7798                       as the original matrix.
7799 
7800     Collective on Mat
7801 
7802     Input Parameters:
7803 +   mat - the original matrix
7804 .   isrow - parallel IS containing the rows this processor should obtain
7805 .   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.
7806 -   cll - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
7807 
7808     Output Parameter:
7809 .   newmat - the new submatrix, of the same type as the old
7810 
7811     Level: advanced
7812 
7813     Notes:
7814     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
7815 
7816     Some matrix types place restrictions on the row and column indices, such
7817     as that they be sorted or that they be equal to each other.
7818 
7819     The index sets may not have duplicate entries.
7820 
7821       The first time this is called you should use a cll of MAT_INITIAL_MATRIX,
7822    the MatCreateSubMatrix() routine will create the newmat for you. Any additional calls
7823    to this routine with a mat of the same nonzero structure and with a call of MAT_REUSE_MATRIX
7824    will reuse the matrix generated the first time.  You should call MatDestroy() on newmat when
7825    you are finished using it.
7826 
7827     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
7828     the input matrix.
7829 
7830     If iscol is NULL then all columns are obtained (not supported in Fortran).
7831 
7832    Example usage:
7833    Consider the following 8x8 matrix with 34 non-zero values, that is
7834    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
7835    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
7836    as follows:
7837 
7838 .vb
7839             1  2  0  |  0  3  0  |  0  4
7840     Proc0   0  5  6  |  7  0  0  |  8  0
7841             9  0 10  | 11  0  0  | 12  0
7842     -------------------------------------
7843            13  0 14  | 15 16 17  |  0  0
7844     Proc1   0 18  0  | 19 20 21  |  0  0
7845             0  0  0  | 22 23  0  | 24  0
7846     -------------------------------------
7847     Proc2  25 26 27  |  0  0 28  | 29  0
7848            30  0  0  | 31 32 33  |  0 34
7849 .ve
7850 
7851     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
7852 
7853 .vb
7854             2  0  |  0  3  0  |  0
7855     Proc0   5  6  |  7  0  0  |  8
7856     -------------------------------
7857     Proc1  18  0  | 19 20 21  |  0
7858     -------------------------------
7859     Proc2  26 27  |  0  0 28  | 29
7860             0  0  | 31 32 33  |  0
7861 .ve
7862 
7863 
7864     Concepts: matrices^submatrices
7865 
7866 .seealso: MatCreateSubMatrices()
7867 @*/
7868 PetscErrorCode MatCreateSubMatrix(Mat mat,IS isrow,IS iscol,MatReuse cll,Mat *newmat)
7869 {
7870   PetscErrorCode ierr;
7871   PetscMPIInt    size;
7872   Mat            *local;
7873   IS             iscoltmp;
7874 
7875   PetscFunctionBegin;
7876   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7877   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
7878   if (iscol) PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
7879   PetscValidPointer(newmat,5);
7880   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat,MAT_CLASSID,5);
7881   PetscValidType(mat,1);
7882   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
7883   if (cll == MAT_IGNORE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Cannot use MAT_IGNORE_MATRIX");
7884 
7885   MatCheckPreallocated(mat,1);
7886   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
7887 
7888   if (!iscol || isrow == iscol) {
7889     PetscBool   stride;
7890     PetscMPIInt grabentirematrix = 0,grab;
7891     ierr = PetscObjectTypeCompare((PetscObject)isrow,ISSTRIDE,&stride);CHKERRQ(ierr);
7892     if (stride) {
7893       PetscInt first,step,n,rstart,rend;
7894       ierr = ISStrideGetInfo(isrow,&first,&step);CHKERRQ(ierr);
7895       if (step == 1) {
7896         ierr = MatGetOwnershipRange(mat,&rstart,&rend);CHKERRQ(ierr);
7897         if (rstart == first) {
7898           ierr = ISGetLocalSize(isrow,&n);CHKERRQ(ierr);
7899           if (n == rend-rstart) {
7900             grabentirematrix = 1;
7901           }
7902         }
7903       }
7904     }
7905     ierr = MPIU_Allreduce(&grabentirematrix,&grab,1,MPI_INT,MPI_MIN,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
7906     if (grab) {
7907       ierr = PetscInfo(mat,"Getting entire matrix as submatrix\n");CHKERRQ(ierr);
7908       if (cll == MAT_INITIAL_MATRIX) {
7909         *newmat = mat;
7910         ierr    = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
7911       }
7912       PetscFunctionReturn(0);
7913     }
7914   }
7915 
7916   if (!iscol) {
7917     ierr = ISCreateStride(PetscObjectComm((PetscObject)mat),mat->cmap->n,mat->cmap->rstart,1,&iscoltmp);CHKERRQ(ierr);
7918   } else {
7919     iscoltmp = iscol;
7920   }
7921 
7922   /* if original matrix is on just one processor then use submatrix generated */
7923   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
7924     ierr = MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_REUSE_MATRIX,&newmat);CHKERRQ(ierr);
7925     if (!iscol) {ierr = ISDestroy(&iscoltmp);CHKERRQ(ierr);}
7926     PetscFunctionReturn(0);
7927   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
7928     ierr    = MatCreateSubMatrices(mat,1,&isrow,&iscoltmp,MAT_INITIAL_MATRIX,&local);CHKERRQ(ierr);
7929     *newmat = *local;
7930     ierr    = PetscFree(local);CHKERRQ(ierr);
7931     if (!iscol) {ierr = ISDestroy(&iscoltmp);CHKERRQ(ierr);}
7932     PetscFunctionReturn(0);
7933   } else if (!mat->ops->createsubmatrix) {
7934     /* Create a new matrix type that implements the operation using the full matrix */
7935     ierr = PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0);CHKERRQ(ierr);
7936     switch (cll) {
7937     case MAT_INITIAL_MATRIX:
7938       ierr = MatCreateSubMatrixVirtual(mat,isrow,iscoltmp,newmat);CHKERRQ(ierr);
7939       break;
7940     case MAT_REUSE_MATRIX:
7941       ierr = MatSubMatrixVirtualUpdate(*newmat,mat,isrow,iscoltmp);CHKERRQ(ierr);
7942       break;
7943     default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
7944     }
7945     ierr = PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0);CHKERRQ(ierr);
7946     if (!iscol) {ierr = ISDestroy(&iscoltmp);CHKERRQ(ierr);}
7947     PetscFunctionReturn(0);
7948   }
7949 
7950   if (!mat->ops->createsubmatrix) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
7951   ierr = PetscLogEventBegin(MAT_CreateSubMat,mat,0,0,0);CHKERRQ(ierr);
7952   ierr = (*mat->ops->createsubmatrix)(mat,isrow,iscoltmp,cll,newmat);CHKERRQ(ierr);
7953   ierr = PetscLogEventEnd(MAT_CreateSubMat,mat,0,0,0);CHKERRQ(ierr);
7954 
7955   /* Propagate symmetry information for diagonal blocks */
7956   if (isrow == iscoltmp) {
7957     if (mat->symmetric_set && mat->symmetric) {
7958       ierr = MatSetOption(*newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
7959     }
7960     if (mat->structurally_symmetric_set && mat->structurally_symmetric) {
7961       ierr = MatSetOption(*newmat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
7962     }
7963     if (mat->hermitian_set && mat->hermitian) {
7964       ierr = MatSetOption(*newmat,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);
7965     }
7966     if (mat->spd_set && mat->spd) {
7967       ierr = MatSetOption(*newmat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
7968     }
7969   }
7970 
7971   if (!iscol) {ierr = ISDestroy(&iscoltmp);CHKERRQ(ierr);}
7972   if (*newmat && cll == MAT_INITIAL_MATRIX) {ierr = PetscObjectStateIncrease((PetscObject)*newmat);CHKERRQ(ierr);}
7973   PetscFunctionReturn(0);
7974 }
7975 
7976 /*@
7977    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
7978    used during the assembly process to store values that belong to
7979    other processors.
7980 
7981    Not Collective
7982 
7983    Input Parameters:
7984 +  mat   - the matrix
7985 .  size  - the initial size of the stash.
7986 -  bsize - the initial size of the block-stash(if used).
7987 
7988    Options Database Keys:
7989 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
7990 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
7991 
7992    Level: intermediate
7993 
7994    Notes:
7995      The block-stash is used for values set with MatSetValuesBlocked() while
7996      the stash is used for values set with MatSetValues()
7997 
7998      Run with the option -info and look for output of the form
7999      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8000      to determine the appropriate value, MM, to use for size and
8001      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8002      to determine the value, BMM to use for bsize
8003 
8004    Concepts: stash^setting matrix size
8005    Concepts: matrices^stash
8006 
8007 .seealso: MatAssemblyBegin(), MatAssemblyEnd(), Mat, MatStashGetInfo()
8008 
8009 @*/
8010 PetscErrorCode MatStashSetInitialSize(Mat mat,PetscInt size, PetscInt bsize)
8011 {
8012   PetscErrorCode ierr;
8013 
8014   PetscFunctionBegin;
8015   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8016   PetscValidType(mat,1);
8017   ierr = MatStashSetInitialSize_Private(&mat->stash,size);CHKERRQ(ierr);
8018   ierr = MatStashSetInitialSize_Private(&mat->bstash,bsize);CHKERRQ(ierr);
8019   PetscFunctionReturn(0);
8020 }
8021 
8022 /*@
8023    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8024      the matrix
8025 
8026    Neighbor-wise Collective on Mat
8027 
8028    Input Parameters:
8029 +  mat   - the matrix
8030 .  x,y - the vectors
8031 -  w - where the result is stored
8032 
8033    Level: intermediate
8034 
8035    Notes:
8036     w may be the same vector as y.
8037 
8038     This allows one to use either the restriction or interpolation (its transpose)
8039     matrix to do the interpolation
8040 
8041     Concepts: interpolation
8042 
8043 .seealso: MatMultAdd(), MatMultTransposeAdd(), MatRestrict()
8044 
8045 @*/
8046 PetscErrorCode MatInterpolateAdd(Mat A,Vec x,Vec y,Vec w)
8047 {
8048   PetscErrorCode ierr;
8049   PetscInt       M,N,Ny;
8050 
8051   PetscFunctionBegin;
8052   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8053   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8054   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8055   PetscValidHeaderSpecific(w,VEC_CLASSID,4);
8056   PetscValidType(A,1);
8057   MatCheckPreallocated(A,1);
8058   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
8059   ierr = VecGetSize(y,&Ny);CHKERRQ(ierr);
8060   if (M == Ny) {
8061     ierr = MatMultAdd(A,x,y,w);CHKERRQ(ierr);
8062   } else {
8063     ierr = MatMultTransposeAdd(A,x,y,w);CHKERRQ(ierr);
8064   }
8065   PetscFunctionReturn(0);
8066 }
8067 
8068 /*@
8069    MatInterpolate - y = A*x or A'*x depending on the shape of
8070      the matrix
8071 
8072    Neighbor-wise Collective on Mat
8073 
8074    Input Parameters:
8075 +  mat   - the matrix
8076 -  x,y - the vectors
8077 
8078    Level: intermediate
8079 
8080    Notes:
8081     This allows one to use either the restriction or interpolation (its transpose)
8082     matrix to do the interpolation
8083 
8084    Concepts: matrices^interpolation
8085 
8086 .seealso: MatMultAdd(), MatMultTransposeAdd(), MatRestrict()
8087 
8088 @*/
8089 PetscErrorCode MatInterpolate(Mat A,Vec x,Vec y)
8090 {
8091   PetscErrorCode ierr;
8092   PetscInt       M,N,Ny;
8093 
8094   PetscFunctionBegin;
8095   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8096   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8097   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8098   PetscValidType(A,1);
8099   MatCheckPreallocated(A,1);
8100   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
8101   ierr = VecGetSize(y,&Ny);CHKERRQ(ierr);
8102   if (M == Ny) {
8103     ierr = MatMult(A,x,y);CHKERRQ(ierr);
8104   } else {
8105     ierr = MatMultTranspose(A,x,y);CHKERRQ(ierr);
8106   }
8107   PetscFunctionReturn(0);
8108 }
8109 
8110 /*@
8111    MatRestrict - y = A*x or A'*x
8112 
8113    Neighbor-wise Collective on Mat
8114 
8115    Input Parameters:
8116 +  mat   - the matrix
8117 -  x,y - the vectors
8118 
8119    Level: intermediate
8120 
8121    Notes:
8122     This allows one to use either the restriction or interpolation (its transpose)
8123     matrix to do the restriction
8124 
8125    Concepts: matrices^restriction
8126 
8127 .seealso: MatMultAdd(), MatMultTransposeAdd(), MatInterpolate()
8128 
8129 @*/
8130 PetscErrorCode MatRestrict(Mat A,Vec x,Vec y)
8131 {
8132   PetscErrorCode ierr;
8133   PetscInt       M,N,Ny;
8134 
8135   PetscFunctionBegin;
8136   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8137   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
8138   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
8139   PetscValidType(A,1);
8140   MatCheckPreallocated(A,1);
8141 
8142   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
8143   ierr = VecGetSize(y,&Ny);CHKERRQ(ierr);
8144   if (M == Ny) {
8145     ierr = MatMult(A,x,y);CHKERRQ(ierr);
8146   } else {
8147     ierr = MatMultTranspose(A,x,y);CHKERRQ(ierr);
8148   }
8149   PetscFunctionReturn(0);
8150 }
8151 
8152 /*@C
8153    MatGetNullSpace - retrieves the null space of a matrix.
8154 
8155    Logically Collective on Mat and MatNullSpace
8156 
8157    Input Parameters:
8158 +  mat - the matrix
8159 -  nullsp - the null space object
8160 
8161    Level: developer
8162 
8163    Concepts: null space^attaching to matrix
8164 
8165 .seealso: MatCreate(), MatNullSpaceCreate(), MatSetNearNullSpace(), MatSetNullSpace()
8166 @*/
8167 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8168 {
8169   PetscFunctionBegin;
8170   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8171   PetscValidPointer(nullsp,2);
8172   *nullsp = (mat->symmetric_set && mat->symmetric && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8173   PetscFunctionReturn(0);
8174 }
8175 
8176 /*@C
8177    MatSetNullSpace - attaches a null space to a matrix.
8178 
8179    Logically Collective on Mat and MatNullSpace
8180 
8181    Input Parameters:
8182 +  mat - the matrix
8183 -  nullsp - the null space object
8184 
8185    Level: advanced
8186 
8187    Notes:
8188       This null space is used by the linear solvers. Overwrites any previous null space that may have been attached
8189 
8190       For inconsistent singular systems (linear systems where the right hand side is not in the range of the operator) you also likely should
8191       call MatSetTransposeNullSpace(). This allows the linear system to be solved in a least squares sense.
8192 
8193       You can remove the null space by calling this routine with an nullsp of NULL
8194 
8195 
8196       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8197    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).
8198    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
8199    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
8200    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).
8201 
8202       Krylov solvers can produce the minimal norm solution to the least squares problem by utilizing MatNullSpaceRemove().
8203 
8204     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
8205     routine also automatically calls MatSetTransposeNullSpace().
8206 
8207    Concepts: null space^attaching to matrix
8208 
8209 .seealso: MatCreate(), MatNullSpaceCreate(), MatSetNearNullSpace(), MatGetNullSpace(), MatSetTransposeNullSpace(), MatGetTransposeNullSpace(), MatNullSpaceRemove()
8210 @*/
8211 PetscErrorCode MatSetNullSpace(Mat mat,MatNullSpace nullsp)
8212 {
8213   PetscErrorCode ierr;
8214 
8215   PetscFunctionBegin;
8216   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8217   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8218   if (nullsp) {ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr);}
8219   ierr = MatNullSpaceDestroy(&mat->nullsp);CHKERRQ(ierr);
8220   mat->nullsp = nullsp;
8221   if (mat->symmetric_set && mat->symmetric) {
8222     ierr = MatSetTransposeNullSpace(mat,nullsp);CHKERRQ(ierr);
8223   }
8224   PetscFunctionReturn(0);
8225 }
8226 
8227 /*@
8228    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8229 
8230    Logically Collective on Mat and MatNullSpace
8231 
8232    Input Parameters:
8233 +  mat - the matrix
8234 -  nullsp - the null space object
8235 
8236    Level: developer
8237 
8238    Concepts: null space^attaching to matrix
8239 
8240 .seealso: MatCreate(), MatNullSpaceCreate(), MatSetNearNullSpace(), MatSetTransposeNullSpace(), MatSetNullSpace(), MatGetNullSpace()
8241 @*/
8242 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8243 {
8244   PetscFunctionBegin;
8245   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8246   PetscValidType(mat,1);
8247   PetscValidPointer(nullsp,2);
8248   *nullsp = (mat->symmetric_set && mat->symmetric && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8249   PetscFunctionReturn(0);
8250 }
8251 
8252 /*@
8253    MatSetTransposeNullSpace - attaches a null space to a matrix.
8254 
8255    Logically Collective on Mat and MatNullSpace
8256 
8257    Input Parameters:
8258 +  mat - the matrix
8259 -  nullsp - the null space object
8260 
8261    Level: advanced
8262 
8263    Notes:
8264       For inconsistent singular systems (linear systems where the right hand side is not in the range of the operator) this allows the linear system to be solved in a least squares sense.
8265       You must also call MatSetNullSpace()
8266 
8267 
8268       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8269    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).
8270    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
8271    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
8272    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).
8273 
8274       Krylov solvers can produce the minimal norm solution to the least squares problem by utilizing MatNullSpaceRemove().
8275 
8276    Concepts: null space^attaching to matrix
8277 
8278 .seealso: MatCreate(), MatNullSpaceCreate(), MatSetNearNullSpace(), MatGetNullSpace(), MatSetNullSpace(), MatGetTransposeNullSpace(), MatNullSpaceRemove()
8279 @*/
8280 PetscErrorCode MatSetTransposeNullSpace(Mat mat,MatNullSpace nullsp)
8281 {
8282   PetscErrorCode ierr;
8283 
8284   PetscFunctionBegin;
8285   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8286   PetscValidType(mat,1);
8287   PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8288   MatCheckPreallocated(mat,1);
8289   ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr);
8290   ierr = MatNullSpaceDestroy(&mat->transnullsp);CHKERRQ(ierr);
8291   mat->transnullsp = nullsp;
8292   PetscFunctionReturn(0);
8293 }
8294 
8295 /*@
8296    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8297         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8298 
8299    Logically Collective on Mat and MatNullSpace
8300 
8301    Input Parameters:
8302 +  mat - the matrix
8303 -  nullsp - the null space object
8304 
8305    Level: advanced
8306 
8307    Notes:
8308       Overwrites any previous near null space that may have been attached
8309 
8310       You can remove the null space by calling this routine with an nullsp of NULL
8311 
8312    Concepts: null space^attaching to matrix
8313 
8314 .seealso: MatCreate(), MatNullSpaceCreate(), MatSetNullSpace(), MatNullSpaceCreateRigidBody(), MatGetNearNullSpace()
8315 @*/
8316 PetscErrorCode MatSetNearNullSpace(Mat mat,MatNullSpace nullsp)
8317 {
8318   PetscErrorCode ierr;
8319 
8320   PetscFunctionBegin;
8321   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8322   PetscValidType(mat,1);
8323   if (nullsp) PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_CLASSID,2);
8324   MatCheckPreallocated(mat,1);
8325   if (nullsp) {ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr);}
8326   ierr = MatNullSpaceDestroy(&mat->nearnullsp);CHKERRQ(ierr);
8327   mat->nearnullsp = nullsp;
8328   PetscFunctionReturn(0);
8329 }
8330 
8331 /*@
8332    MatGetNearNullSpace -Get null space attached with MatSetNearNullSpace()
8333 
8334    Not Collective
8335 
8336    Input Parameters:
8337 .  mat - the matrix
8338 
8339    Output Parameters:
8340 .  nullsp - the null space object, NULL if not set
8341 
8342    Level: developer
8343 
8344    Concepts: null space^attaching to matrix
8345 
8346 .seealso: MatSetNearNullSpace(), MatGetNullSpace(), MatNullSpaceCreate()
8347 @*/
8348 PetscErrorCode MatGetNearNullSpace(Mat mat,MatNullSpace *nullsp)
8349 {
8350   PetscFunctionBegin;
8351   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8352   PetscValidType(mat,1);
8353   PetscValidPointer(nullsp,2);
8354   MatCheckPreallocated(mat,1);
8355   *nullsp = mat->nearnullsp;
8356   PetscFunctionReturn(0);
8357 }
8358 
8359 /*@C
8360    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8361 
8362    Collective on Mat
8363 
8364    Input Parameters:
8365 +  mat - the matrix
8366 .  row - row/column permutation
8367 .  fill - expected fill factor >= 1.0
8368 -  level - level of fill, for ICC(k)
8369 
8370    Notes:
8371    Probably really in-place only when level of fill is zero, otherwise allocates
8372    new space to store factored matrix and deletes previous memory.
8373 
8374    Most users should employ the simplified KSP interface for linear solvers
8375    instead of working directly with matrix algebra routines such as this.
8376    See, e.g., KSPCreate().
8377 
8378    Level: developer
8379 
8380    Concepts: matrices^incomplete Cholesky factorization
8381    Concepts: Cholesky factorization
8382 
8383 .seealso: MatICCFactorSymbolic(), MatLUFactorNumeric(), MatCholeskyFactor()
8384 
8385     Developer Note: fortran interface is not autogenerated as the f90
8386     interface defintion cannot be generated correctly [due to MatFactorInfo]
8387 
8388 @*/
8389 PetscErrorCode MatICCFactor(Mat mat,IS row,const MatFactorInfo *info)
8390 {
8391   PetscErrorCode ierr;
8392 
8393   PetscFunctionBegin;
8394   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8395   PetscValidType(mat,1);
8396   if (row) PetscValidHeaderSpecific(row,IS_CLASSID,2);
8397   PetscValidPointer(info,3);
8398   if (mat->rmap->N != mat->cmap->N) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"matrix must be square");
8399   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
8400   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
8401   if (!mat->ops->iccfactor) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8402   MatCheckPreallocated(mat,1);
8403   ierr = (*mat->ops->iccfactor)(mat,row,info);CHKERRQ(ierr);
8404   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
8405   PetscFunctionReturn(0);
8406 }
8407 
8408 /*@
8409    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8410          ghosted ones.
8411 
8412    Not Collective
8413 
8414    Input Parameters:
8415 +  mat - the matrix
8416 -  diag = the diagonal values, including ghost ones
8417 
8418    Level: developer
8419 
8420    Notes:
8421     Works only for MPIAIJ and MPIBAIJ matrices
8422 
8423 .seealso: MatDiagonalScale()
8424 @*/
8425 PetscErrorCode MatDiagonalScaleLocal(Mat mat,Vec diag)
8426 {
8427   PetscErrorCode ierr;
8428   PetscMPIInt    size;
8429 
8430   PetscFunctionBegin;
8431   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8432   PetscValidHeaderSpecific(diag,VEC_CLASSID,2);
8433   PetscValidType(mat,1);
8434 
8435   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be already assembled");
8436   ierr = PetscLogEventBegin(MAT_Scale,mat,0,0,0);CHKERRQ(ierr);
8437   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
8438   if (size == 1) {
8439     PetscInt n,m;
8440     ierr = VecGetSize(diag,&n);CHKERRQ(ierr);
8441     ierr = MatGetSize(mat,0,&m);CHKERRQ(ierr);
8442     if (m == n) {
8443       ierr = MatDiagonalScale(mat,0,diag);CHKERRQ(ierr);
8444     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only supported for sequential matrices when no ghost points/periodic conditions");
8445   } else {
8446     ierr = PetscUseMethod(mat,"MatDiagonalScaleLocal_C",(Mat,Vec),(mat,diag));CHKERRQ(ierr);
8447   }
8448   ierr = PetscLogEventEnd(MAT_Scale,mat,0,0,0);CHKERRQ(ierr);
8449   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
8450   PetscFunctionReturn(0);
8451 }
8452 
8453 /*@
8454    MatGetInertia - Gets the inertia from a factored matrix
8455 
8456    Collective on Mat
8457 
8458    Input Parameter:
8459 .  mat - the matrix
8460 
8461    Output Parameters:
8462 +   nneg - number of negative eigenvalues
8463 .   nzero - number of zero eigenvalues
8464 -   npos - number of positive eigenvalues
8465 
8466    Level: advanced
8467 
8468    Notes:
8469     Matrix must have been factored by MatCholeskyFactor()
8470 
8471 
8472 @*/
8473 PetscErrorCode MatGetInertia(Mat mat,PetscInt *nneg,PetscInt *nzero,PetscInt *npos)
8474 {
8475   PetscErrorCode ierr;
8476 
8477   PetscFunctionBegin;
8478   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8479   PetscValidType(mat,1);
8480   if (!mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
8481   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Numeric factor mat is not assembled");
8482   if (!mat->ops->getinertia) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8483   ierr = (*mat->ops->getinertia)(mat,nneg,nzero,npos);CHKERRQ(ierr);
8484   PetscFunctionReturn(0);
8485 }
8486 
8487 /* ----------------------------------------------------------------*/
8488 /*@C
8489    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8490 
8491    Neighbor-wise Collective on Mat and Vecs
8492 
8493    Input Parameters:
8494 +  mat - the factored matrix
8495 -  b - the right-hand-side vectors
8496 
8497    Output Parameter:
8498 .  x - the result vectors
8499 
8500    Notes:
8501    The vectors b and x cannot be the same.  I.e., one cannot
8502    call MatSolves(A,x,x).
8503 
8504    Notes:
8505    Most users should employ the simplified KSP interface for linear solvers
8506    instead of working directly with matrix algebra routines such as this.
8507    See, e.g., KSPCreate().
8508 
8509    Level: developer
8510 
8511    Concepts: matrices^triangular solves
8512 
8513 .seealso: MatSolveAdd(), MatSolveTranspose(), MatSolveTransposeAdd(), MatSolve()
8514 @*/
8515 PetscErrorCode MatSolves(Mat mat,Vecs b,Vecs x)
8516 {
8517   PetscErrorCode ierr;
8518 
8519   PetscFunctionBegin;
8520   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8521   PetscValidType(mat,1);
8522   if (x == b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
8523   if (!mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
8524   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
8525 
8526   if (!mat->ops->solves) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)mat)->type_name);
8527   MatCheckPreallocated(mat,1);
8528   ierr = PetscLogEventBegin(MAT_Solves,mat,0,0,0);CHKERRQ(ierr);
8529   ierr = (*mat->ops->solves)(mat,b,x);CHKERRQ(ierr);
8530   ierr = PetscLogEventEnd(MAT_Solves,mat,0,0,0);CHKERRQ(ierr);
8531   PetscFunctionReturn(0);
8532 }
8533 
8534 /*@
8535    MatIsSymmetric - Test whether a matrix is symmetric
8536 
8537    Collective on Mat
8538 
8539    Input Parameter:
8540 +  A - the matrix to test
8541 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8542 
8543    Output Parameters:
8544 .  flg - the result
8545 
8546    Notes:
8547     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
8548 
8549    Level: intermediate
8550 
8551    Concepts: matrix^symmetry
8552 
8553 .seealso: MatTranspose(), MatIsTranspose(), MatIsHermitian(), MatIsStructurallySymmetric(), MatSetOption(), MatIsSymmetricKnown()
8554 @*/
8555 PetscErrorCode MatIsSymmetric(Mat A,PetscReal tol,PetscBool  *flg)
8556 {
8557   PetscErrorCode ierr;
8558 
8559   PetscFunctionBegin;
8560   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8561   PetscValidPointer(flg,2);
8562 
8563   if (!A->symmetric_set) {
8564     if (!A->ops->issymmetric) {
8565       MatType mattype;
8566       ierr = MatGetType(A,&mattype);CHKERRQ(ierr);
8567       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type <%s> does not support checking for symmetric",mattype);
8568     }
8569     ierr = (*A->ops->issymmetric)(A,tol,flg);CHKERRQ(ierr);
8570     if (!tol) {
8571       A->symmetric_set = PETSC_TRUE;
8572       A->symmetric     = *flg;
8573       if (A->symmetric) {
8574         A->structurally_symmetric_set = PETSC_TRUE;
8575         A->structurally_symmetric     = PETSC_TRUE;
8576       }
8577     }
8578   } else if (A->symmetric) {
8579     *flg = PETSC_TRUE;
8580   } else if (!tol) {
8581     *flg = PETSC_FALSE;
8582   } else {
8583     if (!A->ops->issymmetric) {
8584       MatType mattype;
8585       ierr = MatGetType(A,&mattype);CHKERRQ(ierr);
8586       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type <%s> does not support checking for symmetric",mattype);
8587     }
8588     ierr = (*A->ops->issymmetric)(A,tol,flg);CHKERRQ(ierr);
8589   }
8590   PetscFunctionReturn(0);
8591 }
8592 
8593 /*@
8594    MatIsHermitian - Test whether a matrix is Hermitian
8595 
8596    Collective on Mat
8597 
8598    Input Parameter:
8599 +  A - the matrix to test
8600 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8601 
8602    Output Parameters:
8603 .  flg - the result
8604 
8605    Level: intermediate
8606 
8607    Concepts: matrix^symmetry
8608 
8609 .seealso: MatTranspose(), MatIsTranspose(), MatIsHermitian(), MatIsStructurallySymmetric(), MatSetOption(),
8610           MatIsSymmetricKnown(), MatIsSymmetric()
8611 @*/
8612 PetscErrorCode MatIsHermitian(Mat A,PetscReal tol,PetscBool  *flg)
8613 {
8614   PetscErrorCode ierr;
8615 
8616   PetscFunctionBegin;
8617   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8618   PetscValidPointer(flg,2);
8619 
8620   if (!A->hermitian_set) {
8621     if (!A->ops->ishermitian) {
8622       MatType mattype;
8623       ierr = MatGetType(A,&mattype);CHKERRQ(ierr);
8624       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type <%s> does not support checking for hermitian",mattype);
8625     }
8626     ierr = (*A->ops->ishermitian)(A,tol,flg);CHKERRQ(ierr);
8627     if (!tol) {
8628       A->hermitian_set = PETSC_TRUE;
8629       A->hermitian     = *flg;
8630       if (A->hermitian) {
8631         A->structurally_symmetric_set = PETSC_TRUE;
8632         A->structurally_symmetric     = PETSC_TRUE;
8633       }
8634     }
8635   } else if (A->hermitian) {
8636     *flg = PETSC_TRUE;
8637   } else if (!tol) {
8638     *flg = PETSC_FALSE;
8639   } else {
8640     if (!A->ops->ishermitian) {
8641       MatType mattype;
8642       ierr = MatGetType(A,&mattype);CHKERRQ(ierr);
8643       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Matrix of type <%s> does not support checking for hermitian",mattype);
8644     }
8645     ierr = (*A->ops->ishermitian)(A,tol,flg);CHKERRQ(ierr);
8646   }
8647   PetscFunctionReturn(0);
8648 }
8649 
8650 /*@
8651    MatIsSymmetricKnown - Checks the flag on the matrix to see if it is symmetric.
8652 
8653    Not Collective
8654 
8655    Input Parameter:
8656 .  A - the matrix to check
8657 
8658    Output Parameters:
8659 +  set - if the symmetric flag is set (this tells you if the next flag is valid)
8660 -  flg - the result
8661 
8662    Level: advanced
8663 
8664    Concepts: matrix^symmetry
8665 
8666    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsSymmetric()
8667          if you want it explicitly checked
8668 
8669 .seealso: MatTranspose(), MatIsTranspose(), MatIsHermitian(), MatIsStructurallySymmetric(), MatSetOption(), MatIsSymmetric()
8670 @*/
8671 PetscErrorCode MatIsSymmetricKnown(Mat A,PetscBool  *set,PetscBool  *flg)
8672 {
8673   PetscFunctionBegin;
8674   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8675   PetscValidPointer(set,2);
8676   PetscValidPointer(flg,3);
8677   if (A->symmetric_set) {
8678     *set = PETSC_TRUE;
8679     *flg = A->symmetric;
8680   } else {
8681     *set = PETSC_FALSE;
8682   }
8683   PetscFunctionReturn(0);
8684 }
8685 
8686 /*@
8687    MatIsHermitianKnown - Checks the flag on the matrix to see if it is hermitian.
8688 
8689    Not Collective
8690 
8691    Input Parameter:
8692 .  A - the matrix to check
8693 
8694    Output Parameters:
8695 +  set - if the hermitian flag is set (this tells you if the next flag is valid)
8696 -  flg - the result
8697 
8698    Level: advanced
8699 
8700    Concepts: matrix^symmetry
8701 
8702    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsHermitian()
8703          if you want it explicitly checked
8704 
8705 .seealso: MatTranspose(), MatIsTranspose(), MatIsHermitian(), MatIsStructurallySymmetric(), MatSetOption(), MatIsSymmetric()
8706 @*/
8707 PetscErrorCode MatIsHermitianKnown(Mat A,PetscBool  *set,PetscBool  *flg)
8708 {
8709   PetscFunctionBegin;
8710   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8711   PetscValidPointer(set,2);
8712   PetscValidPointer(flg,3);
8713   if (A->hermitian_set) {
8714     *set = PETSC_TRUE;
8715     *flg = A->hermitian;
8716   } else {
8717     *set = PETSC_FALSE;
8718   }
8719   PetscFunctionReturn(0);
8720 }
8721 
8722 /*@
8723    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
8724 
8725    Collective on Mat
8726 
8727    Input Parameter:
8728 .  A - the matrix to test
8729 
8730    Output Parameters:
8731 .  flg - the result
8732 
8733    Level: intermediate
8734 
8735    Concepts: matrix^symmetry
8736 
8737 .seealso: MatTranspose(), MatIsTranspose(), MatIsHermitian(), MatIsSymmetric(), MatSetOption()
8738 @*/
8739 PetscErrorCode MatIsStructurallySymmetric(Mat A,PetscBool  *flg)
8740 {
8741   PetscErrorCode ierr;
8742 
8743   PetscFunctionBegin;
8744   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
8745   PetscValidPointer(flg,2);
8746   if (!A->structurally_symmetric_set) {
8747     if (!A->ops->isstructurallysymmetric) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Matrix does not support checking for structural symmetric");
8748     ierr = (*A->ops->isstructurallysymmetric)(A,&A->structurally_symmetric);CHKERRQ(ierr);
8749 
8750     A->structurally_symmetric_set = PETSC_TRUE;
8751   }
8752   *flg = A->structurally_symmetric;
8753   PetscFunctionReturn(0);
8754 }
8755 
8756 /*@
8757    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
8758        to be communicated to other processors during the MatAssemblyBegin/End() process
8759 
8760     Not collective
8761 
8762    Input Parameter:
8763 .   vec - the vector
8764 
8765    Output Parameters:
8766 +   nstash   - the size of the stash
8767 .   reallocs - the number of additional mallocs incurred.
8768 .   bnstash   - the size of the block stash
8769 -   breallocs - the number of additional mallocs incurred.in the block stash
8770 
8771    Level: advanced
8772 
8773 .seealso: MatAssemblyBegin(), MatAssemblyEnd(), Mat, MatStashSetInitialSize()
8774 
8775 @*/
8776 PetscErrorCode MatStashGetInfo(Mat mat,PetscInt *nstash,PetscInt *reallocs,PetscInt *bnstash,PetscInt *breallocs)
8777 {
8778   PetscErrorCode ierr;
8779 
8780   PetscFunctionBegin;
8781   ierr = MatStashGetInfo_Private(&mat->stash,nstash,reallocs);CHKERRQ(ierr);
8782   ierr = MatStashGetInfo_Private(&mat->bstash,bnstash,breallocs);CHKERRQ(ierr);
8783   PetscFunctionReturn(0);
8784 }
8785 
8786 /*@C
8787    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
8788      parallel layout
8789 
8790    Collective on Mat
8791 
8792    Input Parameter:
8793 .  mat - the matrix
8794 
8795    Output Parameter:
8796 +   right - (optional) vector that the matrix can be multiplied against
8797 -   left - (optional) vector that the matrix vector product can be stored in
8798 
8799    Notes:
8800     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().
8801 
8802   Notes:
8803     These are new vectors which are not owned by the Mat, they should be destroyed in VecDestroy() when no longer needed
8804 
8805   Level: advanced
8806 
8807 .seealso: MatCreate(), VecDestroy()
8808 @*/
8809 PetscErrorCode MatCreateVecs(Mat mat,Vec *right,Vec *left)
8810 {
8811   PetscErrorCode ierr;
8812 
8813   PetscFunctionBegin;
8814   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8815   PetscValidType(mat,1);
8816   if (mat->ops->getvecs) {
8817     ierr = (*mat->ops->getvecs)(mat,right,left);CHKERRQ(ierr);
8818   } else {
8819     PetscInt rbs,cbs;
8820     ierr = MatGetBlockSizes(mat,&rbs,&cbs);CHKERRQ(ierr);
8821     if (right) {
8822       if (mat->cmap->n < 0) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for columns not yet setup");
8823       ierr = VecCreate(PetscObjectComm((PetscObject)mat),right);CHKERRQ(ierr);
8824       ierr = VecSetSizes(*right,mat->cmap->n,PETSC_DETERMINE);CHKERRQ(ierr);
8825       ierr = VecSetBlockSize(*right,cbs);CHKERRQ(ierr);
8826       ierr = VecSetType(*right,VECSTANDARD);CHKERRQ(ierr);
8827       ierr = PetscLayoutReference(mat->cmap,&(*right)->map);CHKERRQ(ierr);
8828     }
8829     if (left) {
8830       if (mat->rmap->n < 0) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"PetscLayout for rows not yet setup");
8831       ierr = VecCreate(PetscObjectComm((PetscObject)mat),left);CHKERRQ(ierr);
8832       ierr = VecSetSizes(*left,mat->rmap->n,PETSC_DETERMINE);CHKERRQ(ierr);
8833       ierr = VecSetBlockSize(*left,rbs);CHKERRQ(ierr);
8834       ierr = VecSetType(*left,VECSTANDARD);CHKERRQ(ierr);
8835       ierr = PetscLayoutReference(mat->rmap,&(*left)->map);CHKERRQ(ierr);
8836     }
8837   }
8838   PetscFunctionReturn(0);
8839 }
8840 
8841 /*@C
8842    MatFactorInfoInitialize - Initializes a MatFactorInfo data structure
8843      with default values.
8844 
8845    Not Collective
8846 
8847    Input Parameters:
8848 .    info - the MatFactorInfo data structure
8849 
8850 
8851    Notes:
8852     The solvers are generally used through the KSP and PC objects, for example
8853           PCLU, PCILU, PCCHOLESKY, PCICC
8854 
8855    Level: developer
8856 
8857 .seealso: MatFactorInfo
8858 
8859     Developer Note: fortran interface is not autogenerated as the f90
8860     interface defintion cannot be generated correctly [due to MatFactorInfo]
8861 
8862 @*/
8863 
8864 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
8865 {
8866   PetscErrorCode ierr;
8867 
8868   PetscFunctionBegin;
8869   ierr = PetscMemzero(info,sizeof(MatFactorInfo));CHKERRQ(ierr);
8870   PetscFunctionReturn(0);
8871 }
8872 
8873 /*@
8874    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
8875 
8876    Collective on Mat
8877 
8878    Input Parameters:
8879 +  mat - the factored matrix
8880 -  is - the index set defining the Schur indices (0-based)
8881 
8882    Notes:
8883     Call MatFactorSolveSchurComplement() or MatFactorSolveSchurComplementTranspose() after this call to solve a Schur complement system.
8884 
8885    You can call MatFactorGetSchurComplement() or MatFactorCreateSchurComplement() after this call.
8886 
8887    Level: developer
8888 
8889    Concepts:
8890 
8891 .seealso: MatGetFactor(), MatFactorGetSchurComplement(), MatFactorRestoreSchurComplement(), MatFactorCreateSchurComplement(), MatFactorSolveSchurComplement(),
8892           MatFactorSolveSchurComplementTranspose(), MatFactorSolveSchurComplement()
8893 
8894 @*/
8895 PetscErrorCode MatFactorSetSchurIS(Mat mat,IS is)
8896 {
8897   PetscErrorCode ierr,(*f)(Mat,IS);
8898 
8899   PetscFunctionBegin;
8900   PetscValidType(mat,1);
8901   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8902   PetscValidType(is,2);
8903   PetscValidHeaderSpecific(is,IS_CLASSID,2);
8904   PetscCheckSameComm(mat,1,is,2);
8905   if (!mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Only for factored matrix");
8906   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatFactorSetSchurIS_C",&f);CHKERRQ(ierr);
8907   if (!f) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
8908   if (mat->schur) {
8909     ierr = MatDestroy(&mat->schur);CHKERRQ(ierr);
8910   }
8911   ierr = (*f)(mat,is);CHKERRQ(ierr);
8912   if (!mat->schur) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Schur complement has not been created");
8913   ierr = MatFactorSetUpInPlaceSchur_Private(mat);CHKERRQ(ierr);
8914   PetscFunctionReturn(0);
8915 }
8916 
8917 /*@
8918   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
8919 
8920    Logically Collective on Mat
8921 
8922    Input Parameters:
8923 +  F - the factored matrix obtained by calling MatGetFactor() from PETSc-MUMPS interface
8924 .  S - location where to return the Schur complement, can be NULL
8925 -  status - the status of the Schur complement matrix, can be NULL
8926 
8927    Notes:
8928    You must call MatFactorSetSchurIS() before calling this routine.
8929 
8930    The routine provides a copy of the Schur matrix stored within the solver data structures.
8931    The caller must destroy the object when it is no longer needed.
8932    If MatFactorInvertSchurComplement() has been called, the routine gets back the inverse.
8933 
8934    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)
8935 
8936    Developer Notes:
8937     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
8938    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
8939 
8940    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
8941 
8942    Level: advanced
8943 
8944    References:
8945 
8946 .seealso: MatGetFactor(), MatFactorSetSchurIS(), MatFactorGetSchurComplement(), MatFactorSchurStatus
8947 @*/
8948 PetscErrorCode MatFactorCreateSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
8949 {
8950   PetscErrorCode ierr;
8951 
8952   PetscFunctionBegin;
8953   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
8954   if (S) PetscValidPointer(S,2);
8955   if (status) PetscValidPointer(status,3);
8956   if (S) {
8957     PetscErrorCode (*f)(Mat,Mat*);
8958 
8959     ierr = PetscObjectQueryFunction((PetscObject)F,"MatFactorCreateSchurComplement_C",&f);CHKERRQ(ierr);
8960     if (f) {
8961       ierr = (*f)(F,S);CHKERRQ(ierr);
8962     } else {
8963       ierr = MatDuplicate(F->schur,MAT_COPY_VALUES,S);CHKERRQ(ierr);
8964     }
8965   }
8966   if (status) *status = F->schur_status;
8967   PetscFunctionReturn(0);
8968 }
8969 
8970 /*@
8971   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
8972 
8973    Logically Collective on Mat
8974 
8975    Input Parameters:
8976 +  F - the factored matrix obtained by calling MatGetFactor()
8977 .  *S - location where to return the Schur complement, can be NULL
8978 -  status - the status of the Schur complement matrix, can be NULL
8979 
8980    Notes:
8981    You must call MatFactorSetSchurIS() before calling this routine.
8982 
8983    Schur complement mode is currently implemented for sequential matrices.
8984    The routine returns a the Schur Complement stored within the data strutures of the solver.
8985    If MatFactorInvertSchurComplement() has previously been called, the returned matrix is actually the inverse of the Schur complement.
8986    The returned matrix should not be destroyed; the caller should call MatFactorRestoreSchurComplement() when the object is no longer needed.
8987 
8988    Use MatFactorCreateSchurComplement() to create a copy of the Schur complement matrix that is within a factored matrix
8989 
8990    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
8991 
8992    Level: advanced
8993 
8994    References:
8995 
8996 .seealso: MatGetFactor(), MatFactorSetSchurIS(), MatFactorRestoreSchurComplement(), MatFactorCreateSchurComplement(), MatFactorSchurStatus
8997 @*/
8998 PetscErrorCode MatFactorGetSchurComplement(Mat F,Mat* S,MatFactorSchurStatus* status)
8999 {
9000   PetscFunctionBegin;
9001   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9002   if (S) PetscValidPointer(S,2);
9003   if (status) PetscValidPointer(status,3);
9004   if (S) *S = F->schur;
9005   if (status) *status = F->schur_status;
9006   PetscFunctionReturn(0);
9007 }
9008 
9009 /*@
9010   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to MatFactorGetSchurComplement
9011 
9012    Logically Collective on Mat
9013 
9014    Input Parameters:
9015 +  F - the factored matrix obtained by calling MatGetFactor()
9016 .  *S - location where the Schur complement is stored
9017 -  status - the status of the Schur complement matrix (see MatFactorSchurStatus)
9018 
9019    Notes:
9020 
9021    Level: advanced
9022 
9023    References:
9024 
9025 .seealso: MatGetFactor(), MatFactorSetSchurIS(), MatFactorRestoreSchurComplement(), MatFactorCreateSchurComplement(), MatFactorSchurStatus
9026 @*/
9027 PetscErrorCode MatFactorRestoreSchurComplement(Mat F,Mat* S,MatFactorSchurStatus status)
9028 {
9029   PetscErrorCode ierr;
9030 
9031   PetscFunctionBegin;
9032   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9033   if (S) {
9034     PetscValidHeaderSpecific(*S,MAT_CLASSID,2);
9035     *S = NULL;
9036   }
9037   F->schur_status = status;
9038   ierr = MatFactorUpdateSchurStatus_Private(F);CHKERRQ(ierr);
9039   PetscFunctionReturn(0);
9040 }
9041 
9042 /*@
9043   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9044 
9045    Logically Collective on Mat
9046 
9047    Input Parameters:
9048 +  F - the factored matrix obtained by calling MatGetFactor()
9049 .  rhs - location where the right hand side of the Schur complement system is stored
9050 -  sol - location where the solution of the Schur complement system has to be returned
9051 
9052    Notes:
9053    The sizes of the vectors should match the size of the Schur complement
9054 
9055    Must be called after MatFactorSetSchurIS()
9056 
9057    Level: advanced
9058 
9059    References:
9060 
9061 .seealso: MatGetFactor(), MatFactorSetSchurIS(), MatFactorSolveSchurComplement()
9062 @*/
9063 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9064 {
9065   PetscErrorCode ierr;
9066 
9067   PetscFunctionBegin;
9068   PetscValidType(F,1);
9069   PetscValidType(rhs,2);
9070   PetscValidType(sol,3);
9071   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9072   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9073   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9074   PetscCheckSameComm(F,1,rhs,2);
9075   PetscCheckSameComm(F,1,sol,3);
9076   ierr = MatFactorFactorizeSchurComplement(F);CHKERRQ(ierr);
9077   switch (F->schur_status) {
9078   case MAT_FACTOR_SCHUR_FACTORED:
9079     ierr = MatSolveTranspose(F->schur,rhs,sol);CHKERRQ(ierr);
9080     break;
9081   case MAT_FACTOR_SCHUR_INVERTED:
9082     ierr = MatMultTranspose(F->schur,rhs,sol);CHKERRQ(ierr);
9083     break;
9084   default:
9085     SETERRQ1(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %D",F->schur_status);
9086     break;
9087   }
9088   PetscFunctionReturn(0);
9089 }
9090 
9091 /*@
9092   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9093 
9094    Logically Collective on Mat
9095 
9096    Input Parameters:
9097 +  F - the factored matrix obtained by calling MatGetFactor()
9098 .  rhs - location where the right hand side of the Schur complement system is stored
9099 -  sol - location where the solution of the Schur complement system has to be returned
9100 
9101    Notes:
9102    The sizes of the vectors should match the size of the Schur complement
9103 
9104    Must be called after MatFactorSetSchurIS()
9105 
9106    Level: advanced
9107 
9108    References:
9109 
9110 .seealso: MatGetFactor(), MatFactorSetSchurIS(), MatFactorSolveSchurComplementTranspose()
9111 @*/
9112 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9113 {
9114   PetscErrorCode ierr;
9115 
9116   PetscFunctionBegin;
9117   PetscValidType(F,1);
9118   PetscValidType(rhs,2);
9119   PetscValidType(sol,3);
9120   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9121   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
9122   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
9123   PetscCheckSameComm(F,1,rhs,2);
9124   PetscCheckSameComm(F,1,sol,3);
9125   ierr = MatFactorFactorizeSchurComplement(F);CHKERRQ(ierr);
9126   switch (F->schur_status) {
9127   case MAT_FACTOR_SCHUR_FACTORED:
9128     ierr = MatSolve(F->schur,rhs,sol);CHKERRQ(ierr);
9129     break;
9130   case MAT_FACTOR_SCHUR_INVERTED:
9131     ierr = MatMult(F->schur,rhs,sol);CHKERRQ(ierr);
9132     break;
9133   default:
9134     SETERRQ1(PetscObjectComm((PetscObject)F),PETSC_ERR_SUP,"Unhandled MatFactorSchurStatus %D",F->schur_status);
9135     break;
9136   }
9137   PetscFunctionReturn(0);
9138 }
9139 
9140 /*@
9141   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9142 
9143    Logically Collective on Mat
9144 
9145    Input Parameters:
9146 +  F - the factored matrix obtained by calling MatGetFactor()
9147 
9148    Notes:
9149     Must be called after MatFactorSetSchurIS().
9150 
9151    Call MatFactorGetSchurComplement() or  MatFactorCreateSchurComplement() AFTER this call to actually compute the inverse and get access to it.
9152 
9153    Level: advanced
9154 
9155    References:
9156 
9157 .seealso: MatGetFactor(), MatFactorSetSchurIS(), MatFactorGetSchurComplement(), MatFactorCreateSchurComplement()
9158 @*/
9159 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9160 {
9161   PetscErrorCode ierr;
9162 
9163   PetscFunctionBegin;
9164   PetscValidType(F,1);
9165   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9166   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9167   ierr = MatFactorFactorizeSchurComplement(F);CHKERRQ(ierr);
9168   ierr = MatFactorInvertSchurComplement_Private(F);CHKERRQ(ierr);
9169   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9170   PetscFunctionReturn(0);
9171 }
9172 
9173 /*@
9174   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9175 
9176    Logically Collective on Mat
9177 
9178    Input Parameters:
9179 +  F - the factored matrix obtained by calling MatGetFactor()
9180 
9181    Notes:
9182     Must be called after MatFactorSetSchurIS().
9183 
9184    Level: advanced
9185 
9186    References:
9187 
9188 .seealso: MatGetFactor(), MatFactorSetSchurIS(), MatFactorInvertSchurComplement()
9189 @*/
9190 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9191 {
9192   PetscErrorCode ierr;
9193 
9194   PetscFunctionBegin;
9195   PetscValidType(F,1);
9196   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
9197   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9198   ierr = MatFactorFactorizeSchurComplement_Private(F);CHKERRQ(ierr);
9199   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9200   PetscFunctionReturn(0);
9201 }
9202 
9203 /*@
9204    MatPtAP - Creates the matrix product C = P^T * A * P
9205 
9206    Neighbor-wise Collective on Mat
9207 
9208    Input Parameters:
9209 +  A - the matrix
9210 .  P - the projection matrix
9211 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9212 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use PETSC_DEFAULT if you do not have a good estimate
9213           if the result is a dense matrix this is irrelevent
9214 
9215    Output Parameters:
9216 .  C - the product matrix
9217 
9218    Notes:
9219    C will be created and must be destroyed by the user with MatDestroy().
9220 
9221    This routine is currently only implemented for pairs of sequential dense matrices, AIJ matrices and classes
9222    which inherit from AIJ.
9223 
9224    Level: intermediate
9225 
9226 .seealso: MatPtAPSymbolic(), MatPtAPNumeric(), MatMatMult(), MatRARt()
9227 @*/
9228 PetscErrorCode MatPtAP(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
9229 {
9230   PetscErrorCode ierr;
9231   PetscErrorCode (*fA)(Mat,Mat,MatReuse,PetscReal,Mat*);
9232   PetscErrorCode (*fP)(Mat,Mat,MatReuse,PetscReal,Mat*);
9233   PetscErrorCode (*ptap)(Mat,Mat,MatReuse,PetscReal,Mat*)=NULL;
9234   PetscBool      sametype;
9235 
9236   PetscFunctionBegin;
9237   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9238   PetscValidType(A,1);
9239   MatCheckPreallocated(A,1);
9240   if (scall == MAT_INPLACE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9241   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9242   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9243   PetscValidHeaderSpecific(P,MAT_CLASSID,2);
9244   PetscValidType(P,2);
9245   MatCheckPreallocated(P,2);
9246   if (!P->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9247   if (P->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9248 
9249   if (A->rmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix A must be square, %D != %D",A->rmap->N,A->cmap->N);
9250   if (P->rmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",P->rmap->N,A->cmap->N);
9251   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) fill = 2.0;
9252   if (fill < 1.0) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Expected fill=%g must be >= 1.0",(double)fill);
9253 
9254   if (scall == MAT_REUSE_MATRIX) {
9255     PetscValidPointer(*C,5);
9256     PetscValidHeaderSpecific(*C,MAT_CLASSID,5);
9257 
9258     if (!(*C)->ops->ptapnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"MatPtAPNumeric implementation is missing. You cannot use MAT_REUSE_MATRIX");
9259     ierr = PetscLogEventBegin(MAT_PtAP,A,P,0,0);CHKERRQ(ierr);
9260     ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
9261     ierr = (*(*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
9262     ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
9263     ierr = PetscLogEventEnd(MAT_PtAP,A,P,0,0);CHKERRQ(ierr);
9264     PetscFunctionReturn(0);
9265   }
9266 
9267   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) fill = 2.0;
9268   if (fill < 1.0) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Expected fill=%g must be >= 1.0",(double)fill);
9269 
9270   fA = A->ops->ptap;
9271   fP = P->ops->ptap;
9272   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)P)->type_name,&sametype);CHKERRQ(ierr);
9273   if (fP == fA && sametype) {
9274     if (!fA) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatPtAP not supported for A of type %s",((PetscObject)A)->type_name);
9275     ptap = fA;
9276   } else {
9277     /* dispatch based on the type of A and P from their PetscObject's PetscFunctionLists. */
9278     char ptapname[256];
9279     ierr = PetscStrncpy(ptapname,"MatPtAP_",sizeof(ptapname));CHKERRQ(ierr);
9280     ierr = PetscStrlcat(ptapname,((PetscObject)A)->type_name,sizeof(ptapname));CHKERRQ(ierr);
9281     ierr = PetscStrlcat(ptapname,"_",sizeof(ptapname));CHKERRQ(ierr);
9282     ierr = PetscStrlcat(ptapname,((PetscObject)P)->type_name,sizeof(ptapname));CHKERRQ(ierr);
9283     ierr = PetscStrlcat(ptapname,"_C",sizeof(ptapname));CHKERRQ(ierr); /* e.g., ptapname = "MatPtAP_seqdense_seqaij_C" */
9284     ierr = PetscObjectQueryFunction((PetscObject)P,ptapname,&ptap);CHKERRQ(ierr);
9285     if (!ptap) SETERRQ3(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"MatPtAP requires A, %s, to be compatible with P, %s (Misses composed function %s)",((PetscObject)A)->type_name,((PetscObject)P)->type_name,ptapname);
9286   }
9287 
9288   ierr = PetscLogEventBegin(MAT_PtAP,A,P,0,0);CHKERRQ(ierr);
9289   ierr = (*ptap)(A,P,scall,fill,C);CHKERRQ(ierr);
9290   ierr = PetscLogEventEnd(MAT_PtAP,A,P,0,0);CHKERRQ(ierr);
9291   PetscFunctionReturn(0);
9292 }
9293 
9294 /*@
9295    MatPtAPNumeric - Computes the matrix product C = P^T * A * P
9296 
9297    Neighbor-wise Collective on Mat
9298 
9299    Input Parameters:
9300 +  A - the matrix
9301 -  P - the projection matrix
9302 
9303    Output Parameters:
9304 .  C - the product matrix
9305 
9306    Notes:
9307    C must have been created by calling MatPtAPSymbolic and must be destroyed by
9308    the user using MatDeatroy().
9309 
9310    This routine is currently only implemented for pairs of AIJ matrices and classes
9311    which inherit from AIJ.  C will be of type MATAIJ.
9312 
9313    Level: intermediate
9314 
9315 .seealso: MatPtAP(), MatPtAPSymbolic(), MatMatMultNumeric()
9316 @*/
9317 PetscErrorCode MatPtAPNumeric(Mat A,Mat P,Mat C)
9318 {
9319   PetscErrorCode ierr;
9320 
9321   PetscFunctionBegin;
9322   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9323   PetscValidType(A,1);
9324   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9325   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9326   PetscValidHeaderSpecific(P,MAT_CLASSID,2);
9327   PetscValidType(P,2);
9328   MatCheckPreallocated(P,2);
9329   if (!P->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9330   if (P->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9331   PetscValidHeaderSpecific(C,MAT_CLASSID,3);
9332   PetscValidType(C,3);
9333   MatCheckPreallocated(C,3);
9334   if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9335   if (P->cmap->N!=C->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",P->cmap->N,C->rmap->N);
9336   if (P->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",P->rmap->N,A->cmap->N);
9337   if (A->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %D != %D",A->rmap->N,A->cmap->N);
9338   if (P->cmap->N!=C->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",P->cmap->N,C->cmap->N);
9339   MatCheckPreallocated(A,1);
9340 
9341   if (!C->ops->ptapnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"MatPtAPNumeric implementation is missing. You should call MatPtAPSymbolic first");
9342   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
9343   ierr = (*C->ops->ptapnumeric)(A,P,C);CHKERRQ(ierr);
9344   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
9345   PetscFunctionReturn(0);
9346 }
9347 
9348 /*@
9349    MatPtAPSymbolic - Creates the (i,j) structure of the matrix product C = P^T * A * P
9350 
9351    Neighbor-wise Collective on Mat
9352 
9353    Input Parameters:
9354 +  A - the matrix
9355 -  P - the projection matrix
9356 
9357    Output Parameters:
9358 .  C - the (i,j) structure of the product matrix
9359 
9360    Notes:
9361    C will be created and must be destroyed by the user with MatDestroy().
9362 
9363    This routine is currently only implemented for pairs of SeqAIJ matrices and classes
9364    which inherit from SeqAIJ.  C will be of type MATSEQAIJ.  The product is computed using
9365    this (i,j) structure by calling MatPtAPNumeric().
9366 
9367    Level: intermediate
9368 
9369 .seealso: MatPtAP(), MatPtAPNumeric(), MatMatMultSymbolic()
9370 @*/
9371 PetscErrorCode MatPtAPSymbolic(Mat A,Mat P,PetscReal fill,Mat *C)
9372 {
9373   PetscErrorCode ierr;
9374 
9375   PetscFunctionBegin;
9376   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9377   PetscValidType(A,1);
9378   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9379   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9380   if (fill <1.0) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Expected fill=%g must be >= 1.0",(double)fill);
9381   PetscValidHeaderSpecific(P,MAT_CLASSID,2);
9382   PetscValidType(P,2);
9383   MatCheckPreallocated(P,2);
9384   if (!P->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9385   if (P->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9386   PetscValidPointer(C,3);
9387 
9388   if (P->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",P->rmap->N,A->cmap->N);
9389   if (A->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %D != %D",A->rmap->N,A->cmap->N);
9390   MatCheckPreallocated(A,1);
9391 
9392   if (!A->ops->ptapsymbolic) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatType %s",((PetscObject)A)->type_name);
9393   ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
9394   ierr = (*A->ops->ptapsymbolic)(A,P,fill,C);CHKERRQ(ierr);
9395   ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
9396 
9397   /* ierr = MatSetBlockSize(*C,A->rmap->bs);CHKERRQ(ierr); NO! this is not always true -ma */
9398   PetscFunctionReturn(0);
9399 }
9400 
9401 /*@
9402    MatRARt - Creates the matrix product C = R * A * R^T
9403 
9404    Neighbor-wise Collective on Mat
9405 
9406    Input Parameters:
9407 +  A - the matrix
9408 .  R - the projection matrix
9409 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9410 -  fill - expected fill as ratio of nnz(C)/nnz(A), use PETSC_DEFAULT if you do not have a good estimate
9411           if the result is a dense matrix this is irrelevent
9412 
9413    Output Parameters:
9414 .  C - the product matrix
9415 
9416    Notes:
9417    C will be created and must be destroyed by the user with MatDestroy().
9418 
9419    This routine is currently only implemented for pairs of AIJ matrices and classes
9420    which inherit from AIJ. Due to PETSc sparse matrix block row distribution among processes,
9421    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9422    We recommend using MatPtAP().
9423 
9424    Level: intermediate
9425 
9426 .seealso: MatRARtSymbolic(), MatRARtNumeric(), MatMatMult(), MatPtAP()
9427 @*/
9428 PetscErrorCode MatRARt(Mat A,Mat R,MatReuse scall,PetscReal fill,Mat *C)
9429 {
9430   PetscErrorCode ierr;
9431 
9432   PetscFunctionBegin;
9433   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9434   PetscValidType(A,1);
9435   if (scall == MAT_INPLACE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9436   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9437   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9438   PetscValidHeaderSpecific(R,MAT_CLASSID,2);
9439   PetscValidType(R,2);
9440   MatCheckPreallocated(R,2);
9441   if (!R->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9442   if (R->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9443   PetscValidPointer(C,3);
9444   if (R->cmap->N!=A->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)R),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",R->cmap->N,A->rmap->N);
9445 
9446   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) fill = 2.0;
9447   if (fill < 1.0) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Expected fill=%g must be >= 1.0",(double)fill);
9448   MatCheckPreallocated(A,1);
9449 
9450   if (!A->ops->rart) {
9451     Mat Rt;
9452     ierr = MatTranspose(R,MAT_INITIAL_MATRIX,&Rt);CHKERRQ(ierr);
9453     ierr = MatMatMatMult(R,A,Rt,scall,fill,C);CHKERRQ(ierr);
9454     ierr = MatDestroy(&Rt);CHKERRQ(ierr);
9455     PetscFunctionReturn(0);
9456   }
9457   ierr = PetscLogEventBegin(MAT_RARt,A,R,0,0);CHKERRQ(ierr);
9458   ierr = (*A->ops->rart)(A,R,scall,fill,C);CHKERRQ(ierr);
9459   ierr = PetscLogEventEnd(MAT_RARt,A,R,0,0);CHKERRQ(ierr);
9460   PetscFunctionReturn(0);
9461 }
9462 
9463 /*@
9464    MatRARtNumeric - Computes the matrix product C = R * A * R^T
9465 
9466    Neighbor-wise Collective on Mat
9467 
9468    Input Parameters:
9469 +  A - the matrix
9470 -  R - the projection matrix
9471 
9472    Output Parameters:
9473 .  C - the product matrix
9474 
9475    Notes:
9476    C must have been created by calling MatRARtSymbolic and must be destroyed by
9477    the user using MatDestroy().
9478 
9479    This routine is currently only implemented for pairs of AIJ matrices and classes
9480    which inherit from AIJ.  C will be of type MATAIJ.
9481 
9482    Level: intermediate
9483 
9484 .seealso: MatRARt(), MatRARtSymbolic(), MatMatMultNumeric()
9485 @*/
9486 PetscErrorCode MatRARtNumeric(Mat A,Mat R,Mat C)
9487 {
9488   PetscErrorCode ierr;
9489 
9490   PetscFunctionBegin;
9491   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9492   PetscValidType(A,1);
9493   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9494   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9495   PetscValidHeaderSpecific(R,MAT_CLASSID,2);
9496   PetscValidType(R,2);
9497   MatCheckPreallocated(R,2);
9498   if (!R->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9499   if (R->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9500   PetscValidHeaderSpecific(C,MAT_CLASSID,3);
9501   PetscValidType(C,3);
9502   MatCheckPreallocated(C,3);
9503   if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9504   if (R->rmap->N!=C->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",R->rmap->N,C->rmap->N);
9505   if (R->cmap->N!=A->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",R->cmap->N,A->rmap->N);
9506   if (A->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %D != %D",A->rmap->N,A->cmap->N);
9507   if (R->rmap->N!=C->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",R->rmap->N,C->cmap->N);
9508   MatCheckPreallocated(A,1);
9509 
9510   ierr = PetscLogEventBegin(MAT_RARtNumeric,A,R,0,0);CHKERRQ(ierr);
9511   ierr = (*A->ops->rartnumeric)(A,R,C);CHKERRQ(ierr);
9512   ierr = PetscLogEventEnd(MAT_RARtNumeric,A,R,0,0);CHKERRQ(ierr);
9513   PetscFunctionReturn(0);
9514 }
9515 
9516 /*@
9517    MatRARtSymbolic - Creates the (i,j) structure of the matrix product C = R * A * R^T
9518 
9519    Neighbor-wise Collective on Mat
9520 
9521    Input Parameters:
9522 +  A - the matrix
9523 -  R - the projection matrix
9524 
9525    Output Parameters:
9526 .  C - the (i,j) structure of the product matrix
9527 
9528    Notes:
9529    C will be created and must be destroyed by the user with MatDestroy().
9530 
9531    This routine is currently only implemented for pairs of SeqAIJ matrices and classes
9532    which inherit from SeqAIJ.  C will be of type MATSEQAIJ.  The product is computed using
9533    this (i,j) structure by calling MatRARtNumeric().
9534 
9535    Level: intermediate
9536 
9537 .seealso: MatRARt(), MatRARtNumeric(), MatMatMultSymbolic()
9538 @*/
9539 PetscErrorCode MatRARtSymbolic(Mat A,Mat R,PetscReal fill,Mat *C)
9540 {
9541   PetscErrorCode ierr;
9542 
9543   PetscFunctionBegin;
9544   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9545   PetscValidType(A,1);
9546   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9547   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9548   if (fill <1.0) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Expected fill=%g must be >= 1.0",(double)fill);
9549   PetscValidHeaderSpecific(R,MAT_CLASSID,2);
9550   PetscValidType(R,2);
9551   MatCheckPreallocated(R,2);
9552   if (!R->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9553   if (R->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9554   PetscValidPointer(C,3);
9555 
9556   if (R->cmap->N!=A->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",R->cmap->N,A->rmap->N);
9557   if (A->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %D != %D",A->rmap->N,A->cmap->N);
9558   MatCheckPreallocated(A,1);
9559   ierr = PetscLogEventBegin(MAT_RARtSymbolic,A,R,0,0);CHKERRQ(ierr);
9560   ierr = (*A->ops->rartsymbolic)(A,R,fill,C);CHKERRQ(ierr);
9561   ierr = PetscLogEventEnd(MAT_RARtSymbolic,A,R,0,0);CHKERRQ(ierr);
9562 
9563   ierr = MatSetBlockSizes(*C,PetscAbs(R->rmap->bs),PetscAbs(R->rmap->bs));CHKERRQ(ierr);
9564   PetscFunctionReturn(0);
9565 }
9566 
9567 /*@
9568    MatMatMult - Performs Matrix-Matrix Multiplication C=A*B.
9569 
9570    Neighbor-wise Collective on Mat
9571 
9572    Input Parameters:
9573 +  A - the left matrix
9574 .  B - the right matrix
9575 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9576 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if you do not have a good estimate
9577           if the result is a dense matrix this is irrelevent
9578 
9579    Output Parameters:
9580 .  C - the product matrix
9581 
9582    Notes:
9583    Unless scall is MAT_REUSE_MATRIX C will be created.
9584 
9585    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
9586    call to this function with either MAT_INITIAL_MATRIX or MatMatMultSymbolic()
9587 
9588    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9589    actually needed.
9590 
9591    If you have many matrices with the same non-zero structure to multiply, you
9592    should either
9593 $   1) use MAT_REUSE_MATRIX in all calls but the first or
9594 $   2) call MatMatMultSymbolic() once and then MatMatMultNumeric() for each product needed
9595    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
9596    with MAT_REUSE_MATRIX, rather than first having MatMatMult() create it for you. You can NEVER do this if the matrix C is sparse.
9597 
9598    Level: intermediate
9599 
9600 .seealso: MatMatMultSymbolic(), MatMatMultNumeric(), MatTransposeMatMult(),  MatMatTransposeMult(), MatPtAP()
9601 @*/
9602 PetscErrorCode MatMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9603 {
9604   PetscErrorCode ierr;
9605   PetscErrorCode (*fA)(Mat,Mat,MatReuse,PetscReal,Mat*);
9606   PetscErrorCode (*fB)(Mat,Mat,MatReuse,PetscReal,Mat*);
9607   PetscErrorCode (*mult)(Mat,Mat,MatReuse,PetscReal,Mat*)=NULL;
9608 
9609   PetscFunctionBegin;
9610   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9611   PetscValidType(A,1);
9612   MatCheckPreallocated(A,1);
9613   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9614   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9615   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
9616   PetscValidType(B,2);
9617   MatCheckPreallocated(B,2);
9618   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9619   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9620   PetscValidPointer(C,3);
9621   if (scall == MAT_INPLACE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9622   if (B->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N);
9623   if (scall == MAT_REUSE_MATRIX) {
9624     PetscValidPointer(*C,5);
9625     PetscValidHeaderSpecific(*C,MAT_CLASSID,5);
9626     ierr = PetscLogEventBegin(MAT_MatMult,A,B,0,0);CHKERRQ(ierr);
9627     ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
9628     ierr = (*(*C)->ops->matmultnumeric)(A,B,*C);CHKERRQ(ierr);
9629     ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
9630     ierr = PetscLogEventEnd(MAT_MatMult,A,B,0,0);CHKERRQ(ierr);
9631     PetscFunctionReturn(0);
9632   }
9633   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) fill = 2.0;
9634   if (fill < 1.0) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Expected fill=%g must be >= 1.0",(double)fill);
9635 
9636   fA = A->ops->matmult;
9637   fB = B->ops->matmult;
9638   if (fB == fA) {
9639     if (!fB) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatMatMult not supported for B of type %s",((PetscObject)B)->type_name);
9640     mult = fB;
9641   } else {
9642     /* dispatch based on the type of A and B from their PetscObject's PetscFunctionLists. */
9643     char multname[256];
9644     ierr = PetscStrncpy(multname,"MatMatMult_",sizeof(multname));CHKERRQ(ierr);
9645     ierr = PetscStrlcat(multname,((PetscObject)A)->type_name,sizeof(multname));CHKERRQ(ierr);
9646     ierr = PetscStrlcat(multname,"_",sizeof(multname));CHKERRQ(ierr);
9647     ierr = PetscStrlcat(multname,((PetscObject)B)->type_name,sizeof(multname));CHKERRQ(ierr);
9648     ierr = PetscStrlcat(multname,"_C",sizeof(multname));CHKERRQ(ierr); /* e.g., multname = "MatMatMult_seqdense_seqaij_C" */
9649     ierr = PetscObjectQueryFunction((PetscObject)B,multname,&mult);CHKERRQ(ierr);
9650     if (!mult) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"MatMatMult requires A, %s, to be compatible with B, %s",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
9651   }
9652   ierr = PetscLogEventBegin(MAT_MatMult,A,B,0,0);CHKERRQ(ierr);
9653   ierr = (*mult)(A,B,scall,fill,C);CHKERRQ(ierr);
9654   ierr = PetscLogEventEnd(MAT_MatMult,A,B,0,0);CHKERRQ(ierr);
9655   PetscFunctionReturn(0);
9656 }
9657 
9658 /*@
9659    MatMatMultSymbolic - Performs construction, preallocation, and computes the ij structure
9660    of the matrix-matrix product C=A*B.  Call this routine before calling MatMatMultNumeric().
9661 
9662    Neighbor-wise Collective on Mat
9663 
9664    Input Parameters:
9665 +  A - the left matrix
9666 .  B - the right matrix
9667 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if you do not have a good estimate,
9668       if C is a dense matrix this is irrelevent
9669 
9670    Output Parameters:
9671 .  C - the product matrix
9672 
9673    Notes:
9674    Unless scall is MAT_REUSE_MATRIX C will be created.
9675 
9676    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9677    actually needed.
9678 
9679    This routine is currently implemented for
9680     - pairs of AIJ matrices and classes which inherit from AIJ, C will be of type AIJ
9681     - pairs of AIJ (A) and Dense (B) matrix, C will be of type Dense.
9682     - pairs of Dense (A) and AIJ (B) matrix, C will be of type Dense.
9683 
9684    Level: intermediate
9685 
9686    Developers Note: There are ways to estimate the number of nonzeros in the resulting product, see for example, http://arxiv.org/abs/1006.4173
9687      We should incorporate them into PETSc.
9688 
9689 .seealso: MatMatMult(), MatMatMultNumeric()
9690 @*/
9691 PetscErrorCode MatMatMultSymbolic(Mat A,Mat B,PetscReal fill,Mat *C)
9692 {
9693   PetscErrorCode ierr;
9694   PetscErrorCode (*Asymbolic)(Mat,Mat,PetscReal,Mat*);
9695   PetscErrorCode (*Bsymbolic)(Mat,Mat,PetscReal,Mat*);
9696   PetscErrorCode (*symbolic)(Mat,Mat,PetscReal,Mat*)=NULL;
9697 
9698   PetscFunctionBegin;
9699   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9700   PetscValidType(A,1);
9701   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9702   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9703 
9704   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
9705   PetscValidType(B,2);
9706   MatCheckPreallocated(B,2);
9707   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9708   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9709   PetscValidPointer(C,3);
9710 
9711   if (B->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N);
9712   if (fill == PETSC_DEFAULT) fill = 2.0;
9713   if (fill < 1.0) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Expected fill=%g must be > 1.0",(double)fill);
9714   MatCheckPreallocated(A,1);
9715 
9716   Asymbolic = A->ops->matmultsymbolic;
9717   Bsymbolic = B->ops->matmultsymbolic;
9718   if (Asymbolic == Bsymbolic) {
9719     if (!Bsymbolic) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"C=A*B not implemented for B of type %s",((PetscObject)B)->type_name);
9720     symbolic = Bsymbolic;
9721   } else { /* dispatch based on the type of A and B */
9722     char symbolicname[256];
9723     ierr = PetscStrncpy(symbolicname,"MatMatMultSymbolic_",sizeof(symbolicname));CHKERRQ(ierr);
9724     ierr = PetscStrlcat(symbolicname,((PetscObject)A)->type_name,sizeof(symbolicname));CHKERRQ(ierr);
9725     ierr = PetscStrlcat(symbolicname,"_",sizeof(symbolicname));CHKERRQ(ierr);
9726     ierr = PetscStrlcat(symbolicname,((PetscObject)B)->type_name,sizeof(symbolicname));CHKERRQ(ierr);
9727     ierr = PetscStrlcat(symbolicname,"_C",sizeof(symbolicname));CHKERRQ(ierr);
9728     ierr = PetscObjectQueryFunction((PetscObject)B,symbolicname,&symbolic);CHKERRQ(ierr);
9729     if (!symbolic) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"MatMatMultSymbolic requires A, %s, to be compatible with B, %s",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
9730   }
9731   ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
9732   ierr = (*symbolic)(A,B,fill,C);CHKERRQ(ierr);
9733   ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
9734   PetscFunctionReturn(0);
9735 }
9736 
9737 /*@
9738    MatMatMultNumeric - Performs the numeric matrix-matrix product.
9739    Call this routine after first calling MatMatMultSymbolic().
9740 
9741    Neighbor-wise Collective on Mat
9742 
9743    Input Parameters:
9744 +  A - the left matrix
9745 -  B - the right matrix
9746 
9747    Output Parameters:
9748 .  C - the product matrix, which was created by from MatMatMultSymbolic() or a call to MatMatMult().
9749 
9750    Notes:
9751    C must have been created with MatMatMultSymbolic().
9752 
9753    This routine is currently implemented for
9754     - pairs of AIJ matrices and classes which inherit from AIJ, C will be of type MATAIJ.
9755     - pairs of AIJ (A) and Dense (B) matrix, C will be of type Dense.
9756     - pairs of Dense (A) and AIJ (B) matrix, C will be of type Dense.
9757 
9758    Level: intermediate
9759 
9760 .seealso: MatMatMult(), MatMatMultSymbolic()
9761 @*/
9762 PetscErrorCode MatMatMultNumeric(Mat A,Mat B,Mat C)
9763 {
9764   PetscErrorCode ierr;
9765 
9766   PetscFunctionBegin;
9767   ierr = MatMatMult(A,B,MAT_REUSE_MATRIX,0.0,&C);CHKERRQ(ierr);
9768   PetscFunctionReturn(0);
9769 }
9770 
9771 /*@
9772    MatMatTransposeMult - Performs Matrix-Matrix Multiplication C=A*B^T.
9773 
9774    Neighbor-wise Collective on Mat
9775 
9776    Input Parameters:
9777 +  A - the left matrix
9778 .  B - the right matrix
9779 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9780 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9781 
9782    Output Parameters:
9783 .  C - the product matrix
9784 
9785    Notes:
9786    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9787 
9788    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9789 
9790   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9791    actually needed.
9792 
9793    This routine is currently only implemented for pairs of SeqAIJ matrices and for the SeqDense class.
9794 
9795    Level: intermediate
9796 
9797 .seealso: MatMatTransposeMultSymbolic(), MatMatTransposeMultNumeric(), MatMatMult(), MatTransposeMatMult() MatPtAP()
9798 @*/
9799 PetscErrorCode MatMatTransposeMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9800 {
9801   PetscErrorCode ierr;
9802   PetscErrorCode (*fA)(Mat,Mat,MatReuse,PetscReal,Mat*);
9803   PetscErrorCode (*fB)(Mat,Mat,MatReuse,PetscReal,Mat*);
9804 
9805   PetscFunctionBegin;
9806   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9807   PetscValidType(A,1);
9808   if (scall == MAT_INPLACE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9809   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9810   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9811   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
9812   PetscValidType(B,2);
9813   MatCheckPreallocated(B,2);
9814   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9815   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9816   PetscValidPointer(C,3);
9817   if (B->cmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, AN %D != BN %D",A->cmap->N,B->cmap->N);
9818   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) fill = 2.0;
9819   if (fill < 1.0) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Expected fill=%g must be > 1.0",(double)fill);
9820   MatCheckPreallocated(A,1);
9821 
9822   fA = A->ops->mattransposemult;
9823   if (!fA) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatMatTransposeMult not supported for A of type %s",((PetscObject)A)->type_name);
9824   fB = B->ops->mattransposemult;
9825   if (!fB) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatMatTransposeMult not supported for B of type %s",((PetscObject)B)->type_name);
9826   if (fB!=fA) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"MatMatTransposeMult requires A, %s, to be compatible with B, %s",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
9827 
9828   ierr = PetscLogEventBegin(MAT_MatTransposeMult,A,B,0,0);CHKERRQ(ierr);
9829   if (scall == MAT_INITIAL_MATRIX) {
9830     ierr = PetscLogEventBegin(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr);
9831     ierr = (*A->ops->mattransposemultsymbolic)(A,B,fill,C);CHKERRQ(ierr);
9832     ierr = PetscLogEventEnd(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr);
9833   }
9834   ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
9835   ierr = (*A->ops->mattransposemultnumeric)(A,B,*C);CHKERRQ(ierr);
9836   ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
9837   ierr = PetscLogEventEnd(MAT_MatTransposeMult,A,B,0,0);CHKERRQ(ierr);
9838   PetscFunctionReturn(0);
9839 }
9840 
9841 /*@
9842    MatTransposeMatMult - Performs Matrix-Matrix Multiplication C=A^T*B.
9843 
9844    Neighbor-wise Collective on Mat
9845 
9846    Input Parameters:
9847 +  A - the left matrix
9848 .  B - the right matrix
9849 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9850 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9851 
9852    Output Parameters:
9853 .  C - the product matrix
9854 
9855    Notes:
9856    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9857 
9858    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9859 
9860   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9861    actually needed.
9862 
9863    This routine is currently implemented for pairs of AIJ matrices and pairs of SeqDense matrices and classes
9864    which inherit from SeqAIJ.  C will be of same type as the input matrices.
9865 
9866    Level: intermediate
9867 
9868 .seealso: MatTransposeMatMultSymbolic(), MatTransposeMatMultNumeric(), MatMatMult(), MatMatTransposeMult(), MatPtAP()
9869 @*/
9870 PetscErrorCode MatTransposeMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
9871 {
9872   PetscErrorCode ierr;
9873   PetscErrorCode (*fA)(Mat,Mat,MatReuse,PetscReal,Mat*);
9874   PetscErrorCode (*fB)(Mat,Mat,MatReuse,PetscReal,Mat*);
9875   PetscErrorCode (*transposematmult)(Mat,Mat,MatReuse,PetscReal,Mat*) = NULL;
9876 
9877   PetscFunctionBegin;
9878   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9879   PetscValidType(A,1);
9880   if (scall == MAT_INPLACE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9881   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9882   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9883   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
9884   PetscValidType(B,2);
9885   MatCheckPreallocated(B,2);
9886   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9887   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9888   PetscValidPointer(C,3);
9889   if (B->rmap->N!=A->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->rmap->N);
9890   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) fill = 2.0;
9891   if (fill < 1.0) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Expected fill=%g must be > 1.0",(double)fill);
9892   MatCheckPreallocated(A,1);
9893 
9894   fA = A->ops->transposematmult;
9895   fB = B->ops->transposematmult;
9896   if (fB==fA) {
9897     if (!fA) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatTransposeMatMult not supported for A of type %s",((PetscObject)A)->type_name);
9898     transposematmult = fA;
9899   } else {
9900     /* dispatch based on the type of A and B from their PetscObject's PetscFunctionLists. */
9901     char multname[256];
9902     ierr = PetscStrncpy(multname,"MatTransposeMatMult_",sizeof(multname));CHKERRQ(ierr);
9903     ierr = PetscStrlcat(multname,((PetscObject)A)->type_name,sizeof(multname));CHKERRQ(ierr);
9904     ierr = PetscStrlcat(multname,"_",sizeof(multname));CHKERRQ(ierr);
9905     ierr = PetscStrlcat(multname,((PetscObject)B)->type_name,sizeof(multname));CHKERRQ(ierr);
9906     ierr = PetscStrlcat(multname,"_C",sizeof(multname));CHKERRQ(ierr); /* e.g., multname = "MatMatMult_seqdense_seqaij_C" */
9907     ierr = PetscObjectQueryFunction((PetscObject)B,multname,&transposematmult);CHKERRQ(ierr);
9908     if (!transposematmult) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"MatTransposeMatMult requires A, %s, to be compatible with B, %s",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
9909   }
9910   ierr = PetscLogEventBegin(MAT_TransposeMatMult,A,B,0,0);CHKERRQ(ierr);
9911   ierr = (*transposematmult)(A,B,scall,fill,C);CHKERRQ(ierr);
9912   ierr = PetscLogEventEnd(MAT_TransposeMatMult,A,B,0,0);CHKERRQ(ierr);
9913   PetscFunctionReturn(0);
9914 }
9915 
9916 /*@
9917    MatMatMatMult - Performs Matrix-Matrix-Matrix Multiplication D=A*B*C.
9918 
9919    Neighbor-wise Collective on Mat
9920 
9921    Input Parameters:
9922 +  A - the left matrix
9923 .  B - the middle matrix
9924 .  C - the right matrix
9925 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9926 -  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
9927           if the result is a dense matrix this is irrelevent
9928 
9929    Output Parameters:
9930 .  D - the product matrix
9931 
9932    Notes:
9933    Unless scall is MAT_REUSE_MATRIX D will be created.
9934 
9935    MAT_REUSE_MATRIX can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9936 
9937    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9938    actually needed.
9939 
9940    If you have many matrices with the same non-zero structure to multiply, you
9941    should use MAT_REUSE_MATRIX in all calls but the first or
9942 
9943    Level: intermediate
9944 
9945 .seealso: MatMatMult, MatPtAP()
9946 @*/
9947 PetscErrorCode MatMatMatMult(Mat A,Mat B,Mat C,MatReuse scall,PetscReal fill,Mat *D)
9948 {
9949   PetscErrorCode ierr;
9950   PetscErrorCode (*fA)(Mat,Mat,Mat,MatReuse,PetscReal,Mat*);
9951   PetscErrorCode (*fB)(Mat,Mat,Mat,MatReuse,PetscReal,Mat*);
9952   PetscErrorCode (*fC)(Mat,Mat,Mat,MatReuse,PetscReal,Mat*);
9953   PetscErrorCode (*mult)(Mat,Mat,Mat,MatReuse,PetscReal,Mat*)=NULL;
9954 
9955   PetscFunctionBegin;
9956   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9957   PetscValidType(A,1);
9958   MatCheckPreallocated(A,1);
9959   if (scall == MAT_INPLACE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
9960   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9961   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9962   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
9963   PetscValidType(B,2);
9964   MatCheckPreallocated(B,2);
9965   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9966   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9967   PetscValidHeaderSpecific(C,MAT_CLASSID,3);
9968   PetscValidPointer(C,3);
9969   MatCheckPreallocated(C,3);
9970   if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9971   if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9972   if (B->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N);
9973   if (C->rmap->N!=B->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",C->rmap->N,B->cmap->N);
9974   if (scall == MAT_REUSE_MATRIX) {
9975     PetscValidPointer(*D,6);
9976     PetscValidHeaderSpecific(*D,MAT_CLASSID,6);
9977     ierr = PetscLogEventBegin(MAT_MatMatMult,A,B,0,0);CHKERRQ(ierr);
9978     ierr = (*(*D)->ops->matmatmult)(A,B,C,scall,fill,D);CHKERRQ(ierr);
9979     ierr = PetscLogEventEnd(MAT_MatMatMult,A,B,0,0);CHKERRQ(ierr);
9980     PetscFunctionReturn(0);
9981   }
9982   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) fill = 2.0;
9983   if (fill < 1.0) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Expected fill=%g must be >= 1.0",(double)fill);
9984 
9985   fA = A->ops->matmatmult;
9986   fB = B->ops->matmatmult;
9987   fC = C->ops->matmatmult;
9988   if (fA == fB && fA == fC) {
9989     if (!fA) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatMatMatMult not supported for A of type %s",((PetscObject)A)->type_name);
9990     mult = fA;
9991   } else {
9992     /* dispatch based on the type of A, B and C from their PetscObject's PetscFunctionLists. */
9993     char multname[256];
9994     ierr = PetscStrncpy(multname,"MatMatMatMult_",sizeof(multname));CHKERRQ(ierr);
9995     ierr = PetscStrlcat(multname,((PetscObject)A)->type_name,sizeof(multname));CHKERRQ(ierr);
9996     ierr = PetscStrlcat(multname,"_",sizeof(multname));CHKERRQ(ierr);
9997     ierr = PetscStrlcat(multname,((PetscObject)B)->type_name,sizeof(multname));CHKERRQ(ierr);
9998     ierr = PetscStrlcat(multname,"_",sizeof(multname));CHKERRQ(ierr);
9999     ierr = PetscStrlcat(multname,((PetscObject)C)->type_name,sizeof(multname));CHKERRQ(ierr);
10000     ierr = PetscStrlcat(multname,"_C",sizeof(multname));CHKERRQ(ierr);
10001     ierr = PetscObjectQueryFunction((PetscObject)B,multname,&mult);CHKERRQ(ierr);
10002     if (!mult) SETERRQ3(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"MatMatMatMult requires A, %s, to be compatible with B, %s, C, %s",((PetscObject)A)->type_name,((PetscObject)B)->type_name,((PetscObject)C)->type_name);
10003   }
10004   ierr = PetscLogEventBegin(MAT_MatMatMult,A,B,0,0);CHKERRQ(ierr);
10005   ierr = (*mult)(A,B,C,scall,fill,D);CHKERRQ(ierr);
10006   ierr = PetscLogEventEnd(MAT_MatMatMult,A,B,0,0);CHKERRQ(ierr);
10007   PetscFunctionReturn(0);
10008 }
10009 
10010 /*@
10011    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10012 
10013    Collective on Mat
10014 
10015    Input Parameters:
10016 +  mat - the matrix
10017 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10018 .  subcomm - MPI communicator split from the communicator where mat resides in (or MPI_COMM_NULL if nsubcomm is used)
10019 -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10020 
10021    Output Parameter:
10022 .  matredundant - redundant matrix
10023 
10024    Notes:
10025    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
10026    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10027 
10028    This routine creates the duplicated matrices in subcommunicators; you should NOT create them before
10029    calling it.
10030 
10031    Level: advanced
10032 
10033    Concepts: subcommunicator
10034    Concepts: duplicate matrix
10035 
10036 .seealso: MatDestroy()
10037 @*/
10038 PetscErrorCode MatCreateRedundantMatrix(Mat mat,PetscInt nsubcomm,MPI_Comm subcomm,MatReuse reuse,Mat *matredundant)
10039 {
10040   PetscErrorCode ierr;
10041   MPI_Comm       comm;
10042   PetscMPIInt    size;
10043   PetscInt       mloc_sub,nloc_sub,rstart,rend,M=mat->rmap->N,N=mat->cmap->N,bs=mat->rmap->bs;
10044   Mat_Redundant  *redund=NULL;
10045   PetscSubcomm   psubcomm=NULL;
10046   MPI_Comm       subcomm_in=subcomm;
10047   Mat            *matseq;
10048   IS             isrow,iscol;
10049   PetscBool      newsubcomm=PETSC_FALSE;
10050 
10051   PetscFunctionBegin;
10052   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10053   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10054     PetscValidPointer(*matredundant,5);
10055     PetscValidHeaderSpecific(*matredundant,MAT_CLASSID,5);
10056   }
10057 
10058   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
10059   if (size == 1 || nsubcomm == 1) {
10060     if (reuse == MAT_INITIAL_MATRIX) {
10061       ierr = MatDuplicate(mat,MAT_COPY_VALUES,matredundant);CHKERRQ(ierr);
10062     } else {
10063       if (*matredundant == mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10064       ierr = MatCopy(mat,*matredundant,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
10065     }
10066     PetscFunctionReturn(0);
10067   }
10068 
10069   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10070   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10071   MatCheckPreallocated(mat,1);
10072 
10073   ierr = PetscLogEventBegin(MAT_RedundantMat,mat,0,0,0);CHKERRQ(ierr);
10074   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10075     /* create psubcomm, then get subcomm */
10076     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
10077     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
10078     if (nsubcomm < 1 || nsubcomm > size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"nsubcomm must between 1 and %D",size);
10079 
10080     ierr = PetscSubcommCreate(comm,&psubcomm);CHKERRQ(ierr);
10081     ierr = PetscSubcommSetNumber(psubcomm,nsubcomm);CHKERRQ(ierr);
10082     ierr = PetscSubcommSetType(psubcomm,PETSC_SUBCOMM_CONTIGUOUS);CHKERRQ(ierr);
10083     ierr = PetscSubcommSetFromOptions(psubcomm);CHKERRQ(ierr);
10084     ierr = PetscCommDuplicate(PetscSubcommChild(psubcomm),&subcomm,NULL);CHKERRQ(ierr);
10085     newsubcomm = PETSC_TRUE;
10086     ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
10087   }
10088 
10089   /* get isrow, iscol and a local sequential matrix matseq[0] */
10090   if (reuse == MAT_INITIAL_MATRIX) {
10091     mloc_sub = PETSC_DECIDE;
10092     nloc_sub = PETSC_DECIDE;
10093     if (bs < 1) {
10094       ierr = PetscSplitOwnership(subcomm,&mloc_sub,&M);CHKERRQ(ierr);
10095       ierr = PetscSplitOwnership(subcomm,&nloc_sub,&N);CHKERRQ(ierr);
10096     } else {
10097       ierr = PetscSplitOwnershipBlock(subcomm,bs,&mloc_sub,&M);CHKERRQ(ierr);
10098       ierr = PetscSplitOwnershipBlock(subcomm,bs,&nloc_sub,&N);CHKERRQ(ierr);
10099     }
10100     ierr = MPI_Scan(&mloc_sub,&rend,1,MPIU_INT,MPI_SUM,subcomm);CHKERRQ(ierr);
10101     rstart = rend - mloc_sub;
10102     ierr = ISCreateStride(PETSC_COMM_SELF,mloc_sub,rstart,1,&isrow);CHKERRQ(ierr);
10103     ierr = ISCreateStride(PETSC_COMM_SELF,N,0,1,&iscol);CHKERRQ(ierr);
10104   } else { /* reuse == MAT_REUSE_MATRIX */
10105     if (*matredundant == mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10106     /* retrieve subcomm */
10107     ierr = PetscObjectGetComm((PetscObject)(*matredundant),&subcomm);CHKERRQ(ierr);
10108     redund = (*matredundant)->redundant;
10109     isrow  = redund->isrow;
10110     iscol  = redund->iscol;
10111     matseq = redund->matseq;
10112   }
10113   ierr = MatCreateSubMatrices(mat,1,&isrow,&iscol,reuse,&matseq);CHKERRQ(ierr);
10114 
10115   /* get matredundant over subcomm */
10116   if (reuse == MAT_INITIAL_MATRIX) {
10117     ierr = MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],nloc_sub,reuse,matredundant);CHKERRQ(ierr);
10118 
10119     /* create a supporting struct and attach it to C for reuse */
10120     ierr = PetscNewLog(*matredundant,&redund);CHKERRQ(ierr);
10121     (*matredundant)->redundant = redund;
10122     redund->isrow              = isrow;
10123     redund->iscol              = iscol;
10124     redund->matseq             = matseq;
10125     if (newsubcomm) {
10126       redund->subcomm          = subcomm;
10127     } else {
10128       redund->subcomm          = MPI_COMM_NULL;
10129     }
10130   } else {
10131     ierr = MatCreateMPIMatConcatenateSeqMat(subcomm,matseq[0],PETSC_DECIDE,reuse,matredundant);CHKERRQ(ierr);
10132   }
10133   ierr = PetscLogEventEnd(MAT_RedundantMat,mat,0,0,0);CHKERRQ(ierr);
10134   PetscFunctionReturn(0);
10135 }
10136 
10137 /*@C
10138    MatGetMultiProcBlock - Create multiple [bjacobi] 'parallel submatrices' from
10139    a given 'mat' object. Each submatrix can span multiple procs.
10140 
10141    Collective on Mat
10142 
10143    Input Parameters:
10144 +  mat - the matrix
10145 .  subcomm - the subcommunicator obtained by com_split(comm)
10146 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10147 
10148    Output Parameter:
10149 .  subMat - 'parallel submatrices each spans a given subcomm
10150 
10151   Notes:
10152   The submatrix partition across processors is dictated by 'subComm' a
10153   communicator obtained by com_split(comm). The comm_split
10154   is not restriced to be grouped with consecutive original ranks.
10155 
10156   Due the comm_split() usage, the parallel layout of the submatrices
10157   map directly to the layout of the original matrix [wrt the local
10158   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10159   into the 'DiagonalMat' of the subMat, hence it is used directly from
10160   the subMat. However the offDiagMat looses some columns - and this is
10161   reconstructed with MatSetValues()
10162 
10163   Level: advanced
10164 
10165   Concepts: subcommunicator
10166   Concepts: submatrices
10167 
10168 .seealso: MatCreateSubMatrices()
10169 @*/
10170 PetscErrorCode   MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall,Mat *subMat)
10171 {
10172   PetscErrorCode ierr;
10173   PetscMPIInt    commsize,subCommSize;
10174 
10175   PetscFunctionBegin;
10176   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&commsize);CHKERRQ(ierr);
10177   ierr = MPI_Comm_size(subComm,&subCommSize);CHKERRQ(ierr);
10178   if (subCommSize > commsize) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"CommSize %D < SubCommZize %D",commsize,subCommSize);
10179 
10180   if (scall == MAT_REUSE_MATRIX && *subMat == mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10181   ierr = PetscLogEventBegin(MAT_GetMultiProcBlock,mat,0,0,0);CHKERRQ(ierr);
10182   ierr = (*mat->ops->getmultiprocblock)(mat,subComm,scall,subMat);CHKERRQ(ierr);
10183   ierr = PetscLogEventEnd(MAT_GetMultiProcBlock,mat,0,0,0);CHKERRQ(ierr);
10184   PetscFunctionReturn(0);
10185 }
10186 
10187 /*@
10188    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10189 
10190    Not Collective
10191 
10192    Input Arguments:
10193    mat - matrix to extract local submatrix from
10194    isrow - local row indices for submatrix
10195    iscol - local column indices for submatrix
10196 
10197    Output Arguments:
10198    submat - the submatrix
10199 
10200    Level: intermediate
10201 
10202    Notes:
10203    The submat should be returned with MatRestoreLocalSubMatrix().
10204 
10205    Depending on the format of mat, the returned submat may not implement MatMult().  Its communicator may be
10206    the same as mat, it may be PETSC_COMM_SELF, or some other subcomm of mat's.
10207 
10208    The submat always implements MatSetValuesLocal().  If isrow and iscol have the same block size, then
10209    MatSetValuesBlockedLocal() will also be implemented.
10210 
10211    The mat must have had a ISLocalToGlobalMapping provided to it with MatSetLocalToGlobalMapping(). Note that
10212    matrices obtained with DMCreateMat() generally already have the local to global mapping provided.
10213 
10214 .seealso: MatRestoreLocalSubMatrix(), MatCreateLocalRef(), MatSetLocalToGlobalMapping()
10215 @*/
10216 PetscErrorCode MatGetLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10217 {
10218   PetscErrorCode ierr;
10219 
10220   PetscFunctionBegin;
10221   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10222   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10223   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10224   PetscCheckSameComm(isrow,2,iscol,3);
10225   PetscValidPointer(submat,4);
10226   if (!mat->rmap->mapping) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must have local to global mapping provided before this call");
10227 
10228   if (mat->ops->getlocalsubmatrix) {
10229     ierr = (*mat->ops->getlocalsubmatrix)(mat,isrow,iscol,submat);CHKERRQ(ierr);
10230   } else {
10231     ierr = MatCreateLocalRef(mat,isrow,iscol,submat);CHKERRQ(ierr);
10232   }
10233   PetscFunctionReturn(0);
10234 }
10235 
10236 /*@
10237    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering
10238 
10239    Not Collective
10240 
10241    Input Arguments:
10242    mat - matrix to extract local submatrix from
10243    isrow - local row indices for submatrix
10244    iscol - local column indices for submatrix
10245    submat - the submatrix
10246 
10247    Level: intermediate
10248 
10249 .seealso: MatGetLocalSubMatrix()
10250 @*/
10251 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat *submat)
10252 {
10253   PetscErrorCode ierr;
10254 
10255   PetscFunctionBegin;
10256   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10257   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
10258   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
10259   PetscCheckSameComm(isrow,2,iscol,3);
10260   PetscValidPointer(submat,4);
10261   if (*submat) {
10262     PetscValidHeaderSpecific(*submat,MAT_CLASSID,4);
10263   }
10264 
10265   if (mat->ops->restorelocalsubmatrix) {
10266     ierr = (*mat->ops->restorelocalsubmatrix)(mat,isrow,iscol,submat);CHKERRQ(ierr);
10267   } else {
10268     ierr = MatDestroy(submat);CHKERRQ(ierr);
10269   }
10270   *submat = NULL;
10271   PetscFunctionReturn(0);
10272 }
10273 
10274 /* --------------------------------------------------------*/
10275 /*@
10276    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10277 
10278    Collective on Mat
10279 
10280    Input Parameter:
10281 .  mat - the matrix
10282 
10283    Output Parameter:
10284 .  is - if any rows have zero diagonals this contains the list of them
10285 
10286    Level: developer
10287 
10288    Concepts: matrix-vector product
10289 
10290 .seealso: MatMultTranspose(), MatMultAdd(), MatMultTransposeAdd()
10291 @*/
10292 PetscErrorCode MatFindZeroDiagonals(Mat mat,IS *is)
10293 {
10294   PetscErrorCode ierr;
10295 
10296   PetscFunctionBegin;
10297   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10298   PetscValidType(mat,1);
10299   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10300   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10301 
10302   if (!mat->ops->findzerodiagonals) {
10303     Vec                diag;
10304     const PetscScalar *a;
10305     PetscInt          *rows;
10306     PetscInt           rStart, rEnd, r, nrow = 0;
10307 
10308     ierr = MatCreateVecs(mat, &diag, NULL);CHKERRQ(ierr);
10309     ierr = MatGetDiagonal(mat, diag);CHKERRQ(ierr);
10310     ierr = MatGetOwnershipRange(mat, &rStart, &rEnd);CHKERRQ(ierr);
10311     ierr = VecGetArrayRead(diag, &a);CHKERRQ(ierr);
10312     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) ++nrow;
10313     ierr = PetscMalloc1(nrow, &rows);CHKERRQ(ierr);
10314     nrow = 0;
10315     for (r = 0; r < rEnd-rStart; ++r) if (a[r] == 0.0) rows[nrow++] = r+rStart;
10316     ierr = VecRestoreArrayRead(diag, &a);CHKERRQ(ierr);
10317     ierr = VecDestroy(&diag);CHKERRQ(ierr);
10318     ierr = ISCreateGeneral(PetscObjectComm((PetscObject) mat), nrow, rows, PETSC_OWN_POINTER, is);CHKERRQ(ierr);
10319   } else {
10320     ierr = (*mat->ops->findzerodiagonals)(mat, is);CHKERRQ(ierr);
10321   }
10322   PetscFunctionReturn(0);
10323 }
10324 
10325 /*@
10326    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10327 
10328    Collective on Mat
10329 
10330    Input Parameter:
10331 .  mat - the matrix
10332 
10333    Output Parameter:
10334 .  is - contains the list of rows with off block diagonal entries
10335 
10336    Level: developer
10337 
10338    Concepts: matrix-vector product
10339 
10340 .seealso: MatMultTranspose(), MatMultAdd(), MatMultTransposeAdd()
10341 @*/
10342 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat,IS *is)
10343 {
10344   PetscErrorCode ierr;
10345 
10346   PetscFunctionBegin;
10347   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10348   PetscValidType(mat,1);
10349   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10350   if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10351 
10352   if (!mat->ops->findoffblockdiagonalentries) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"This matrix type does not have a find off block diagonal entries defined");
10353   ierr = (*mat->ops->findoffblockdiagonalentries)(mat,is);CHKERRQ(ierr);
10354   PetscFunctionReturn(0);
10355 }
10356 
10357 /*@C
10358   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10359 
10360   Collective on Mat
10361 
10362   Input Parameters:
10363 . mat - the matrix
10364 
10365   Output Parameters:
10366 . values - the block inverses in column major order (FORTRAN-like)
10367 
10368    Note:
10369    This routine is not available from Fortran.
10370 
10371   Level: advanced
10372 
10373 .seealso: MatInvertBockDiagonalMat
10374 @*/
10375 PetscErrorCode MatInvertBlockDiagonal(Mat mat,const PetscScalar **values)
10376 {
10377   PetscErrorCode ierr;
10378 
10379   PetscFunctionBegin;
10380   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10381   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10382   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10383   if (!mat->ops->invertblockdiagonal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported");
10384   ierr = (*mat->ops->invertblockdiagonal)(mat,values);CHKERRQ(ierr);
10385   PetscFunctionReturn(0);
10386 }
10387 
10388 /*@
10389   MatInvertBlockDiagonalMat - set matrix C to be the inverted block diagonal of matrix A
10390 
10391   Collective on Mat
10392 
10393   Input Parameters:
10394 . A - the matrix
10395 
10396   Output Parameters:
10397 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10398 
10399   Level: advanced
10400 
10401 .seealso: MatInvertBockDiagonal()
10402 @*/
10403 PetscErrorCode MatInvertBlockDiagonalMat(Mat A,Mat C)
10404 {
10405   PetscErrorCode     ierr;
10406   const PetscScalar *vals;
10407   PetscInt          *dnnz;
10408   PetscInt           M,N,m,n,rstart,rend,bs,i,j;
10409 
10410   PetscFunctionBegin;
10411   ierr = MatInvertBlockDiagonal(A,&vals);CHKERRQ(ierr);
10412   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
10413   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
10414   ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr);
10415   ierr = MatSetSizes(C,m,n,M,N);CHKERRQ(ierr);
10416   ierr = MatSetBlockSize(C,bs);CHKERRQ(ierr);
10417   ierr = PetscMalloc1(m/bs,&dnnz);CHKERRQ(ierr);
10418   for(j = 0; j < m/bs; j++) {
10419     dnnz[j] = 1;
10420   }
10421   ierr = MatXAIJSetPreallocation(C,bs,dnnz,NULL,NULL,NULL);CHKERRQ(ierr);
10422   ierr = PetscFree(dnnz);CHKERRQ(ierr);
10423   ierr = MatGetOwnershipRange(C,&rstart,&rend);CHKERRQ(ierr);
10424   ierr = MatSetOption(C,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
10425   for (i = rstart/bs; i < rend/bs; i++) {
10426     ierr = MatSetValuesBlocked(C,1,&i,1,&i,&vals[(i-rstart/bs)*bs*bs],INSERT_VALUES);CHKERRQ(ierr);
10427   }
10428   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10429   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10430   ierr = MatSetOption(C,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
10431   PetscFunctionReturn(0);
10432 }
10433 
10434 /*@C
10435     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10436     via MatTransposeColoringCreate().
10437 
10438     Collective on MatTransposeColoring
10439 
10440     Input Parameter:
10441 .   c - coloring context
10442 
10443     Level: intermediate
10444 
10445 .seealso: MatTransposeColoringCreate()
10446 @*/
10447 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10448 {
10449   PetscErrorCode       ierr;
10450   MatTransposeColoring matcolor=*c;
10451 
10452   PetscFunctionBegin;
10453   if (!matcolor) PetscFunctionReturn(0);
10454   if (--((PetscObject)matcolor)->refct > 0) {matcolor = 0; PetscFunctionReturn(0);}
10455 
10456   ierr = PetscFree3(matcolor->ncolumns,matcolor->nrows,matcolor->colorforrow);CHKERRQ(ierr);
10457   ierr = PetscFree(matcolor->rows);CHKERRQ(ierr);
10458   ierr = PetscFree(matcolor->den2sp);CHKERRQ(ierr);
10459   ierr = PetscFree(matcolor->colorforcol);CHKERRQ(ierr);
10460   ierr = PetscFree(matcolor->columns);CHKERRQ(ierr);
10461   if (matcolor->brows>0) {
10462     ierr = PetscFree(matcolor->lstart);CHKERRQ(ierr);
10463   }
10464   ierr = PetscHeaderDestroy(c);CHKERRQ(ierr);
10465   PetscFunctionReturn(0);
10466 }
10467 
10468 /*@C
10469     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10470     a MatTransposeColoring context has been created, computes a dense B^T by Apply
10471     MatTransposeColoring to sparse B.
10472 
10473     Collective on MatTransposeColoring
10474 
10475     Input Parameters:
10476 +   B - sparse matrix B
10477 .   Btdense - symbolic dense matrix B^T
10478 -   coloring - coloring context created with MatTransposeColoringCreate()
10479 
10480     Output Parameter:
10481 .   Btdense - dense matrix B^T
10482 
10483     Level: advanced
10484 
10485      Notes:
10486     These are used internally for some implementations of MatRARt()
10487 
10488 .seealso: MatTransposeColoringCreate(), MatTransposeColoringDestroy(), MatTransColoringApplyDenToSp()
10489 
10490 .keywords: coloring
10491 @*/
10492 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring,Mat B,Mat Btdense)
10493 {
10494   PetscErrorCode ierr;
10495 
10496   PetscFunctionBegin;
10497   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
10498   PetscValidHeaderSpecific(Btdense,MAT_CLASSID,2);
10499   PetscValidHeaderSpecific(coloring,MAT_TRANSPOSECOLORING_CLASSID,3);
10500 
10501   if (!B->ops->transcoloringapplysptoden) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)B)->type_name);
10502   ierr = (B->ops->transcoloringapplysptoden)(coloring,B,Btdense);CHKERRQ(ierr);
10503   PetscFunctionReturn(0);
10504 }
10505 
10506 /*@C
10507     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10508     a MatTransposeColoring context has been created and a dense matrix Cden=A*Btdense
10509     in which Btdens is obtained from MatTransColoringApplySpToDen(), recover sparse matrix
10510     Csp from Cden.
10511 
10512     Collective on MatTransposeColoring
10513 
10514     Input Parameters:
10515 +   coloring - coloring context created with MatTransposeColoringCreate()
10516 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10517 
10518     Output Parameter:
10519 .   Csp - sparse matrix
10520 
10521     Level: advanced
10522 
10523      Notes:
10524     These are used internally for some implementations of MatRARt()
10525 
10526 .seealso: MatTransposeColoringCreate(), MatTransposeColoringDestroy(), MatTransColoringApplySpToDen()
10527 
10528 .keywords: coloring
10529 @*/
10530 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring,Mat Cden,Mat Csp)
10531 {
10532   PetscErrorCode ierr;
10533 
10534   PetscFunctionBegin;
10535   PetscValidHeaderSpecific(matcoloring,MAT_TRANSPOSECOLORING_CLASSID,1);
10536   PetscValidHeaderSpecific(Cden,MAT_CLASSID,2);
10537   PetscValidHeaderSpecific(Csp,MAT_CLASSID,3);
10538 
10539   if (!Csp->ops->transcoloringapplydentosp) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)Csp)->type_name);
10540   ierr = (Csp->ops->transcoloringapplydentosp)(matcoloring,Cden,Csp);CHKERRQ(ierr);
10541   PetscFunctionReturn(0);
10542 }
10543 
10544 /*@C
10545    MatTransposeColoringCreate - Creates a matrix coloring context for matrix product C=A*B^T.
10546 
10547    Collective on Mat
10548 
10549    Input Parameters:
10550 +  mat - the matrix product C
10551 -  iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring()
10552 
10553     Output Parameter:
10554 .   color - the new coloring context
10555 
10556     Level: intermediate
10557 
10558 .seealso: MatTransposeColoringDestroy(),  MatTransColoringApplySpToDen(),
10559            MatTransColoringApplyDenToSp()
10560 @*/
10561 PetscErrorCode MatTransposeColoringCreate(Mat mat,ISColoring iscoloring,MatTransposeColoring *color)
10562 {
10563   MatTransposeColoring c;
10564   MPI_Comm             comm;
10565   PetscErrorCode       ierr;
10566 
10567   PetscFunctionBegin;
10568   ierr = PetscLogEventBegin(MAT_TransposeColoringCreate,mat,0,0,0);CHKERRQ(ierr);
10569   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
10570   ierr = PetscHeaderCreate(c,MAT_TRANSPOSECOLORING_CLASSID,"MatTransposeColoring","Matrix product C=A*B^T via coloring","Mat",comm,MatTransposeColoringDestroy,NULL);CHKERRQ(ierr);
10571 
10572   c->ctype = iscoloring->ctype;
10573   if (mat->ops->transposecoloringcreate) {
10574     ierr = (*mat->ops->transposecoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr);
10575   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for this matrix type");
10576 
10577   *color = c;
10578   ierr   = PetscLogEventEnd(MAT_TransposeColoringCreate,mat,0,0,0);CHKERRQ(ierr);
10579   PetscFunctionReturn(0);
10580 }
10581 
10582 /*@
10583       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10584         matrix has had no new nonzero locations added to the matrix since the previous call then the value will be the
10585         same, otherwise it will be larger
10586 
10587      Not Collective
10588 
10589   Input Parameter:
10590 .    A  - the matrix
10591 
10592   Output Parameter:
10593 .    state - the current state
10594 
10595   Notes:
10596     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10597          different matrices
10598 
10599   Level: intermediate
10600 
10601 @*/
10602 PetscErrorCode MatGetNonzeroState(Mat mat,PetscObjectState *state)
10603 {
10604   PetscFunctionBegin;
10605   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10606   *state = mat->nonzerostate;
10607   PetscFunctionReturn(0);
10608 }
10609 
10610 /*@
10611       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10612                  matrices from each processor
10613 
10614     Collective on MPI_Comm
10615 
10616    Input Parameters:
10617 +    comm - the communicators the parallel matrix will live on
10618 .    seqmat - the input sequential matrices
10619 .    n - number of local columns (or PETSC_DECIDE)
10620 -    reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10621 
10622    Output Parameter:
10623 .    mpimat - the parallel matrix generated
10624 
10625     Level: advanced
10626 
10627    Notes:
10628     The number of columns of the matrix in EACH processor MUST be the same.
10629 
10630 @*/
10631 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm,Mat seqmat,PetscInt n,MatReuse reuse,Mat *mpimat)
10632 {
10633   PetscErrorCode ierr;
10634 
10635   PetscFunctionBegin;
10636   if (!seqmat->ops->creatempimatconcatenateseqmat) SETERRQ1(PetscObjectComm((PetscObject)seqmat),PETSC_ERR_SUP,"Mat type %s",((PetscObject)seqmat)->type_name);
10637   if (reuse == MAT_REUSE_MATRIX && seqmat == *mpimat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10638 
10639   ierr = PetscLogEventBegin(MAT_Merge,seqmat,0,0,0);CHKERRQ(ierr);
10640   ierr = (*seqmat->ops->creatempimatconcatenateseqmat)(comm,seqmat,n,reuse,mpimat);CHKERRQ(ierr);
10641   ierr = PetscLogEventEnd(MAT_Merge,seqmat,0,0,0);CHKERRQ(ierr);
10642   PetscFunctionReturn(0);
10643 }
10644 
10645 /*@
10646      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent
10647                  ranks' ownership ranges.
10648 
10649     Collective on A
10650 
10651    Input Parameters:
10652 +    A   - the matrix to create subdomains from
10653 -    N   - requested number of subdomains
10654 
10655 
10656    Output Parameters:
10657 +    n   - number of subdomains resulting on this rank
10658 -    iss - IS list with indices of subdomains on this rank
10659 
10660     Level: advanced
10661 
10662     Notes:
10663     number of subdomains must be smaller than the communicator size
10664 @*/
10665 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A,PetscInt N,PetscInt *n,IS *iss[])
10666 {
10667   MPI_Comm        comm,subcomm;
10668   PetscMPIInt     size,rank,color;
10669   PetscInt        rstart,rend,k;
10670   PetscErrorCode  ierr;
10671 
10672   PetscFunctionBegin;
10673   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
10674   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
10675   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
10676   if (N < 1 || N >= (PetscInt)size) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of subdomains must be > 0 and < %D, got N = %D",size,N);
10677   *n = 1;
10678   k = ((PetscInt)size)/N + ((PetscInt)size%N>0); /* There are up to k ranks to a color */
10679   color = rank/k;
10680   ierr = MPI_Comm_split(comm,color,rank,&subcomm);CHKERRQ(ierr);
10681   ierr = PetscMalloc1(1,iss);CHKERRQ(ierr);
10682   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
10683   ierr = ISCreateStride(subcomm,rend-rstart,rstart,1,iss[0]);CHKERRQ(ierr);
10684   ierr = MPI_Comm_free(&subcomm);CHKERRQ(ierr);
10685   PetscFunctionReturn(0);
10686 }
10687 
10688 /*@
10689    MatGalerkin - Constructs the coarse grid problem via Galerkin projection.
10690 
10691    If the interpolation and restriction operators are the same, uses MatPtAP.
10692    If they are not the same, use MatMatMatMult.
10693 
10694    Once the coarse grid problem is constructed, correct for interpolation operators
10695    that are not of full rank, which can legitimately happen in the case of non-nested
10696    geometric multigrid.
10697 
10698    Input Parameters:
10699 +  restrct - restriction operator
10700 .  dA - fine grid matrix
10701 .  interpolate - interpolation operator
10702 .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10703 -  fill - expected fill, use PETSC_DEFAULT if you do not have a good estimate
10704 
10705    Output Parameters:
10706 .  A - the Galerkin coarse matrix
10707 
10708    Options Database Key:
10709 .  -pc_mg_galerkin <both,pmat,mat,none>
10710 
10711    Level: developer
10712 
10713 .keywords: MG, multigrid, Galerkin
10714 
10715 .seealso: MatPtAP(), MatMatMatMult()
10716 @*/
10717 PetscErrorCode  MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10718 {
10719   PetscErrorCode ierr;
10720   IS             zerorows;
10721   Vec            diag;
10722 
10723   PetscFunctionBegin;
10724   if (reuse == MAT_INPLACE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Inplace product not supported");
10725   /* Construct the coarse grid matrix */
10726   if (interpolate == restrct) {
10727     ierr = MatPtAP(dA,interpolate,reuse,fill,A);CHKERRQ(ierr);
10728   } else {
10729     ierr = MatMatMatMult(restrct,dA,interpolate,reuse,fill,A);CHKERRQ(ierr);
10730   }
10731 
10732   /* If the interpolation matrix is not of full rank, A will have zero rows.
10733      This can legitimately happen in the case of non-nested geometric multigrid.
10734      In that event, we set the rows of the matrix to the rows of the identity,
10735      ignoring the equations (as the RHS will also be zero). */
10736 
10737   ierr = MatFindZeroRows(*A, &zerorows);CHKERRQ(ierr);
10738 
10739   if (zerorows != NULL) { /* if there are any zero rows */
10740     ierr = MatCreateVecs(*A, &diag, NULL);CHKERRQ(ierr);
10741     ierr = MatGetDiagonal(*A, diag);CHKERRQ(ierr);
10742     ierr = VecISSet(diag, zerorows, 1.0);CHKERRQ(ierr);
10743     ierr = MatDiagonalSet(*A, diag, INSERT_VALUES);CHKERRQ(ierr);
10744     ierr = VecDestroy(&diag);CHKERRQ(ierr);
10745     ierr = ISDestroy(&zerorows);CHKERRQ(ierr);
10746   }
10747   PetscFunctionReturn(0);
10748 }
10749 
10750 /*@C
10751     MatSetOperation - Allows user to set a matrix operation for any matrix type
10752 
10753    Logically Collective on Mat
10754 
10755     Input Parameters:
10756 +   mat - the matrix
10757 .   op - the name of the operation
10758 -   f - the function that provides the operation
10759 
10760    Level: developer
10761 
10762     Usage:
10763 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10764 $      ierr = MatCreateXXX(comm,...&A);
10765 $      ierr = MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10766 
10767     Notes:
10768     See the file include/petscmat.h for a complete list of matrix
10769     operations, which all have the form MATOP_<OPERATION>, where
10770     <OPERATION> is the name (in all capital letters) of the
10771     user interface routine (e.g., MatMult() -> MATOP_MULT).
10772 
10773     All user-provided functions (except for MATOP_DESTROY) should have the same calling
10774     sequence as the usual matrix interface routines, since they
10775     are intended to be accessed via the usual matrix interface
10776     routines, e.g.,
10777 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10778 
10779     In particular each function MUST return an error code of 0 on success and
10780     nonzero on failure.
10781 
10782     This routine is distinct from MatShellSetOperation() in that it can be called on any matrix type.
10783 
10784 .keywords: matrix, set, operation
10785 
10786 .seealso: MatGetOperation(), MatCreateShell(), MatShellSetContext(), MatShellSetOperation()
10787 @*/
10788 PetscErrorCode MatSetOperation(Mat mat,MatOperation op,void (*f)(void))
10789 {
10790   PetscFunctionBegin;
10791   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10792   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) {
10793     mat->ops->viewnative = mat->ops->view;
10794   }
10795   (((void(**)(void))mat->ops)[op]) = f;
10796   PetscFunctionReturn(0);
10797 }
10798 
10799 /*@C
10800     MatGetOperation - Gets a matrix operation for any matrix type.
10801 
10802     Not Collective
10803 
10804     Input Parameters:
10805 +   mat - the matrix
10806 -   op - the name of the operation
10807 
10808     Output Parameter:
10809 .   f - the function that provides the operation
10810 
10811     Level: developer
10812 
10813     Usage:
10814 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10815 $      ierr = MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10816 
10817     Notes:
10818     See the file include/petscmat.h for a complete list of matrix
10819     operations, which all have the form MATOP_<OPERATION>, where
10820     <OPERATION> is the name (in all capital letters) of the
10821     user interface routine (e.g., MatMult() -> MATOP_MULT).
10822 
10823     This routine is distinct from MatShellGetOperation() in that it can be called on any matrix type.
10824 
10825 .keywords: matrix, get, operation
10826 
10827 .seealso: MatSetOperation(), MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
10828 @*/
10829 PetscErrorCode MatGetOperation(Mat mat,MatOperation op,void(**f)(void))
10830 {
10831   PetscFunctionBegin;
10832   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10833   *f = (((void (**)(void))mat->ops)[op]);
10834   PetscFunctionReturn(0);
10835 }
10836 
10837 /*@
10838     MatHasOperation - Determines whether the given matrix supports the particular
10839     operation.
10840 
10841    Not Collective
10842 
10843    Input Parameters:
10844 +  mat - the matrix
10845 -  op - the operation, for example, MATOP_GET_DIAGONAL
10846 
10847    Output Parameter:
10848 .  has - either PETSC_TRUE or PETSC_FALSE
10849 
10850    Level: advanced
10851 
10852    Notes:
10853    See the file include/petscmat.h for a complete list of matrix
10854    operations, which all have the form MATOP_<OPERATION>, where
10855    <OPERATION> is the name (in all capital letters) of the
10856    user-level routine.  E.g., MatNorm() -> MATOP_NORM.
10857 
10858 .keywords: matrix, has, operation
10859 
10860 .seealso: MatCreateShell()
10861 @*/
10862 PetscErrorCode MatHasOperation(Mat mat,MatOperation op,PetscBool *has)
10863 {
10864   PetscErrorCode ierr;
10865 
10866   PetscFunctionBegin;
10867   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10868   PetscValidType(mat,1);
10869   PetscValidPointer(has,3);
10870   if (mat->ops->hasoperation) {
10871     ierr = (*mat->ops->hasoperation)(mat,op,has);CHKERRQ(ierr);
10872   } else {
10873     if (((void**)mat->ops)[op]) *has =  PETSC_TRUE;
10874     else {
10875       *has = PETSC_FALSE;
10876       if (op == MATOP_CREATE_SUBMATRIX) {
10877         PetscMPIInt size;
10878 
10879         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
10880         if (size == 1) {
10881           ierr = MatHasOperation(mat,MATOP_CREATE_SUBMATRICES,has);CHKERRQ(ierr);
10882         }
10883       }
10884     }
10885   }
10886   PetscFunctionReturn(0);
10887 }
10888 
10889 /*@
10890     MatHasCongruentLayouts - Determines whether the rows and columns layouts
10891     of the matrix are congruent
10892 
10893    Collective on mat
10894 
10895    Input Parameters:
10896 .  mat - the matrix
10897 
10898    Output Parameter:
10899 .  cong - either PETSC_TRUE or PETSC_FALSE
10900 
10901    Level: beginner
10902 
10903    Notes:
10904 
10905 .keywords: matrix, has
10906 
10907 .seealso: MatCreate(), MatSetSizes()
10908 @*/
10909 PetscErrorCode MatHasCongruentLayouts(Mat mat,PetscBool *cong)
10910 {
10911   PetscErrorCode ierr;
10912 
10913   PetscFunctionBegin;
10914   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10915   PetscValidType(mat,1);
10916   PetscValidPointer(cong,2);
10917   if (!mat->rmap || !mat->cmap) {
10918     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10919     PetscFunctionReturn(0);
10920   }
10921   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10922     ierr = PetscLayoutCompare(mat->rmap,mat->cmap,cong);CHKERRQ(ierr);
10923     if (*cong) mat->congruentlayouts = 1;
10924     else       mat->congruentlayouts = 0;
10925   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10926   PetscFunctionReturn(0);
10927 }
10928