xref: /petsc/src/ksp/pc/interface/precon.c (revision e6e75211d226c622f451867f53ce5d558649ff4f)
1 
2 /*
3     The PC (preconditioner) interface routines, callable by users.
4 */
5 #include <petsc/private/pcimpl.h>            /*I "petscksp.h" I*/
6 #include <petscdm.h>
7 
8 /* Logging support */
9 PetscClassId  PC_CLASSID;
10 PetscLogEvent PC_SetUp, PC_SetUpOnBlocks, PC_Apply, PC_ApplyCoarse, PC_ApplyMultiple, PC_ApplySymmetricLeft;
11 PetscLogEvent PC_ApplySymmetricRight, PC_ModifySubMatrices, PC_ApplyOnBlocks, PC_ApplyTransposeOnBlocks, PC_ApplyOnMproc;
12 
13 #undef __FUNCT__
14 #define __FUNCT__ "PCGetDefaultType_Private"
15 PetscErrorCode PCGetDefaultType_Private(PC pc,const char *type[])
16 {
17   PetscErrorCode ierr;
18   PetscMPIInt    size;
19   PetscBool      flg1,flg2,set,flg3;
20 
21   PetscFunctionBegin;
22   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
23   if (pc->pmat) {
24     PetscErrorCode (*f)(Mat,MatReuse,Mat*);
25     ierr = PetscObjectQueryFunction((PetscObject)pc->pmat,"MatGetDiagonalBlock_C",&f);CHKERRQ(ierr);
26     if (size == 1) {
27       ierr = MatGetFactorAvailable(pc->pmat,"petsc",MAT_FACTOR_ICC,&flg1);CHKERRQ(ierr);
28       ierr = MatGetFactorAvailable(pc->pmat,"petsc",MAT_FACTOR_ILU,&flg2);CHKERRQ(ierr);
29       ierr = MatIsSymmetricKnown(pc->pmat,&set,&flg3);CHKERRQ(ierr);
30       if (flg1 && (!flg2 || (set && flg3))) {
31         *type = PCICC;
32       } else if (flg2) {
33         *type = PCILU;
34       } else if (f) { /* likely is a parallel matrix run on one processor */
35         *type = PCBJACOBI;
36       } else {
37         *type = PCNONE;
38       }
39     } else {
40        if (f) {
41         *type = PCBJACOBI;
42       } else {
43         *type = PCNONE;
44       }
45     }
46   } else {
47     if (size == 1) {
48       *type = PCILU;
49     } else {
50       *type = PCBJACOBI;
51     }
52   }
53   PetscFunctionReturn(0);
54 }
55 
56 #undef __FUNCT__
57 #define __FUNCT__ "PCReset"
58 /*@
59    PCReset - Resets a PC context to the pcsetupcalled = 0 state and removes any allocated Vecs and Mats
60 
61    Collective on PC
62 
63    Input Parameter:
64 .  pc - the preconditioner context
65 
66    Level: developer
67 
68    Notes: This allows a PC to be reused for a different sized linear system but using the same options that have been previously set in the PC
69 
70 .keywords: PC, destroy
71 
72 .seealso: PCCreate(), PCSetUp()
73 @*/
74 PetscErrorCode  PCReset(PC pc)
75 {
76   PetscErrorCode ierr;
77 
78   PetscFunctionBegin;
79   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
80   if (pc->ops->reset) {
81     ierr = (*pc->ops->reset)(pc);CHKERRQ(ierr);
82   }
83   ierr = VecDestroy(&pc->diagonalscaleright);CHKERRQ(ierr);
84   ierr = VecDestroy(&pc->diagonalscaleleft);CHKERRQ(ierr);
85   ierr = MatDestroy(&pc->pmat);CHKERRQ(ierr);
86   ierr = MatDestroy(&pc->mat);CHKERRQ(ierr);
87 
88   pc->setupcalled = 0;
89   PetscFunctionReturn(0);
90 }
91 
92 #undef __FUNCT__
93 #define __FUNCT__ "PCDestroy"
94 /*@
95    PCDestroy - Destroys PC context that was created with PCCreate().
96 
97    Collective on PC
98 
99    Input Parameter:
100 .  pc - the preconditioner context
101 
102    Level: developer
103 
104 .keywords: PC, destroy
105 
106 .seealso: PCCreate(), PCSetUp()
107 @*/
108 PetscErrorCode  PCDestroy(PC *pc)
109 {
110   PetscErrorCode ierr;
111 
112   PetscFunctionBegin;
113   if (!*pc) PetscFunctionReturn(0);
114   PetscValidHeaderSpecific((*pc),PC_CLASSID,1);
115   if (--((PetscObject)(*pc))->refct > 0) {*pc = 0; PetscFunctionReturn(0);}
116 
117   ierr = PCReset(*pc);CHKERRQ(ierr);
118 
119   /* if memory was published with SAWs then destroy it */
120   ierr = PetscObjectSAWsViewOff((PetscObject)*pc);CHKERRQ(ierr);
121   if ((*pc)->ops->destroy) {ierr = (*(*pc)->ops->destroy)((*pc));CHKERRQ(ierr);}
122   ierr = DMDestroy(&(*pc)->dm);CHKERRQ(ierr);
123   ierr = PetscHeaderDestroy(pc);CHKERRQ(ierr);
124   PetscFunctionReturn(0);
125 }
126 
127 #undef __FUNCT__
128 #define __FUNCT__ "PCGetDiagonalScale"
129 /*@C
130    PCGetDiagonalScale - Indicates if the preconditioner applies an additional left and right
131       scaling as needed by certain time-stepping codes.
132 
133    Logically Collective on PC
134 
135    Input Parameter:
136 .  pc - the preconditioner context
137 
138    Output Parameter:
139 .  flag - PETSC_TRUE if it applies the scaling
140 
141    Level: developer
142 
143    Notes: If this returns PETSC_TRUE then the system solved via the Krylov method is
144 $           D M A D^{-1} y = D M b  for left preconditioning or
145 $           D A M D^{-1} z = D b for right preconditioning
146 
147 .keywords: PC
148 
149 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCSetDiagonalScale()
150 @*/
151 PetscErrorCode  PCGetDiagonalScale(PC pc,PetscBool  *flag)
152 {
153   PetscFunctionBegin;
154   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
155   PetscValidPointer(flag,2);
156   *flag = pc->diagonalscale;
157   PetscFunctionReturn(0);
158 }
159 
160 #undef __FUNCT__
161 #define __FUNCT__ "PCSetDiagonalScale"
162 /*@
163    PCSetDiagonalScale - Indicates the left scaling to use to apply an additional left and right
164       scaling as needed by certain time-stepping codes.
165 
166    Logically Collective on PC
167 
168    Input Parameters:
169 +  pc - the preconditioner context
170 -  s - scaling vector
171 
172    Level: intermediate
173 
174    Notes: The system solved via the Krylov method is
175 $           D M A D^{-1} y = D M b  for left preconditioning or
176 $           D A M D^{-1} z = D b for right preconditioning
177 
178    PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
179 
180 .keywords: PC
181 
182 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCGetDiagonalScale()
183 @*/
184 PetscErrorCode  PCSetDiagonalScale(PC pc,Vec s)
185 {
186   PetscErrorCode ierr;
187 
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
190   PetscValidHeaderSpecific(s,VEC_CLASSID,2);
191   pc->diagonalscale     = PETSC_TRUE;
192 
193   ierr = PetscObjectReference((PetscObject)s);CHKERRQ(ierr);
194   ierr = VecDestroy(&pc->diagonalscaleleft);CHKERRQ(ierr);
195 
196   pc->diagonalscaleleft = s;
197 
198   ierr = VecDuplicate(s,&pc->diagonalscaleright);CHKERRQ(ierr);
199   ierr = VecCopy(s,pc->diagonalscaleright);CHKERRQ(ierr);
200   ierr = VecReciprocal(pc->diagonalscaleright);CHKERRQ(ierr);
201   PetscFunctionReturn(0);
202 }
203 
204 #undef __FUNCT__
205 #define __FUNCT__ "PCDiagonalScaleLeft"
206 /*@
207    PCDiagonalScaleLeft - Scales a vector by the left scaling as needed by certain time-stepping codes.
208 
209    Logically Collective on PC
210 
211    Input Parameters:
212 +  pc - the preconditioner context
213 .  in - input vector
214 +  out - scaled vector (maybe the same as in)
215 
216    Level: intermediate
217 
218    Notes: The system solved via the Krylov method is
219 $           D M A D^{-1} y = D M b  for left preconditioning or
220 $           D A M D^{-1} z = D b for right preconditioning
221 
222    PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
223 
224    If diagonal scaling is turned off and in is not out then in is copied to out
225 
226 .keywords: PC
227 
228 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
229 @*/
230 PetscErrorCode  PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
231 {
232   PetscErrorCode ierr;
233 
234   PetscFunctionBegin;
235   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
236   PetscValidHeaderSpecific(in,VEC_CLASSID,2);
237   PetscValidHeaderSpecific(out,VEC_CLASSID,3);
238   if (pc->diagonalscale) {
239     ierr = VecPointwiseMult(out,pc->diagonalscaleleft,in);CHKERRQ(ierr);
240   } else if (in != out) {
241     ierr = VecCopy(in,out);CHKERRQ(ierr);
242   }
243   PetscFunctionReturn(0);
244 }
245 
246 #undef __FUNCT__
247 #define __FUNCT__ "PCDiagonalScaleRight"
248 /*@
249    PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.
250 
251    Logically Collective on PC
252 
253    Input Parameters:
254 +  pc - the preconditioner context
255 .  in - input vector
256 +  out - scaled vector (maybe the same as in)
257 
258    Level: intermediate
259 
260    Notes: The system solved via the Krylov method is
261 $           D M A D^{-1} y = D M b  for left preconditioning or
262 $           D A M D^{-1} z = D b for right preconditioning
263 
264    PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
265 
266    If diagonal scaling is turned off and in is not out then in is copied to out
267 
268 .keywords: PC
269 
270 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
271 @*/
272 PetscErrorCode  PCDiagonalScaleRight(PC pc,Vec in,Vec out)
273 {
274   PetscErrorCode ierr;
275 
276   PetscFunctionBegin;
277   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
278   PetscValidHeaderSpecific(in,VEC_CLASSID,2);
279   PetscValidHeaderSpecific(out,VEC_CLASSID,3);
280   if (pc->diagonalscale) {
281     ierr = VecPointwiseMult(out,pc->diagonalscaleright,in);CHKERRQ(ierr);
282   } else if (in != out) {
283     ierr = VecCopy(in,out);CHKERRQ(ierr);
284   }
285   PetscFunctionReturn(0);
286 }
287 
288 #undef __FUNCT__
289 #define __FUNCT__ "PCSetUseAmat"
290 /*@
291    PCSetUseAmat - Sets a flag to indicate that when the preconditioner needs to apply (part of) the
292    operator during the preconditioning process it applies the Amat provided to TSSetRHSJacobian(),
293    TSSetIJacobian(), SNESSetJacobian(), KSPSetOperator() or PCSetOperator() not the Pmat.
294 
295    Logically Collective on PC
296 
297    Input Parameters:
298 +  pc - the preconditioner context
299 -  flg - PETSC_TRUE to use the Amat, PETSC_FALSE to use the Pmat (default is false)
300 
301    Options Database Key:
302 .  -pc_use_amat <true,false>
303 
304    Notes:
305    For the common case in which the linear system matrix and the matrix used to construct the
306    preconditioner are identical, this routine is does nothing.
307 
308    Level: intermediate
309 
310 .seealso: PCGetUseAmat(), PCBJACOBI, PGMG, PCFIELDSPLIT, PCCOMPOSITE
311 @*/
312 PetscErrorCode  PCSetUseAmat(PC pc,PetscBool flg)
313 {
314   PetscFunctionBegin;
315   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
316   pc->useAmat = flg;
317   PetscFunctionReturn(0);
318 }
319 
320 #undef __FUNCT__
321 #define __FUNCT__ "PCSetErrorIfFailure"
322 /*@
323    PCSetErrorIfFailure - Causes PC to generate an error if a FPE, for example a zero pivot, is detected.
324 
325    Logically Collective on PC
326 
327    Input Parameters:
328 +  pc - iterative context obtained from PCCreate()
329 -  flg - PETSC_TRUE indicates you want the error generated
330 
331    Level: advanced
332 
333    Notes:
334     Normally PETSc continues if a linear solver fails due to a failed setup of a preconditioner, you can call KSPGetConvergedReason() after a KSPSolve()
335     to determine if it has converged or failed. Or use -ksp_error_if_not_converged to cause the program to terminate as soon as lack of convergence is
336     detected.
337 
338     This is propagated into KSPs used by this PC, which then propagate it into PCs used by those KSPs
339 
340 .keywords: PC, set, initial guess, nonzero
341 
342 .seealso: PCGetInitialGuessNonzero(), PCSetInitialGuessKnoll(), PCGetInitialGuessKnoll()
343 @*/
344 PetscErrorCode  PCSetErrorIfFailure(PC pc,PetscBool flg)
345 {
346   PetscFunctionBegin;
347   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
348   PetscValidLogicalCollectiveBool(pc,flg,2);
349   pc->erroriffailure = flg;
350   PetscFunctionReturn(0);
351 }
352 
353 #undef __FUNCT__
354 #define __FUNCT__ "PCGetUseAmat"
355 /*@
356    PCGetUseAmat - Gets a flag to indicate that when the preconditioner needs to apply (part of) the
357    operator during the preconditioning process it applies the Amat provided to TSSetRHSJacobian(),
358    TSSetIJacobian(), SNESSetJacobian(), KSPSetOperator() or PCSetOperator() not the Pmat.
359 
360    Logically Collective on PC
361 
362    Input Parameter:
363 .  pc - the preconditioner context
364 
365    Output Parameter:
366 .  flg - PETSC_TRUE to use the Amat, PETSC_FALSE to use the Pmat (default is false)
367 
368    Notes:
369    For the common case in which the linear system matrix and the matrix used to construct the
370    preconditioner are identical, this routine is does nothing.
371 
372    Level: intermediate
373 
374 .seealso: PCSetUseAmat(), PCBJACOBI, PGMG, PCFIELDSPLIT, PCCOMPOSITE
375 @*/
376 PetscErrorCode  PCGetUseAmat(PC pc,PetscBool *flg)
377 {
378   PetscFunctionBegin;
379   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
380   *flg = pc->useAmat;
381   PetscFunctionReturn(0);
382 }
383 
384 #undef __FUNCT__
385 #define __FUNCT__ "PCCreate"
386 /*@
387    PCCreate - Creates a preconditioner context.
388 
389    Collective on MPI_Comm
390 
391    Input Parameter:
392 .  comm - MPI communicator
393 
394    Output Parameter:
395 .  pc - location to put the preconditioner context
396 
397    Notes:
398    The default preconditioner for sparse matrices is PCILU or PCICC with 0 fill on one process and block Jacobi with PCILU or ICC
399    in parallel. For dense matrices it is always PCNONE.
400 
401    Level: developer
402 
403 .keywords: PC, create, context
404 
405 .seealso: PCSetUp(), PCApply(), PCDestroy()
406 @*/
407 PetscErrorCode  PCCreate(MPI_Comm comm,PC *newpc)
408 {
409   PC             pc;
410   PetscErrorCode ierr;
411 
412   PetscFunctionBegin;
413   PetscValidPointer(newpc,1);
414   *newpc = 0;
415   ierr = PCInitializePackage();CHKERRQ(ierr);
416 
417   ierr = PetscHeaderCreate(pc,PC_CLASSID,"PC","Preconditioner","PC",comm,PCDestroy,PCView);CHKERRQ(ierr);
418 
419   pc->mat                  = 0;
420   pc->pmat                 = 0;
421   pc->setupcalled          = 0;
422   pc->setfromoptionscalled = 0;
423   pc->data                 = 0;
424   pc->diagonalscale        = PETSC_FALSE;
425   pc->diagonalscaleleft    = 0;
426   pc->diagonalscaleright   = 0;
427 
428   pc->modifysubmatrices  = 0;
429   pc->modifysubmatricesP = 0;
430 
431   *newpc = pc;
432   PetscFunctionReturn(0);
433 
434 }
435 
436 /* -------------------------------------------------------------------------------*/
437 
438 #undef __FUNCT__
439 #define __FUNCT__ "PCApply"
440 /*@
441    PCApply - Applies the preconditioner to a vector.
442 
443    Collective on PC and Vec
444 
445    Input Parameters:
446 +  pc - the preconditioner context
447 -  x - input vector
448 
449    Output Parameter:
450 .  y - output vector
451 
452    Level: developer
453 
454 .keywords: PC, apply
455 
456 .seealso: PCApplyTranspose(), PCApplyBAorAB()
457 @*/
458 PetscErrorCode  PCApply(PC pc,Vec x,Vec y)
459 {
460   PetscErrorCode ierr;
461   PetscInt       m,n,mv,nv;
462 
463   PetscFunctionBegin;
464   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
465   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
466   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
467   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
468   if (pc->erroriffailure) {ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr);}
469   ierr = MatGetLocalSize(pc->mat,&m,&n);CHKERRQ(ierr);
470   ierr = VecGetLocalSize(x,&nv);CHKERRQ(ierr);
471   ierr = VecGetLocalSize(y,&mv);CHKERRQ(ierr);
472   if (mv != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Preconditioner number of local rows %D does not equal resulting vector number of rows %D",m,mv);CHKERRQ(ierr);
473   if (nv != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Preconditioner number of local columns %D does not equal resulting vector number of rows %D",n,nv);CHKERRQ(ierr);
474   VecLocked(y,3);
475 
476   if (pc->setupcalled < 2) {
477     ierr = PCSetUp(pc);CHKERRQ(ierr);
478   }
479   if (!pc->ops->apply) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply");
480   ierr = VecLockPush(x);CHKERRQ(ierr);
481   ierr = PetscLogEventBegin(PC_Apply,pc,x,y,0);CHKERRQ(ierr);
482   ierr = (*pc->ops->apply)(pc,x,y);CHKERRQ(ierr);
483   ierr = PetscLogEventEnd(PC_Apply,pc,x,y,0);CHKERRQ(ierr);
484   if (pc->erroriffailure) {ierr = VecValidValues(y,3,PETSC_FALSE);CHKERRQ(ierr);}
485   ierr = VecLockPop(x);CHKERRQ(ierr);
486   PetscFunctionReturn(0);
487 }
488 
489 #undef __FUNCT__
490 #define __FUNCT__ "PCApplySymmetricLeft"
491 /*@
492    PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.
493 
494    Collective on PC and Vec
495 
496    Input Parameters:
497 +  pc - the preconditioner context
498 -  x - input vector
499 
500    Output Parameter:
501 .  y - output vector
502 
503    Notes:
504    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
505 
506    Level: developer
507 
508 .keywords: PC, apply, symmetric, left
509 
510 .seealso: PCApply(), PCApplySymmetricRight()
511 @*/
512 PetscErrorCode  PCApplySymmetricLeft(PC pc,Vec x,Vec y)
513 {
514   PetscErrorCode ierr;
515 
516   PetscFunctionBegin;
517   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
518   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
519   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
520   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
521   if (pc->erroriffailure) {ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr);}
522   if (pc->setupcalled < 2) {
523     ierr = PCSetUp(pc);CHKERRQ(ierr);
524   }
525   if (!pc->ops->applysymmetricleft) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have left symmetric apply");
526   ierr = VecLockPush(x);CHKERRQ(ierr);
527   ierr = PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);CHKERRQ(ierr);
528   ierr = (*pc->ops->applysymmetricleft)(pc,x,y);CHKERRQ(ierr);
529   ierr = PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);CHKERRQ(ierr);
530   ierr = VecLockPop(x);CHKERRQ(ierr);
531   if (pc->erroriffailure) {ierr = VecValidValues(y,3,PETSC_FALSE);CHKERRQ(ierr);}
532   PetscFunctionReturn(0);
533 }
534 
535 #undef __FUNCT__
536 #define __FUNCT__ "PCApplySymmetricRight"
537 /*@
538    PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.
539 
540    Collective on PC and Vec
541 
542    Input Parameters:
543 +  pc - the preconditioner context
544 -  x - input vector
545 
546    Output Parameter:
547 .  y - output vector
548 
549    Level: developer
550 
551    Notes:
552    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
553 
554 .keywords: PC, apply, symmetric, right
555 
556 .seealso: PCApply(), PCApplySymmetricLeft()
557 @*/
558 PetscErrorCode  PCApplySymmetricRight(PC pc,Vec x,Vec y)
559 {
560   PetscErrorCode ierr;
561 
562   PetscFunctionBegin;
563   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
564   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
565   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
566   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
567   if (pc->erroriffailure) {ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr);}
568   if (pc->setupcalled < 2) {
569     ierr = PCSetUp(pc);CHKERRQ(ierr);
570   }
571   if (!pc->ops->applysymmetricright) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have left symmetric apply");
572   ierr = VecLockPush(x);CHKERRQ(ierr);
573   ierr = PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);CHKERRQ(ierr);
574   ierr = (*pc->ops->applysymmetricright)(pc,x,y);CHKERRQ(ierr);
575   ierr = PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);CHKERRQ(ierr);
576   ierr = VecLockPop(x);CHKERRQ(ierr);
577   if (pc->erroriffailure) {ierr = VecValidValues(y,3,PETSC_FALSE);CHKERRQ(ierr);}
578   PetscFunctionReturn(0);
579 }
580 
581 #undef __FUNCT__
582 #define __FUNCT__ "PCApplyTranspose"
583 /*@
584    PCApplyTranspose - Applies the transpose of preconditioner to a vector.
585 
586    Collective on PC and Vec
587 
588    Input Parameters:
589 +  pc - the preconditioner context
590 -  x - input vector
591 
592    Output Parameter:
593 .  y - output vector
594 
595    Notes: For complex numbers this applies the non-Hermitian transpose.
596 
597    Developer Notes: We need to implement a PCApplyHermitianTranspose()
598 
599    Level: developer
600 
601 .keywords: PC, apply, transpose
602 
603 .seealso: PCApply(), PCApplyBAorAB(), PCApplyBAorABTranspose(), PCApplyTransposeExists()
604 @*/
605 PetscErrorCode  PCApplyTranspose(PC pc,Vec x,Vec y)
606 {
607   PetscErrorCode ierr;
608 
609   PetscFunctionBegin;
610   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
611   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
612   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
613   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
614   if (pc->erroriffailure) {ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr);}
615   if (pc->setupcalled < 2) {
616     ierr = PCSetUp(pc);CHKERRQ(ierr);
617   }
618   if (!pc->ops->applytranspose) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply transpose");
619   ierr = VecLockPush(x);CHKERRQ(ierr);
620   ierr = PetscLogEventBegin(PC_Apply,pc,x,y,0);CHKERRQ(ierr);
621   ierr = (*pc->ops->applytranspose)(pc,x,y);CHKERRQ(ierr);
622   ierr = PetscLogEventEnd(PC_Apply,pc,x,y,0);CHKERRQ(ierr);
623   ierr = VecLockPop(x);CHKERRQ(ierr);
624   if (pc->erroriffailure) {ierr = VecValidValues(y,3,PETSC_FALSE);CHKERRQ(ierr);}
625   PetscFunctionReturn(0);
626 }
627 
628 #undef __FUNCT__
629 #define __FUNCT__ "PCApplyTransposeExists"
630 /*@
631    PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation
632 
633    Collective on PC and Vec
634 
635    Input Parameters:
636 .  pc - the preconditioner context
637 
638    Output Parameter:
639 .  flg - PETSC_TRUE if a transpose operation is defined
640 
641    Level: developer
642 
643 .keywords: PC, apply, transpose
644 
645 .seealso: PCApplyTranspose()
646 @*/
647 PetscErrorCode  PCApplyTransposeExists(PC pc,PetscBool  *flg)
648 {
649   PetscFunctionBegin;
650   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
651   PetscValidPointer(flg,2);
652   if (pc->ops->applytranspose) *flg = PETSC_TRUE;
653   else *flg = PETSC_FALSE;
654   PetscFunctionReturn(0);
655 }
656 
657 #undef __FUNCT__
658 #define __FUNCT__ "PCApplyBAorAB"
659 /*@
660    PCApplyBAorAB - Applies the preconditioner and operator to a vector. y = B*A*x or y = A*B*x.
661 
662    Collective on PC and Vec
663 
664    Input Parameters:
665 +  pc - the preconditioner context
666 .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
667 .  x - input vector
668 -  work - work vector
669 
670    Output Parameter:
671 .  y - output vector
672 
673    Level: developer
674 
675    Notes: If the PC has had PCSetDiagonalScale() set then D M A D^{-1} for left preconditioning or  D A M D^{-1} is actually applied. Note that the
676    specific KSPSolve() method must also be written to handle the post-solve "correction" for the diagonal scaling.
677 
678 .keywords: PC, apply, operator
679 
680 .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
681 @*/
682 PetscErrorCode  PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
683 {
684   PetscErrorCode ierr;
685 
686   PetscFunctionBegin;
687   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
688   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
689   PetscValidHeaderSpecific(y,VEC_CLASSID,4);
690   PetscValidHeaderSpecific(work,VEC_CLASSID,5);
691   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
692   if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric");
693   if (pc->diagonalscale && side == PC_SYMMETRIC) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot include diagonal scaling with symmetric preconditioner application");
694   if (pc->erroriffailure) {ierr = VecValidValues(x,3,PETSC_TRUE);CHKERRQ(ierr);}
695 
696   if (pc->setupcalled < 2) {
697     ierr = PCSetUp(pc);CHKERRQ(ierr);
698   }
699 
700   if (pc->diagonalscale) {
701     if (pc->ops->applyBA) {
702       Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
703       ierr = VecDuplicate(x,&work2);CHKERRQ(ierr);
704       ierr = PCDiagonalScaleRight(pc,x,work2);CHKERRQ(ierr);
705       ierr = (*pc->ops->applyBA)(pc,side,work2,y,work);CHKERRQ(ierr);
706       ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr);
707       ierr = VecDestroy(&work2);CHKERRQ(ierr);
708     } else if (side == PC_RIGHT) {
709       ierr = PCDiagonalScaleRight(pc,x,y);CHKERRQ(ierr);
710       ierr = PCApply(pc,y,work);CHKERRQ(ierr);
711       ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr);
712       ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr);
713     } else if (side == PC_LEFT) {
714       ierr = PCDiagonalScaleRight(pc,x,y);CHKERRQ(ierr);
715       ierr = MatMult(pc->mat,y,work);CHKERRQ(ierr);
716       ierr = PCApply(pc,work,y);CHKERRQ(ierr);
717       ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr);
718     } else if (side == PC_SYMMETRIC) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot provide diagonal scaling with symmetric application of preconditioner");
719   } else {
720     if (pc->ops->applyBA) {
721       ierr = (*pc->ops->applyBA)(pc,side,x,y,work);CHKERRQ(ierr);
722     } else if (side == PC_RIGHT) {
723       ierr = PCApply(pc,x,work);CHKERRQ(ierr);
724       ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr);
725     } else if (side == PC_LEFT) {
726       ierr = MatMult(pc->mat,x,work);CHKERRQ(ierr);
727       ierr = PCApply(pc,work,y);CHKERRQ(ierr);
728     } else if (side == PC_SYMMETRIC) {
729       /* There's an extra copy here; maybe should provide 2 work vectors instead? */
730       ierr = PCApplySymmetricRight(pc,x,work);CHKERRQ(ierr);
731       ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr);
732       ierr = VecCopy(y,work);CHKERRQ(ierr);
733       ierr = PCApplySymmetricLeft(pc,work,y);CHKERRQ(ierr);
734     }
735   }
736   if (pc->erroriffailure) {ierr = VecValidValues(y,4,PETSC_FALSE);CHKERRQ(ierr);}
737   PetscFunctionReturn(0);
738 }
739 
740 #undef __FUNCT__
741 #define __FUNCT__ "PCApplyBAorABTranspose"
742 /*@
743    PCApplyBAorABTranspose - Applies the transpose of the preconditioner
744    and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
745    NOT tr(B*A) = tr(A)*tr(B).
746 
747    Collective on PC and Vec
748 
749    Input Parameters:
750 +  pc - the preconditioner context
751 .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
752 .  x - input vector
753 -  work - work vector
754 
755    Output Parameter:
756 .  y - output vector
757 
758 
759    Notes: this routine is used internally so that the same Krylov code can be used to solve A x = b and A' x = b, with a preconditioner
760       defined by B'. This is why this has the funny form that it computes tr(B) * tr(A)
761 
762     Level: developer
763 
764 .keywords: PC, apply, operator, transpose
765 
766 .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
767 @*/
768 PetscErrorCode  PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
769 {
770   PetscErrorCode ierr;
771 
772   PetscFunctionBegin;
773   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
774   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
775   PetscValidHeaderSpecific(y,VEC_CLASSID,4);
776   PetscValidHeaderSpecific(work,VEC_CLASSID,5);
777   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
778   if (pc->erroriffailure) {ierr = VecValidValues(x,3,PETSC_TRUE);CHKERRQ(ierr);}
779   if (pc->ops->applyBAtranspose) {
780     ierr = (*pc->ops->applyBAtranspose)(pc,side,x,y,work);CHKERRQ(ierr);
781     if (pc->erroriffailure) {ierr = VecValidValues(y,4,PETSC_FALSE);CHKERRQ(ierr);}
782     PetscFunctionReturn(0);
783   }
784   if (side != PC_LEFT && side != PC_RIGHT) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");
785 
786   if (pc->setupcalled < 2) {
787     ierr = PCSetUp(pc);CHKERRQ(ierr);
788   }
789 
790   if (side == PC_RIGHT) {
791     ierr = PCApplyTranspose(pc,x,work);CHKERRQ(ierr);
792     ierr = MatMultTranspose(pc->mat,work,y);CHKERRQ(ierr);
793   } else if (side == PC_LEFT) {
794     ierr = MatMultTranspose(pc->mat,x,work);CHKERRQ(ierr);
795     ierr = PCApplyTranspose(pc,work,y);CHKERRQ(ierr);
796   }
797   /* add support for PC_SYMMETRIC */
798   if (pc->erroriffailure) {ierr = VecValidValues(y,4,PETSC_FALSE);CHKERRQ(ierr);}
799   PetscFunctionReturn(0);
800 }
801 
802 /* -------------------------------------------------------------------------------*/
803 
804 #undef __FUNCT__
805 #define __FUNCT__ "PCApplyRichardsonExists"
806 /*@
807    PCApplyRichardsonExists - Determines whether a particular preconditioner has a
808    built-in fast application of Richardson's method.
809 
810    Not Collective
811 
812    Input Parameter:
813 .  pc - the preconditioner
814 
815    Output Parameter:
816 .  exists - PETSC_TRUE or PETSC_FALSE
817 
818    Level: developer
819 
820 .keywords: PC, apply, Richardson, exists
821 
822 .seealso: PCApplyRichardson()
823 @*/
824 PetscErrorCode  PCApplyRichardsonExists(PC pc,PetscBool  *exists)
825 {
826   PetscFunctionBegin;
827   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
828   PetscValidIntPointer(exists,2);
829   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
830   else *exists = PETSC_FALSE;
831   PetscFunctionReturn(0);
832 }
833 
834 #undef __FUNCT__
835 #define __FUNCT__ "PCApplyRichardson"
836 /*@
837    PCApplyRichardson - Applies several steps of Richardson iteration with
838    the particular preconditioner. This routine is usually used by the
839    Krylov solvers and not the application code directly.
840 
841    Collective on PC
842 
843    Input Parameters:
844 +  pc  - the preconditioner context
845 .  b   - the right hand side
846 .  w   - one work vector
847 .  rtol - relative decrease in residual norm convergence criteria
848 .  abstol - absolute residual norm convergence criteria
849 .  dtol - divergence residual norm increase criteria
850 .  its - the number of iterations to apply.
851 -  guesszero - if the input x contains nonzero initial guess
852 
853    Output Parameter:
854 +  outits - number of iterations actually used (for SOR this always equals its)
855 .  reason - the reason the apply terminated
856 -  y - the solution (also contains initial guess if guesszero is PETSC_FALSE
857 
858    Notes:
859    Most preconditioners do not support this function. Use the command
860    PCApplyRichardsonExists() to determine if one does.
861 
862    Except for the multigrid PC this routine ignores the convergence tolerances
863    and always runs for the number of iterations
864 
865    Level: developer
866 
867 .keywords: PC, apply, Richardson
868 
869 .seealso: PCApplyRichardsonExists()
870 @*/
871 PetscErrorCode  PCApplyRichardson(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
872 {
873   PetscErrorCode ierr;
874 
875   PetscFunctionBegin;
876   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
877   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
878   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
879   PetscValidHeaderSpecific(w,VEC_CLASSID,4);
880   if (b == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"b and y must be different vectors");
881   if (pc->setupcalled < 2) {
882     ierr = PCSetUp(pc);CHKERRQ(ierr);
883   }
884   if (!pc->ops->applyrichardson) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply richardson");
885   ierr = (*pc->ops->applyrichardson)(pc,b,y,w,rtol,abstol,dtol,its,guesszero,outits,reason);CHKERRQ(ierr);
886   PetscFunctionReturn(0);
887 }
888 
889 #undef __FUNCT__
890 #define __FUNCT__ "PCGetSetUpFailedReason"
891 /*@
892    PCGetSetUpFailedReason - Gets the reason a PCSetUp() failed or 0 if it did not fail
893 
894    Logically Collective on PC
895 
896    Input Parameter:
897 .  pc - the preconditioner context
898 
899    Output Parameter:
900 .  reason - the reason it failed, currently only -1
901 
902    Level: advanced
903 
904 .keywords: PC, setup
905 
906 .seealso: PCCreate(), PCApply(), PCDestroy()
907 @*/
908 PetscErrorCode  PCGetSetUpFailedReason(PC pc,PetscInt *reason)
909 {
910   PetscFunctionBegin;
911   if (pc->setupcalled < 0) *reason = pc->setupcalled;
912   else *reason = 0;
913   PetscFunctionReturn(0);
914 }
915 
916 
917 /*
918       a setupcall of 0 indicates never setup,
919                      1 indicates has been previously setup
920                     -1 indicates a PCSetUp() was attempted and failed
921 */
922 #undef __FUNCT__
923 #define __FUNCT__ "PCSetUp"
924 /*@
925    PCSetUp - Prepares for the use of a preconditioner.
926 
927    Collective on PC
928 
929    Input Parameter:
930 .  pc - the preconditioner context
931 
932    Level: developer
933 
934 .keywords: PC, setup
935 
936 .seealso: PCCreate(), PCApply(), PCDestroy()
937 @*/
938 PetscErrorCode  PCSetUp(PC pc)
939 {
940   PetscErrorCode   ierr;
941   const char       *def;
942   PetscObjectState matstate, matnonzerostate;
943 
944   PetscFunctionBegin;
945   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
946   if (!pc->mat) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");
947 
948   if (pc->setupcalled && pc->reusepreconditioner) {
949     ierr = PetscInfo(pc,"Leaving PC with identical preconditioner since reuse preconditioner is set\n");CHKERRQ(ierr);
950     PetscFunctionReturn(0);
951   }
952 
953   ierr = PetscObjectStateGet((PetscObject)pc->pmat,&matstate);CHKERRQ(ierr);
954   ierr = MatGetNonzeroState(pc->pmat,&matnonzerostate);CHKERRQ(ierr);
955   if (!pc->setupcalled) {
956     ierr            = PetscInfo(pc,"Setting up PC for first time\n");CHKERRQ(ierr);
957     pc->flag        = DIFFERENT_NONZERO_PATTERN;
958   } else if (matstate == pc->matstate) {
959     ierr = PetscInfo(pc,"Leaving PC with identical preconditioner since operator is unchanged\n");CHKERRQ(ierr);
960     PetscFunctionReturn(0);
961   } else {
962     if (matnonzerostate > pc->matnonzerostate) {
963        ierr = PetscInfo(pc,"Setting up PC with different nonzero pattern\n");CHKERRQ(ierr);
964        pc->flag            = DIFFERENT_NONZERO_PATTERN;
965     } else {
966       ierr = PetscInfo(pc,"Setting up PC with same nonzero pattern\n");CHKERRQ(ierr);
967       pc->flag            = SAME_NONZERO_PATTERN;
968     }
969   }
970   pc->matstate        = matstate;
971   pc->matnonzerostate = matnonzerostate;
972 
973   if (!((PetscObject)pc)->type_name) {
974     ierr = PCGetDefaultType_Private(pc,&def);CHKERRQ(ierr);
975     ierr = PCSetType(pc,def);CHKERRQ(ierr);
976   }
977 
978   ierr = MatSetErrorIfFPE(pc->pmat,pc->erroriffailure);CHKERRQ(ierr);
979   ierr = MatSetErrorIfFPE(pc->mat,pc->erroriffailure);CHKERRQ(ierr);
980   ierr = PetscLogEventBegin(PC_SetUp,pc,0,0,0);CHKERRQ(ierr);
981   if (pc->ops->setup) {
982     ierr = (*pc->ops->setup)(pc);CHKERRQ(ierr);
983   }
984   ierr = PetscLogEventEnd(PC_SetUp,pc,0,0,0);CHKERRQ(ierr);
985   if (!pc->setupcalled) pc->setupcalled = 1;
986   PetscFunctionReturn(0);
987 }
988 
989 #undef __FUNCT__
990 #define __FUNCT__ "PCSetUpOnBlocks"
991 /*@
992    PCSetUpOnBlocks - Sets up the preconditioner for each block in
993    the block Jacobi, block Gauss-Seidel, and overlapping Schwarz
994    methods.
995 
996    Collective on PC
997 
998    Input Parameters:
999 .  pc - the preconditioner context
1000 
1001    Level: developer
1002 
1003 .keywords: PC, setup, blocks
1004 
1005 .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
1006 @*/
1007 PetscErrorCode  PCSetUpOnBlocks(PC pc)
1008 {
1009   PetscErrorCode ierr;
1010 
1011   PetscFunctionBegin;
1012   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1013   if (!pc->ops->setuponblocks) PetscFunctionReturn(0);
1014   ierr = PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);CHKERRQ(ierr);
1015   ierr = (*pc->ops->setuponblocks)(pc);CHKERRQ(ierr);
1016   ierr = PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);CHKERRQ(ierr);
1017   PetscFunctionReturn(0);
1018 }
1019 
1020 #undef __FUNCT__
1021 #define __FUNCT__ "PCSetModifySubMatrices"
1022 /*@C
1023    PCSetModifySubMatrices - Sets a user-defined routine for modifying the
1024    submatrices that arise within certain subdomain-based preconditioners.
1025    The basic submatrices are extracted from the preconditioner matrix as
1026    usual; the user can then alter these (for example, to set different boundary
1027    conditions for each submatrix) before they are used for the local solves.
1028 
1029    Logically Collective on PC
1030 
1031    Input Parameters:
1032 +  pc - the preconditioner context
1033 .  func - routine for modifying the submatrices
1034 -  ctx - optional user-defined context (may be null)
1035 
1036    Calling sequence of func:
1037 $     func (PC pc,PetscInt nsub,IS *row,IS *col,Mat *submat,void *ctx);
1038 
1039 .  row - an array of index sets that contain the global row numbers
1040          that comprise each local submatrix
1041 .  col - an array of index sets that contain the global column numbers
1042          that comprise each local submatrix
1043 .  submat - array of local submatrices
1044 -  ctx - optional user-defined context for private data for the
1045          user-defined func routine (may be null)
1046 
1047    Notes:
1048    PCSetModifySubMatrices() MUST be called before KSPSetUp() and
1049    KSPSolve().
1050 
1051    A routine set by PCSetModifySubMatrices() is currently called within
1052    the block Jacobi (PCBJACOBI) and additive Schwarz (PCASM)
1053    preconditioners.  All other preconditioners ignore this routine.
1054 
1055    Level: advanced
1056 
1057 .keywords: PC, set, modify, submatrices
1058 
1059 .seealso: PCModifySubMatrices(), PCASMGetSubMatrices()
1060 @*/
1061 PetscErrorCode  PCSetModifySubMatrices(PC pc,PetscErrorCode (*func)(PC,PetscInt,const IS[],const IS[],Mat[],void*),void *ctx)
1062 {
1063   PetscFunctionBegin;
1064   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1065   pc->modifysubmatrices  = func;
1066   pc->modifysubmatricesP = ctx;
1067   PetscFunctionReturn(0);
1068 }
1069 
1070 #undef __FUNCT__
1071 #define __FUNCT__ "PCModifySubMatrices"
1072 /*@C
1073    PCModifySubMatrices - Calls an optional user-defined routine within
1074    certain preconditioners if one has been set with PCSetModifySubMarices().
1075 
1076    Collective on PC
1077 
1078    Input Parameters:
1079 +  pc - the preconditioner context
1080 .  nsub - the number of local submatrices
1081 .  row - an array of index sets that contain the global row numbers
1082          that comprise each local submatrix
1083 .  col - an array of index sets that contain the global column numbers
1084          that comprise each local submatrix
1085 .  submat - array of local submatrices
1086 -  ctx - optional user-defined context for private data for the
1087          user-defined routine (may be null)
1088 
1089    Output Parameter:
1090 .  submat - array of local submatrices (the entries of which may
1091             have been modified)
1092 
1093    Notes:
1094    The user should NOT generally call this routine, as it will
1095    automatically be called within certain preconditioners (currently
1096    block Jacobi, additive Schwarz) if set.
1097 
1098    The basic submatrices are extracted from the preconditioner matrix
1099    as usual; the user can then alter these (for example, to set different
1100    boundary conditions for each submatrix) before they are used for the
1101    local solves.
1102 
1103    Level: developer
1104 
1105 .keywords: PC, modify, submatrices
1106 
1107 .seealso: PCSetModifySubMatrices()
1108 @*/
1109 PetscErrorCode  PCModifySubMatrices(PC pc,PetscInt nsub,const IS row[],const IS col[],Mat submat[],void *ctx)
1110 {
1111   PetscErrorCode ierr;
1112 
1113   PetscFunctionBegin;
1114   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1115   if (!pc->modifysubmatrices) PetscFunctionReturn(0);
1116   ierr = PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);CHKERRQ(ierr);
1117   ierr = (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);CHKERRQ(ierr);
1118   ierr = PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);CHKERRQ(ierr);
1119   PetscFunctionReturn(0);
1120 }
1121 
1122 #undef __FUNCT__
1123 #define __FUNCT__ "PCSetOperators"
1124 /*@
1125    PCSetOperators - Sets the matrix associated with the linear system and
1126    a (possibly) different one associated with the preconditioner.
1127 
1128    Logically Collective on PC and Mat
1129 
1130    Input Parameters:
1131 +  pc - the preconditioner context
1132 .  Amat - the matrix that defines the linear system
1133 -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
1134 
1135    Notes:
1136     Passing a NULL for Amat or Pmat removes the matrix that is currently used.
1137 
1138     If you wish to replace either Amat or Pmat but leave the other one untouched then
1139     first call KSPGetOperators() to get the one you wish to keep, call PetscObjectReference()
1140     on it and then pass it back in in your call to KSPSetOperators().
1141 
1142    More Notes about Repeated Solution of Linear Systems:
1143    PETSc does NOT reset the matrix entries of either Amat or Pmat
1144    to zero after a linear solve; the user is completely responsible for
1145    matrix assembly.  See the routine MatZeroEntries() if desiring to
1146    zero all elements of a matrix.
1147 
1148    Level: intermediate
1149 
1150 .keywords: PC, set, operators, matrix, linear system
1151 
1152 .seealso: PCGetOperators(), MatZeroEntries()
1153  @*/
1154 PetscErrorCode  PCSetOperators(PC pc,Mat Amat,Mat Pmat)
1155 {
1156   PetscErrorCode   ierr;
1157   PetscInt         m1,n1,m2,n2;
1158 
1159   PetscFunctionBegin;
1160   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1161   if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
1162   if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3);
1163   if (Amat) PetscCheckSameComm(pc,1,Amat,2);
1164   if (Pmat) PetscCheckSameComm(pc,1,Pmat,3);
1165   if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) {
1166     ierr = MatGetLocalSize(Amat,&m1,&n1);CHKERRQ(ierr);
1167     ierr = MatGetLocalSize(pc->mat,&m2,&n2);CHKERRQ(ierr);
1168     if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot change local size of Amat after use old sizes %D %D new sizes %D %D",m2,n2,m1,n1);
1169     ierr = MatGetLocalSize(Pmat,&m1,&n1);CHKERRQ(ierr);
1170     ierr = MatGetLocalSize(pc->pmat,&m2,&n2);CHKERRQ(ierr);
1171     if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot change local size of Pmat after use old sizes %D %D new sizes %D %D",m2,n2,m1,n1);
1172   }
1173 
1174   if (Pmat != pc->pmat) {
1175     /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */
1176     pc->matnonzerostate = -1;
1177     pc->matstate        = -1;
1178   }
1179 
1180   /* reference first in case the matrices are the same */
1181   if (Amat) {ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);}
1182   ierr = MatDestroy(&pc->mat);CHKERRQ(ierr);
1183   if (Pmat) {ierr = PetscObjectReference((PetscObject)Pmat);CHKERRQ(ierr);}
1184   ierr     = MatDestroy(&pc->pmat);CHKERRQ(ierr);
1185   pc->mat  = Amat;
1186   pc->pmat = Pmat;
1187   PetscFunctionReturn(0);
1188 }
1189 
1190 #undef __FUNCT__
1191 #define __FUNCT__ "PCSetReusePreconditioner"
1192 /*@
1193    PCSetReusePreconditioner - reuse the current preconditioner even if the operator in the preconditioner has changed.
1194 
1195    Logically Collective on PC
1196 
1197    Input Parameters:
1198 +  pc - the preconditioner context
1199 -  flag - PETSC_TRUE do not compute a new preconditioner, PETSC_FALSE do compute a new preconditioner
1200 
1201     Level: intermediate
1202 
1203 .seealso: PCGetOperators(), MatZeroEntries(), PCGetReusePreconditioner(), KSPSetReusePreconditioner()
1204  @*/
1205 PetscErrorCode  PCSetReusePreconditioner(PC pc,PetscBool flag)
1206 {
1207   PetscFunctionBegin;
1208   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1209   pc->reusepreconditioner = flag;
1210   PetscFunctionReturn(0);
1211 }
1212 
1213 #undef __FUNCT__
1214 #define __FUNCT__ "PCGetReusePreconditioner"
1215 /*@
1216    PCGetReusePreconditioner - Determines if the PC reuses the current preconditioner even if the operator in the preconditioner has changed.
1217 
1218    Not Collective
1219 
1220    Input Parameter:
1221 .  pc - the preconditioner context
1222 
1223    Output Parameter:
1224 .  flag - PETSC_TRUE do not compute a new preconditioner, PETSC_FALSE do compute a new preconditioner
1225 
1226    Level: intermediate
1227 
1228 .seealso: PCGetOperators(), MatZeroEntries(), PCSetReusePreconditioner()
1229  @*/
1230 PetscErrorCode  PCGetReusePreconditioner(PC pc,PetscBool *flag)
1231 {
1232   PetscFunctionBegin;
1233   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1234   *flag = pc->reusepreconditioner;
1235   PetscFunctionReturn(0);
1236 }
1237 
1238 #undef __FUNCT__
1239 #define __FUNCT__ "PCGetOperators"
1240 /*@C
1241    PCGetOperators - Gets the matrix associated with the linear system and
1242    possibly a different one associated with the preconditioner.
1243 
1244    Not collective, though parallel Mats are returned if the PC is parallel
1245 
1246    Input Parameter:
1247 .  pc - the preconditioner context
1248 
1249    Output Parameters:
1250 +  Amat - the matrix defining the linear system
1251 -  Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat.
1252 
1253    Level: intermediate
1254 
1255    Notes: Does not increase the reference count of the matrices, so you should not destroy them
1256 
1257    Alternative usage: If the operators have NOT been set with KSP/PCSetOperators() then the operators
1258       are created in PC and returned to the user. In this case, if both operators
1259       mat and pmat are requested, two DIFFERENT operators will be returned. If
1260       only one is requested both operators in the PC will be the same (i.e. as
1261       if one had called KSP/PCSetOperators() with the same argument for both Mats).
1262       The user must set the sizes of the returned matrices and their type etc just
1263       as if the user created them with MatCreate(). For example,
1264 
1265 $         KSP/PCGetOperators(ksp/pc,&Amat,NULL); is equivalent to
1266 $           set size, type, etc of Amat
1267 
1268 $         MatCreate(comm,&mat);
1269 $         KSP/PCSetOperators(ksp/pc,Amat,Amat);
1270 $         PetscObjectDereference((PetscObject)mat);
1271 $           set size, type, etc of Amat
1272 
1273      and
1274 
1275 $         KSP/PCGetOperators(ksp/pc,&Amat,&Pmat); is equivalent to
1276 $           set size, type, etc of Amat and Pmat
1277 
1278 $         MatCreate(comm,&Amat);
1279 $         MatCreate(comm,&Pmat);
1280 $         KSP/PCSetOperators(ksp/pc,Amat,Pmat);
1281 $         PetscObjectDereference((PetscObject)Amat);
1282 $         PetscObjectDereference((PetscObject)Pmat);
1283 $           set size, type, etc of Amat and Pmat
1284 
1285     The rational for this support is so that when creating a TS, SNES, or KSP the hierarchy
1286     of underlying objects (i.e. SNES, KSP, PC, Mat) and their livespans can be completely
1287     managed by the top most level object (i.e. the TS, SNES, or KSP). Another way to look
1288     at this is when you create a SNES you do not NEED to create a KSP and attach it to
1289     the SNES object (the SNES object manages it for you). Similarly when you create a KSP
1290     you do not need to attach a PC to it (the KSP object manages the PC object for you).
1291     Thus, why should YOU have to create the Mat and attach it to the SNES/KSP/PC, when
1292     it can be created for you?
1293 
1294 
1295 .keywords: PC, get, operators, matrix, linear system
1296 
1297 .seealso: PCSetOperators(), KSPGetOperators(), KSPSetOperators(), PCGetOperatorsSet()
1298 @*/
1299 PetscErrorCode  PCGetOperators(PC pc,Mat *Amat,Mat *Pmat)
1300 {
1301   PetscErrorCode ierr;
1302 
1303   PetscFunctionBegin;
1304   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1305   if (Amat) {
1306     if (!pc->mat) {
1307       if (pc->pmat && !Pmat) {  /* Apmat has been set, but user did not request it, so use for Amat */
1308         pc->mat = pc->pmat;
1309         ierr    = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr);
1310       } else {                  /* both Amat and Pmat are empty */
1311         ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pc->mat);CHKERRQ(ierr);
1312         if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */
1313           pc->pmat = pc->mat;
1314           ierr     = PetscObjectReference((PetscObject)pc->pmat);CHKERRQ(ierr);
1315         }
1316       }
1317     }
1318     *Amat = pc->mat;
1319   }
1320   if (Pmat) {
1321     if (!pc->pmat) {
1322       if (pc->mat && !Amat) {    /* Amat has been set but was not requested, so use for pmat */
1323         pc->pmat = pc->mat;
1324         ierr     = PetscObjectReference((PetscObject)pc->pmat);CHKERRQ(ierr);
1325       } else {
1326         ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pc->pmat);CHKERRQ(ierr);
1327         if (!Amat) { /* user did NOT request Amat, so make same as Pmat */
1328           pc->mat = pc->pmat;
1329           ierr    = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr);
1330         }
1331       }
1332     }
1333     *Pmat = pc->pmat;
1334   }
1335   PetscFunctionReturn(0);
1336 }
1337 
1338 #undef __FUNCT__
1339 #define __FUNCT__ "PCGetOperatorsSet"
1340 /*@C
1341    PCGetOperatorsSet - Determines if the matrix associated with the linear system and
1342    possibly a different one associated with the preconditioner have been set in the PC.
1343 
1344    Not collective, though the results on all processes should be the same
1345 
1346    Input Parameter:
1347 .  pc - the preconditioner context
1348 
1349    Output Parameters:
1350 +  mat - the matrix associated with the linear system was set
1351 -  pmat - matrix associated with the preconditioner was set, usually the same
1352 
1353    Level: intermediate
1354 
1355 .keywords: PC, get, operators, matrix, linear system
1356 
1357 .seealso: PCSetOperators(), KSPGetOperators(), KSPSetOperators(), PCGetOperators()
1358 @*/
1359 PetscErrorCode  PCGetOperatorsSet(PC pc,PetscBool  *mat,PetscBool  *pmat)
1360 {
1361   PetscFunctionBegin;
1362   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1363   if (mat) *mat = (pc->mat)  ? PETSC_TRUE : PETSC_FALSE;
1364   if (pmat) *pmat = (pc->pmat) ? PETSC_TRUE : PETSC_FALSE;
1365   PetscFunctionReturn(0);
1366 }
1367 
1368 #undef __FUNCT__
1369 #define __FUNCT__ "PCFactorGetMatrix"
1370 /*@
1371    PCFactorGetMatrix - Gets the factored matrix from the
1372    preconditioner context.  This routine is valid only for the LU,
1373    incomplete LU, Cholesky, and incomplete Cholesky methods.
1374 
1375    Not Collective on PC though Mat is parallel if PC is parallel
1376 
1377    Input Parameters:
1378 .  pc - the preconditioner context
1379 
1380    Output parameters:
1381 .  mat - the factored matrix
1382 
1383    Level: advanced
1384 
1385    Notes: Does not increase the reference count for the matrix so DO NOT destroy it
1386 
1387 .keywords: PC, get, factored, matrix
1388 @*/
1389 PetscErrorCode  PCFactorGetMatrix(PC pc,Mat *mat)
1390 {
1391   PetscErrorCode ierr;
1392 
1393   PetscFunctionBegin;
1394   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1395   PetscValidPointer(mat,2);
1396   if (pc->ops->getfactoredmatrix) {
1397     ierr = (*pc->ops->getfactoredmatrix)(pc,mat);CHKERRQ(ierr);
1398   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC type does not support getting factor matrix");
1399   PetscFunctionReturn(0);
1400 }
1401 
1402 #undef __FUNCT__
1403 #define __FUNCT__ "PCSetOptionsPrefix"
1404 /*@C
1405    PCSetOptionsPrefix - Sets the prefix used for searching for all
1406    PC options in the database.
1407 
1408    Logically Collective on PC
1409 
1410    Input Parameters:
1411 +  pc - the preconditioner context
1412 -  prefix - the prefix string to prepend to all PC option requests
1413 
1414    Notes:
1415    A hyphen (-) must NOT be given at the beginning of the prefix name.
1416    The first character of all runtime options is AUTOMATICALLY the
1417    hyphen.
1418 
1419    Level: advanced
1420 
1421 .keywords: PC, set, options, prefix, database
1422 
1423 .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1424 @*/
1425 PetscErrorCode  PCSetOptionsPrefix(PC pc,const char prefix[])
1426 {
1427   PetscErrorCode ierr;
1428 
1429   PetscFunctionBegin;
1430   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1431   ierr = PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr);
1432   PetscFunctionReturn(0);
1433 }
1434 
1435 #undef __FUNCT__
1436 #define __FUNCT__ "PCAppendOptionsPrefix"
1437 /*@C
1438    PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1439    PC options in the database.
1440 
1441    Logically Collective on PC
1442 
1443    Input Parameters:
1444 +  pc - the preconditioner context
1445 -  prefix - the prefix string to prepend to all PC option requests
1446 
1447    Notes:
1448    A hyphen (-) must NOT be given at the beginning of the prefix name.
1449    The first character of all runtime options is AUTOMATICALLY the
1450    hyphen.
1451 
1452    Level: advanced
1453 
1454 .keywords: PC, append, options, prefix, database
1455 
1456 .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1457 @*/
1458 PetscErrorCode  PCAppendOptionsPrefix(PC pc,const char prefix[])
1459 {
1460   PetscErrorCode ierr;
1461 
1462   PetscFunctionBegin;
1463   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1464   ierr = PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr);
1465   PetscFunctionReturn(0);
1466 }
1467 
1468 #undef __FUNCT__
1469 #define __FUNCT__ "PCGetOptionsPrefix"
1470 /*@C
1471    PCGetOptionsPrefix - Gets the prefix used for searching for all
1472    PC options in the database.
1473 
1474    Not Collective
1475 
1476    Input Parameters:
1477 .  pc - the preconditioner context
1478 
1479    Output Parameters:
1480 .  prefix - pointer to the prefix string used, is returned
1481 
1482    Notes: On the fortran side, the user should pass in a string 'prifix' of
1483    sufficient length to hold the prefix.
1484 
1485    Level: advanced
1486 
1487 .keywords: PC, get, options, prefix, database
1488 
1489 .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1490 @*/
1491 PetscErrorCode  PCGetOptionsPrefix(PC pc,const char *prefix[])
1492 {
1493   PetscErrorCode ierr;
1494 
1495   PetscFunctionBegin;
1496   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1497   PetscValidPointer(prefix,2);
1498   ierr = PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr);
1499   PetscFunctionReturn(0);
1500 }
1501 
1502 #undef __FUNCT__
1503 #define __FUNCT__ "PCPreSolve"
1504 /*@
1505    PCPreSolve - Optional pre-solve phase, intended for any
1506    preconditioner-specific actions that must be performed before
1507    the iterative solve itself.
1508 
1509    Collective on PC
1510 
1511    Input Parameters:
1512 +  pc - the preconditioner context
1513 -  ksp - the Krylov subspace context
1514 
1515    Level: developer
1516 
1517    Sample of Usage:
1518 .vb
1519     PCPreSolve(pc,ksp);
1520     KSPSolve(ksp,b,x);
1521     PCPostSolve(pc,ksp);
1522 .ve
1523 
1524    Notes:
1525    The pre-solve phase is distinct from the PCSetUp() phase.
1526 
1527    KSPSolve() calls this directly, so is rarely called by the user.
1528 
1529 .keywords: PC, pre-solve
1530 
1531 .seealso: PCPostSolve()
1532 @*/
1533 PetscErrorCode  PCPreSolve(PC pc,KSP ksp)
1534 {
1535   PetscErrorCode ierr;
1536   Vec            x,rhs;
1537 
1538   PetscFunctionBegin;
1539   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1540   PetscValidHeaderSpecific(ksp,KSP_CLASSID,2);
1541   pc->presolvedone++;
1542   if (pc->presolvedone > 2) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot embed PCPreSolve() more than twice");
1543   ierr = KSPGetSolution(ksp,&x);CHKERRQ(ierr);
1544   ierr = KSPGetRhs(ksp,&rhs);CHKERRQ(ierr);
1545 
1546   if (pc->ops->presolve) {
1547     ierr = (*pc->ops->presolve)(pc,ksp,rhs,x);CHKERRQ(ierr);
1548   }
1549   PetscFunctionReturn(0);
1550 }
1551 
1552 #undef __FUNCT__
1553 #define __FUNCT__ "PCPostSolve"
1554 /*@
1555    PCPostSolve - Optional post-solve phase, intended for any
1556    preconditioner-specific actions that must be performed after
1557    the iterative solve itself.
1558 
1559    Collective on PC
1560 
1561    Input Parameters:
1562 +  pc - the preconditioner context
1563 -  ksp - the Krylov subspace context
1564 
1565    Sample of Usage:
1566 .vb
1567     PCPreSolve(pc,ksp);
1568     KSPSolve(ksp,b,x);
1569     PCPostSolve(pc,ksp);
1570 .ve
1571 
1572    Note:
1573    KSPSolve() calls this routine directly, so it is rarely called by the user.
1574 
1575    Level: developer
1576 
1577 .keywords: PC, post-solve
1578 
1579 .seealso: PCPreSolve(), KSPSolve()
1580 @*/
1581 PetscErrorCode  PCPostSolve(PC pc,KSP ksp)
1582 {
1583   PetscErrorCode ierr;
1584   Vec            x,rhs;
1585 
1586   PetscFunctionBegin;
1587   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1588   PetscValidHeaderSpecific(ksp,KSP_CLASSID,2);
1589   pc->presolvedone--;
1590   ierr = KSPGetSolution(ksp,&x);CHKERRQ(ierr);
1591   ierr = KSPGetRhs(ksp,&rhs);CHKERRQ(ierr);
1592   if (pc->ops->postsolve) {
1593     ierr =  (*pc->ops->postsolve)(pc,ksp,rhs,x);CHKERRQ(ierr);
1594   }
1595   PetscFunctionReturn(0);
1596 }
1597 
1598 #undef __FUNCT__
1599 #define __FUNCT__ "PCLoad"
1600 /*@C
1601   PCLoad - Loads a PC that has been stored in binary  with PCView().
1602 
1603   Collective on PetscViewer
1604 
1605   Input Parameters:
1606 + newdm - the newly loaded PC, this needs to have been created with PCCreate() or
1607            some related function before a call to PCLoad().
1608 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen()
1609 
1610    Level: intermediate
1611 
1612   Notes:
1613    The type is determined by the data in the file, any type set into the PC before this call is ignored.
1614 
1615   Notes for advanced users:
1616   Most users should not need to know the details of the binary storage
1617   format, since PCLoad() and PCView() completely hide these details.
1618   But for anyone who's interested, the standard binary matrix storage
1619   format is
1620 .vb
1621      has not yet been determined
1622 .ve
1623 
1624 .seealso: PetscViewerBinaryOpen(), PCView(), MatLoad(), VecLoad()
1625 @*/
1626 PetscErrorCode  PCLoad(PC newdm, PetscViewer viewer)
1627 {
1628   PetscErrorCode ierr;
1629   PetscBool      isbinary;
1630   PetscInt       classid;
1631   char           type[256];
1632 
1633   PetscFunctionBegin;
1634   PetscValidHeaderSpecific(newdm,PC_CLASSID,1);
1635   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1636   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1637   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
1638 
1639   ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr);
1640   if (classid != PC_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not PC next in file");
1641   ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr);
1642   ierr = PCSetType(newdm, type);CHKERRQ(ierr);
1643   if (newdm->ops->load) {
1644     ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);
1645   }
1646   PetscFunctionReturn(0);
1647 }
1648 
1649 #include <petscdraw.h>
1650 #if defined(PETSC_HAVE_SAWS)
1651 #include <petscviewersaws.h>
1652 #endif
1653 #undef __FUNCT__
1654 #define __FUNCT__ "PCView"
1655 /*@C
1656    PCView - Prints the PC data structure.
1657 
1658    Collective on PC
1659 
1660    Input Parameters:
1661 +  PC - the PC context
1662 -  viewer - optional visualization context
1663 
1664    Note:
1665    The available visualization contexts include
1666 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
1667 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1668          output where only the first processor opens
1669          the file.  All other processors send their
1670          data to the first processor to print.
1671 
1672    The user can open an alternative visualization contexts with
1673    PetscViewerASCIIOpen() (output to a specified file).
1674 
1675    Level: developer
1676 
1677 .keywords: PC, view
1678 
1679 .seealso: KSPView(), PetscViewerASCIIOpen()
1680 @*/
1681 PetscErrorCode  PCView(PC pc,PetscViewer viewer)
1682 {
1683   PCType            cstr;
1684   PetscErrorCode    ierr;
1685   PetscBool         iascii,isstring,isbinary,isdraw;
1686   PetscViewerFormat format;
1687 #if defined(PETSC_HAVE_SAWS)
1688   PetscBool         issaws;
1689 #endif
1690 
1691   PetscFunctionBegin;
1692   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1693   if (!viewer) {
1694     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&viewer);CHKERRQ(ierr);
1695   }
1696   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1697   PetscCheckSameComm(pc,1,viewer,2);
1698 
1699   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1700   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
1701   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1702   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1703 #if defined(PETSC_HAVE_SAWS)
1704   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);CHKERRQ(ierr);
1705 #endif
1706 
1707   if (iascii) {
1708     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1709     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)pc,viewer);CHKERRQ(ierr);
1710     if (!pc->setupcalled) {
1711       ierr = PetscViewerASCIIPrintf(viewer,"  PC has not been set up so information may be incomplete\n");CHKERRQ(ierr);
1712     }
1713     if (pc->ops->view) {
1714       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1715       ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr);
1716       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1717     }
1718     if (pc->mat) {
1719       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
1720       if (pc->pmat == pc->mat) {
1721         ierr = PetscViewerASCIIPrintf(viewer,"  linear system matrix = precond matrix:\n");CHKERRQ(ierr);
1722         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1723         ierr = MatView(pc->mat,viewer);CHKERRQ(ierr);
1724         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1725       } else {
1726         if (pc->pmat) {
1727           ierr = PetscViewerASCIIPrintf(viewer,"  linear system matrix followed by preconditioner matrix:\n");CHKERRQ(ierr);
1728         } else {
1729           ierr = PetscViewerASCIIPrintf(viewer,"  linear system matrix:\n");CHKERRQ(ierr);
1730         }
1731         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1732         ierr = MatView(pc->mat,viewer);CHKERRQ(ierr);
1733         if (pc->pmat) {ierr = MatView(pc->pmat,viewer);CHKERRQ(ierr);}
1734         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1735       }
1736       ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1737     }
1738   } else if (isstring) {
1739     ierr = PCGetType(pc,&cstr);CHKERRQ(ierr);
1740     ierr = PetscViewerStringSPrintf(viewer," %-7.7s",cstr);CHKERRQ(ierr);
1741     if (pc->ops->view) {ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr);}
1742   } else if (isbinary) {
1743     PetscInt    classid = PC_FILE_CLASSID;
1744     MPI_Comm    comm;
1745     PetscMPIInt rank;
1746     char        type[256];
1747 
1748     ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1749     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1750     if (!rank) {
1751       ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
1752       ierr = PetscStrncpy(type,((PetscObject)pc)->type_name,256);CHKERRQ(ierr);
1753       ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
1754     }
1755     if (pc->ops->view) {
1756       ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr);
1757     }
1758   } else if (isdraw) {
1759     PetscDraw draw;
1760     char      str[25];
1761     PetscReal x,y,bottom,h;
1762     PetscInt  n;
1763 
1764     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1765     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
1766     if (pc->mat) {
1767       ierr = MatGetSize(pc->mat,&n,NULL);CHKERRQ(ierr);
1768       ierr = PetscSNPrintf(str,25,"PC: %s (%D)",((PetscObject)pc)->type_name,n);CHKERRQ(ierr);
1769     } else {
1770       ierr = PetscSNPrintf(str,25,"PC: %s",((PetscObject)pc)->type_name);CHKERRQ(ierr);
1771     }
1772     ierr   = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
1773     bottom = y - h;
1774     ierr   = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr);
1775     if (pc->ops->view) {
1776       ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr);
1777     }
1778     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
1779 #if defined(PETSC_HAVE_SAWS)
1780   } else if (issaws) {
1781     PetscMPIInt rank;
1782 
1783     ierr = PetscObjectName((PetscObject)pc);CHKERRQ(ierr);
1784     ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
1785     if (!((PetscObject)pc)->amsmem && !rank) {
1786       ierr = PetscObjectViewSAWs((PetscObject)pc,viewer);CHKERRQ(ierr);
1787     }
1788     if (pc->mat) {ierr = MatView(pc->mat,viewer);CHKERRQ(ierr);}
1789     if (pc->pmat && pc->pmat != pc->mat) {ierr = MatView(pc->pmat,viewer);CHKERRQ(ierr);}
1790 #endif
1791   }
1792   PetscFunctionReturn(0);
1793 }
1794 
1795 
1796 #undef __FUNCT__
1797 #define __FUNCT__ "PCSetInitialGuessNonzero"
1798 /*@
1799    PCSetInitialGuessNonzero - Tells the iterative solver that the
1800    initial guess is nonzero; otherwise PC assumes the initial guess
1801    is to be zero (and thus zeros it out before solving).
1802 
1803    Logically Collective on PC
1804 
1805    Input Parameters:
1806 +  pc - iterative context obtained from PCCreate()
1807 -  flg - PETSC_TRUE indicates the guess is non-zero, PETSC_FALSE indicates the guess is zero
1808 
1809    Level: Developer
1810 
1811    Notes:
1812     This is a weird function. Since PC's are linear operators on the right hand side they
1813     CANNOT use an initial guess. This function is for the "pass-through" preconditioners
1814     PCKSP and PCREDUNDANT  and causes the inner KSP object to use the nonzero
1815     initial guess. Not currently working for PCREDUNDANT, that has to be rewritten to use KSP.
1816 
1817 
1818 .keywords: PC, set, initial guess, nonzero
1819 
1820 .seealso: PCGetInitialGuessNonzero(), PCSetInitialGuessKnoll(), PCGetInitialGuessKnoll()
1821 @*/
1822 PetscErrorCode  PCSetInitialGuessNonzero(PC pc,PetscBool flg)
1823 {
1824   PetscFunctionBegin;
1825   PetscValidLogicalCollectiveBool(pc,flg,2);
1826   pc->nonzero_guess = flg;
1827   PetscFunctionReturn(0);
1828 }
1829 
1830 #undef __FUNCT__
1831 #define __FUNCT__ "PCGetInitialGuessNonzero"
1832 /*@
1833    PCGetInitialGuessNonzero - Determines if the iterative solver assumes that the
1834    initial guess is nonzero; otherwise PC assumes the initial guess
1835    is to be zero (and thus zeros it out before solving).
1836 
1837    Logically Collective on PC
1838 
1839    Input Parameter:
1840 .   pc - iterative context obtained from PCCreate()
1841 
1842    Output Parameter:
1843 .  flg - PETSC_TRUE indicates the guess is non-zero, PETSC_FALSE indicates the guess is zero
1844 
1845    Level: Developer
1846 
1847 .keywords: PC, set, initial guess, nonzero
1848 
1849 .seealso: PCGetInitialGuessNonzero(), PCSetInitialGuessKnoll(), PCGetInitialGuessKnoll(), PCSetInitialGuessNonzero()
1850 @*/
1851 PetscErrorCode  PCGetInitialGuessNonzero(PC pc,PetscBool *flg)
1852 {
1853   PetscFunctionBegin;
1854   *flg = pc->nonzero_guess;
1855   PetscFunctionReturn(0);
1856 }
1857 
1858 #undef __FUNCT__
1859 #define __FUNCT__ "PCRegister"
1860 /*@C
1861   PCRegister -  Adds a method to the preconditioner package.
1862 
1863    Not collective
1864 
1865    Input Parameters:
1866 +  name_solver - name of a new user-defined solver
1867 -  routine_create - routine to create method context
1868 
1869    Notes:
1870    PCRegister() may be called multiple times to add several user-defined preconditioners.
1871 
1872    Sample usage:
1873 .vb
1874    PCRegister("my_solver", MySolverCreate);
1875 .ve
1876 
1877    Then, your solver can be chosen with the procedural interface via
1878 $     PCSetType(pc,"my_solver")
1879    or at runtime via the option
1880 $     -pc_type my_solver
1881 
1882    Level: advanced
1883 
1884 .keywords: PC, register
1885 
1886 .seealso: PCRegisterAll(), PCRegisterDestroy()
1887 @*/
1888 PetscErrorCode  PCRegister(const char sname[],PetscErrorCode (*function)(PC))
1889 {
1890   PetscErrorCode ierr;
1891 
1892   PetscFunctionBegin;
1893   ierr = PetscFunctionListAdd(&PCList,sname,function);CHKERRQ(ierr);
1894   PetscFunctionReturn(0);
1895 }
1896 
1897 #undef __FUNCT__
1898 #define __FUNCT__ "PCComputeExplicitOperator"
1899 /*@
1900     PCComputeExplicitOperator - Computes the explicit preconditioned operator.
1901 
1902     Collective on PC
1903 
1904     Input Parameter:
1905 .   pc - the preconditioner object
1906 
1907     Output Parameter:
1908 .   mat - the explict preconditioned operator
1909 
1910     Notes:
1911     This computation is done by applying the operators to columns of the
1912     identity matrix.
1913 
1914     Currently, this routine uses a dense matrix format when 1 processor
1915     is used and a sparse format otherwise.  This routine is costly in general,
1916     and is recommended for use only with relatively small systems.
1917 
1918     Level: advanced
1919 
1920 .keywords: PC, compute, explicit, operator
1921 
1922 .seealso: KSPComputeExplicitOperator()
1923 
1924 @*/
1925 PetscErrorCode  PCComputeExplicitOperator(PC pc,Mat *mat)
1926 {
1927   Vec            in,out;
1928   PetscErrorCode ierr;
1929   PetscInt       i,M,m,*rows,start,end;
1930   PetscMPIInt    size;
1931   MPI_Comm       comm;
1932   PetscScalar    *array,one = 1.0;
1933 
1934   PetscFunctionBegin;
1935   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1936   PetscValidPointer(mat,2);
1937 
1938   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1939   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1940 
1941   if (!pc->pmat) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"You must call KSPSetOperators() or PCSetOperators() before this call");
1942   ierr = MatCreateVecs(pc->pmat,&in,0);CHKERRQ(ierr);
1943   ierr = VecDuplicate(in,&out);CHKERRQ(ierr);
1944   ierr = VecGetOwnershipRange(in,&start,&end);CHKERRQ(ierr);
1945   ierr = VecGetSize(in,&M);CHKERRQ(ierr);
1946   ierr = VecGetLocalSize(in,&m);CHKERRQ(ierr);
1947   ierr = PetscMalloc1(m+1,&rows);CHKERRQ(ierr);
1948   for (i=0; i<m; i++) rows[i] = start + i;
1949 
1950   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
1951   ierr = MatSetSizes(*mat,m,m,M,M);CHKERRQ(ierr);
1952   if (size == 1) {
1953     ierr = MatSetType(*mat,MATSEQDENSE);CHKERRQ(ierr);
1954     ierr = MatSeqDenseSetPreallocation(*mat,NULL);CHKERRQ(ierr);
1955   } else {
1956     ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr);
1957     ierr = MatMPIAIJSetPreallocation(*mat,0,NULL,0,NULL);CHKERRQ(ierr);
1958   }
1959   ierr = MatSetOption(*mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1960 
1961   for (i=0; i<M; i++) {
1962 
1963     ierr = VecSet(in,0.0);CHKERRQ(ierr);
1964     ierr = VecSetValues(in,1,&i,&one,INSERT_VALUES);CHKERRQ(ierr);
1965     ierr = VecAssemblyBegin(in);CHKERRQ(ierr);
1966     ierr = VecAssemblyEnd(in);CHKERRQ(ierr);
1967 
1968     /* should fix, allowing user to choose side */
1969     ierr = PCApply(pc,in,out);CHKERRQ(ierr);
1970 
1971     ierr = VecGetArray(out,&array);CHKERRQ(ierr);
1972     ierr = MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1973     ierr = VecRestoreArray(out,&array);CHKERRQ(ierr);
1974 
1975   }
1976   ierr = PetscFree(rows);CHKERRQ(ierr);
1977   ierr = VecDestroy(&out);CHKERRQ(ierr);
1978   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1979   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1980   PetscFunctionReturn(0);
1981 }
1982 
1983 #undef __FUNCT__
1984 #define __FUNCT__ "PCSetCoordinates"
1985 /*@
1986    PCSetCoordinates - sets the coordinates of all the nodes on the local process
1987 
1988    Collective on PC
1989 
1990    Input Parameters:
1991 +  pc - the solver context
1992 .  dim - the dimension of the coordinates 1, 2, or 3
1993 -  coords - the coordinates
1994 
1995    Level: intermediate
1996 
1997    Notes: coords is an array of the 3D coordinates for the nodes on
1998    the local processor.  So if there are 108 equation on a processor
1999    for a displacement finite element discretization of elasticity (so
2000    that there are 36 = 108/3 nodes) then the array must have 108
2001    double precision values (ie, 3 * 36).  These x y z coordinates
2002    should be ordered for nodes 0 to N-1 like so: [ 0.x, 0.y, 0.z, 1.x,
2003    ... , N-1.z ].
2004 
2005 .seealso: MatSetNearNullSpace
2006 @*/
2007 PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2008 {
2009   PetscErrorCode ierr;
2010 
2011   PetscFunctionBegin;
2012   ierr = PetscTryMethod(pc,"PCSetCoordinates_C",(PC,PetscInt,PetscInt,PetscReal*),(pc,dim,nloc,coords));CHKERRQ(ierr);
2013   PetscFunctionReturn(0);
2014 }
2015