xref: /petsc/src/ksp/pc/interface/precon.c (revision 8bc8193efbc389280f83b3d41dffa9e2d23e2ace)
1 /*
2     The PC (preconditioner) interface routines, callable by users.
3 */
4 #include "src/ksp/pc/pcimpl.h"            /*I "petscksp.h" I*/
5 
6 /* Logging support */
7 PetscCookie PC_COOKIE = 0;
8 PetscEvent  PC_SetUp = 0, PC_SetUpOnBlocks = 0, PC_Apply = 0, PC_ApplyCoarse = 0, PC_ApplyMultiple = 0, PC_ApplySymmetricLeft = 0;
9 PetscEvent  PC_ApplySymmetricRight = 0, PC_ModifySubMatrices = 0;
10 
11 #undef __FUNCT__
12 #define __FUNCT__ "PCGetDefaultType_Private"
13 PetscErrorCode PCGetDefaultType_Private(PC pc,const char* type[])
14 {
15   PetscErrorCode ierr;
16   PetscMPIInt    size;
17   PetscTruth     flg1,flg2,set,flg3;
18 
19   PetscFunctionBegin;
20   ierr = MPI_Comm_size(pc->comm,&size);CHKERRQ(ierr);
21   if (pc->pmat) {
22     PetscErrorCode (*f)(Mat,PetscTruth*,MatReuse,Mat*);
23     ierr = PetscObjectQueryFunction((PetscObject)pc->pmat,"MatGetDiagonalBlock_C",(void (**)(void))&f);CHKERRQ(ierr);
24     if (size == 1) {
25       ierr = MatHasOperation(pc->pmat,MATOP_ICCFACTOR_SYMBOLIC,&flg1);CHKERRQ(ierr);
26       ierr = MatHasOperation(pc->pmat,MATOP_ILUFACTOR_SYMBOLIC,&flg2);CHKERRQ(ierr);
27       ierr = MatIsSymmetricKnown(pc->pmat,&set,&flg3);CHKERRQ(ierr);
28       if (flg1 && (!flg2 || (set && flg3))) {
29 	*type = PCICC;
30       } else if (flg2) {
31 	*type = PCILU;
32       } else if (f) { /* likely is a parallel matrix run on one processor */
33 	*type = PCBJACOBI;
34       } else {
35 	*type = PCNONE;
36       }
37     } else {
38        if (f) {
39 	*type = PCBJACOBI;
40       } else {
41 	*type = PCNONE;
42       }
43     }
44   } else {
45     if (size == 1) {
46       *type = PCILU;
47     } else {
48       *type = PCBJACOBI;
49     }
50   }
51   PetscFunctionReturn(0);
52 }
53 
54 #undef __FUNCT__
55 #define __FUNCT__ "PCDestroy"
56 /*@C
57    PCDestroy - Destroys PC context that was created with PCCreate().
58 
59    Collective on PC
60 
61    Input Parameter:
62 .  pc - the preconditioner context
63 
64    Level: developer
65 
66 .keywords: PC, destroy
67 
68 .seealso: PCCreate(), PCSetUp()
69 @*/
70 PetscErrorCode PCDestroy(PC pc)
71 {
72   PetscErrorCode ierr;
73 
74   PetscFunctionBegin;
75   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
76   if (--pc->refct > 0) PetscFunctionReturn(0);
77 
78   /* if memory was published with AMS then destroy it */
79   ierr = PetscObjectDepublish(pc);CHKERRQ(ierr);
80 
81   if (pc->ops->destroy)       {ierr =  (*pc->ops->destroy)(pc);CHKERRQ(ierr);}
82   if (pc->diagonalscaleright) {ierr = VecDestroy(pc->diagonalscaleright);CHKERRQ(ierr);}
83   if (pc->diagonalscaleleft)  {ierr = VecDestroy(pc->diagonalscaleleft);CHKERRQ(ierr);}
84 
85   PetscLogObjectDestroy(pc);
86   PetscHeaderDestroy(pc);
87   PetscFunctionReturn(0);
88 }
89 
90 #undef __FUNCT__
91 #define __FUNCT__ "PCDiagonalScale"
92 /*@C
93    PCDiagonalScale - Indicates if the preconditioner applies an additional left and right
94       scaling as needed by certain time-stepping codes.
95 
96    Collective on PC
97 
98    Input Parameter:
99 .  pc - the preconditioner context
100 
101    Output Parameter:
102 .  flag - PETSC_TRUE if it applies the scaling
103 
104    Level: developer
105 
106    Notes: If this returns PETSC_TRUE then the system solved via the Krylov method is
107 $           D M A D^{-1} y = D M b  for left preconditioning or
108 $           D A M D^{-1} z = D b for right preconditioning
109 
110 .keywords: PC
111 
112 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScaleSet()
113 @*/
114 PetscErrorCode PCDiagonalScale(PC pc,PetscTruth *flag)
115 {
116   PetscFunctionBegin;
117   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
118   PetscValidPointer(flag,2);
119   *flag = pc->diagonalscale;
120   PetscFunctionReturn(0);
121 }
122 
123 #undef __FUNCT__
124 #define __FUNCT__ "PCDiagonalScaleSet"
125 /*@
126    PCDiagonalScaleSet - Indicates the left scaling to use to apply an additional left and right
127       scaling as needed by certain time-stepping codes.
128 
129    Collective on PC
130 
131    Input Parameters:
132 +  pc - the preconditioner context
133 -  s - scaling vector
134 
135    Level: intermediate
136 
137    Notes: The system solved via the Krylov method is
138 $           D M A D^{-1} y = D M b  for left preconditioning or
139 $           D A M D^{-1} z = D b for right preconditioning
140 
141    PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
142 
143 .keywords: PC
144 
145 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScale()
146 @*/
147 PetscErrorCode PCDiagonalScaleSet(PC pc,Vec s)
148 {
149   PetscErrorCode ierr;
150 
151   PetscFunctionBegin;
152   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
153   PetscValidHeaderSpecific(s,VEC_COOKIE,2);
154   pc->diagonalscale     = PETSC_TRUE;
155   if (pc->diagonalscaleleft) {
156     ierr = VecDestroy(pc->diagonalscaleleft);CHKERRQ(ierr);
157   }
158   pc->diagonalscaleleft = s;
159   ierr                  = PetscObjectReference((PetscObject)s);CHKERRQ(ierr);
160   if (!pc->diagonalscaleright) {
161     ierr = VecDuplicate(s,&pc->diagonalscaleright);CHKERRQ(ierr);
162   }
163   ierr = VecCopy(s,pc->diagonalscaleright);CHKERRQ(ierr);
164   ierr = VecReciprocal(pc->diagonalscaleright);CHKERRQ(ierr);
165   PetscFunctionReturn(0);
166 }
167 
168 #undef __FUNCT__
169 #define __FUNCT__ "PCDiagonalScaleLeft"
170 /*@C
171    PCDiagonalScaleLeft - Indicates the left scaling to use to apply an additional left and right
172       scaling as needed by certain time-stepping codes.
173 
174    Collective on PC
175 
176    Input Parameters:
177 +  pc - the preconditioner context
178 .  in - input vector
179 +  out - scaled vector (maybe the same as in)
180 
181    Level: intermediate
182 
183    Notes: The system solved via the Krylov method is
184 $           D M A D^{-1} y = D M b  for left preconditioning or
185 $           D A M D^{-1} z = D b for right preconditioning
186 
187    PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
188 
189    If diagonal scaling is turned off and in is not out then in is copied to out
190 
191 .keywords: PC
192 
193 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
194 @*/
195 PetscErrorCode PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
196 {
197   PetscErrorCode ierr;
198 
199   PetscFunctionBegin;
200   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
201   PetscValidHeaderSpecific(in,VEC_COOKIE,2);
202   PetscValidHeaderSpecific(out,VEC_COOKIE,3);
203   if (pc->diagonalscale) {
204     ierr = VecPointwiseMult(pc->diagonalscaleleft,in,out);CHKERRQ(ierr);
205   } else if (in != out) {
206     ierr = VecCopy(in,out);CHKERRQ(ierr);
207   }
208   PetscFunctionReturn(0);
209 }
210 
211 #undef __FUNCT__
212 #define __FUNCT__ "PCDiagonalScaleRight"
213 /*@C
214    PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.
215 
216    Collective on PC
217 
218    Input Parameters:
219 +  pc - the preconditioner context
220 .  in - input vector
221 +  out - scaled vector (maybe the same as in)
222 
223    Level: intermediate
224 
225    Notes: The system solved via the Krylov method is
226 $           D M A D^{-1} y = D M b  for left preconditioning or
227 $           D A M D^{-1} z = D b for right preconditioning
228 
229    PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
230 
231    If diagonal scaling is turned off and in is not out then in is copied to out
232 
233 .keywords: PC
234 
235 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
236 @*/
237 PetscErrorCode PCDiagonalScaleRight(PC pc,Vec in,Vec out)
238 {
239   PetscErrorCode ierr;
240 
241   PetscFunctionBegin;
242   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
243   PetscValidHeaderSpecific(in,VEC_COOKIE,2);
244   PetscValidHeaderSpecific(out,VEC_COOKIE,3);
245   if (pc->diagonalscale) {
246     ierr = VecPointwiseMult(pc->diagonalscaleright,in,out);CHKERRQ(ierr);
247   } else if (in != out) {
248     ierr = VecCopy(in,out);CHKERRQ(ierr);
249   }
250   PetscFunctionReturn(0);
251 }
252 
253 #undef __FUNCT__
254 #define __FUNCT__ "PCPublish_Petsc"
255 static PetscErrorCode PCPublish_Petsc(PetscObject obj)
256 {
257   PetscFunctionBegin;
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "PCCreate"
263 /*@C
264    PCCreate - Creates a preconditioner context.
265 
266    Collective on MPI_Comm
267 
268    Input Parameter:
269 .  comm - MPI communicator
270 
271    Output Parameter:
272 .  pc - location to put the preconditioner context
273 
274    Notes:
275    The default preconditioner on one processor is PCILU with 0 fill on more
276    then one it is PCBJACOBI with ILU() on each processor.
277 
278    Level: developer
279 
280 .keywords: PC, create, context
281 
282 .seealso: PCSetUp(), PCApply(), PCDestroy()
283 @*/
284 PetscErrorCode PCCreate(MPI_Comm comm,PC *newpc)
285 {
286   PC             pc;
287   PetscErrorCode ierr;
288 
289   PetscFunctionBegin;
290   PetscValidPointer(newpc,1)
291   *newpc = 0;
292 #ifndef PETSC_USE_DYNAMIC_LIBRARIES
293   ierr = PCInitializePackage(PETSC_NULL);CHKERRQ(ierr);
294 #endif
295 
296   PetscHeaderCreate(pc,_p_PC,struct _PCOps,PC_COOKIE,-1,"PC",comm,PCDestroy,PCView);
297   PetscLogObjectCreate(pc);
298   pc->bops->publish      = PCPublish_Petsc;
299   pc->mat                = 0;
300   pc->setupcalled        = 0;
301   pc->data               = 0;
302   pc->diagonalscale      = PETSC_FALSE;
303   pc->diagonalscaleleft  = 0;
304   pc->diagonalscaleright = 0;
305 
306   pc->ops->destroy             = 0;
307   pc->ops->apply               = 0;
308   pc->ops->applytranspose      = 0;
309   pc->ops->applyBA             = 0;
310   pc->ops->applyBAtranspose    = 0;
311   pc->ops->applyrichardson     = 0;
312   pc->ops->view                = 0;
313   pc->ops->getfactoredmatrix   = 0;
314   pc->ops->applysymmetricright = 0;
315   pc->ops->applysymmetricleft  = 0;
316   pc->ops->setuponblocks       = 0;
317 
318   pc->modifysubmatrices   = 0;
319   pc->modifysubmatricesP  = 0;
320   *newpc                  = pc;
321   ierr = PetscPublishAll(pc);CHKERRQ(ierr);
322   PetscFunctionReturn(0);
323 
324 }
325 
326 /* -------------------------------------------------------------------------------*/
327 
328 #undef __FUNCT__
329 #define __FUNCT__ "PCApply"
330 /*@
331    PCApply - Applies the preconditioner to a vector.
332 
333    Collective on PC and Vec
334 
335    Input Parameters:
336 +  pc - the preconditioner context
337 -  x - input vector
338 
339    Output Parameter:
340 .  y - output vector
341 
342    Level: developer
343 
344 .keywords: PC, apply
345 
346 .seealso: PCApplyTranspose(), PCApplyBAorAB()
347 @*/
348 PetscErrorCode PCApply(PC pc,Vec x,Vec y)
349 {
350   PetscErrorCode ierr;
351 
352   PetscFunctionBegin;
353   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
354   PetscValidHeaderSpecific(x,VEC_COOKIE,2);
355   PetscValidHeaderSpecific(y,VEC_COOKIE,3);
356   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
357 
358   if (pc->setupcalled < 2) {
359     ierr = PCSetUp(pc);CHKERRQ(ierr);
360   }
361   ierr = PetscLogEventBegin(PC_Apply,pc,x,y,0);CHKERRQ(ierr);
362   ierr = (*pc->ops->apply)(pc,x,y);CHKERRQ(ierr);
363   ierr = PetscLogEventEnd(PC_Apply,pc,x,y,0);CHKERRQ(ierr);
364   PetscFunctionReturn(0);
365 }
366 
367 #undef __FUNCT__
368 #define __FUNCT__ "PCApplySymmetricLeft"
369 /*@
370    PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.
371 
372    Collective on PC and Vec
373 
374    Input Parameters:
375 +  pc - the preconditioner context
376 -  x - input vector
377 
378    Output Parameter:
379 .  y - output vector
380 
381    Notes:
382    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
383 
384    Level: developer
385 
386 .keywords: PC, apply, symmetric, left
387 
388 .seealso: PCApply(), PCApplySymmetricRight()
389 @*/
390 PetscErrorCode PCApplySymmetricLeft(PC pc,Vec x,Vec y)
391 {
392   PetscErrorCode ierr;
393 
394   PetscFunctionBegin;
395   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
396   PetscValidHeaderSpecific(x,VEC_COOKIE,2);
397   PetscValidHeaderSpecific(y,VEC_COOKIE,3);
398   if (!pc->ops->applysymmetricleft) SETERRQ(PETSC_ERR_SUP,"PC does not have left symmetric apply");
399 
400   if (pc->setupcalled < 2) {
401     ierr = PCSetUp(pc);CHKERRQ(ierr);
402   }
403 
404   ierr = PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);CHKERRQ(ierr);
405   ierr = (*pc->ops->applysymmetricleft)(pc,x,y);CHKERRQ(ierr);
406   ierr = PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);CHKERRQ(ierr);
407   PetscFunctionReturn(0);
408 }
409 
410 #undef __FUNCT__
411 #define __FUNCT__ "PCApplySymmetricRight"
412 /*@
413    PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.
414 
415    Collective on PC and Vec
416 
417    Input Parameters:
418 +  pc - the preconditioner context
419 -  x - input vector
420 
421    Output Parameter:
422 .  y - output vector
423 
424    Level: developer
425 
426    Notes:
427    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
428 
429 .keywords: PC, apply, symmetric, right
430 
431 .seealso: PCApply(), PCApplySymmetricLeft()
432 @*/
433 PetscErrorCode PCApplySymmetricRight(PC pc,Vec x,Vec y)
434 {
435   PetscErrorCode ierr;
436 
437   PetscFunctionBegin;
438   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
439   PetscValidHeaderSpecific(x,VEC_COOKIE,2);
440   PetscValidHeaderSpecific(y,VEC_COOKIE,3);
441   if (!pc->ops->applysymmetricright) SETERRQ(PETSC_ERR_SUP,"PC does not have left symmetric apply");
442 
443   if (pc->setupcalled < 2) {
444     ierr = PCSetUp(pc);CHKERRQ(ierr);
445   }
446 
447   ierr = PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);CHKERRQ(ierr);
448   ierr = (*pc->ops->applysymmetricright)(pc,x,y);CHKERRQ(ierr);
449   ierr = PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);CHKERRQ(ierr);
450   PetscFunctionReturn(0);
451 }
452 
453 #undef __FUNCT__
454 #define __FUNCT__ "PCApplyTranspose"
455 /*@
456    PCApplyTranspose - Applies the transpose of preconditioner to a vector.
457 
458    Collective on PC and Vec
459 
460    Input Parameters:
461 +  pc - the preconditioner context
462 -  x - input vector
463 
464    Output Parameter:
465 .  y - output vector
466 
467    Level: developer
468 
469 .keywords: PC, apply, transpose
470 
471 .seealso: PCApply(), PCApplyBAorAB(), PCApplyBAorABTranspose(), PCHasApplyTranspose()
472 @*/
473 PetscErrorCode PCApplyTranspose(PC pc,Vec x,Vec y)
474 {
475   PetscErrorCode ierr;
476 
477   PetscFunctionBegin;
478   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
479   PetscValidHeaderSpecific(x,VEC_COOKIE,2);
480   PetscValidHeaderSpecific(y,VEC_COOKIE,3);
481   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
482   if (!pc->ops->applytranspose) SETERRQ(PETSC_ERR_SUP," ");
483 
484   if (pc->setupcalled < 2) {
485     ierr = PCSetUp(pc);CHKERRQ(ierr);
486   }
487 
488   ierr = PetscLogEventBegin(PC_Apply,pc,x,y,0);CHKERRQ(ierr);
489   ierr = (*pc->ops->applytranspose)(pc,x,y);CHKERRQ(ierr);
490   ierr = PetscLogEventEnd(PC_Apply,pc,x,y,0);CHKERRQ(ierr);
491   PetscFunctionReturn(0);
492 }
493 
494 #undef __FUNCT__
495 #define __FUNCT__ "PCHasApplyTranspose"
496 /*@
497    PCHasApplyTranspose - Test whether the preconditioner has a transpose apply operation
498 
499    Collective on PC and Vec
500 
501    Input Parameters:
502 .  pc - the preconditioner context
503 
504    Output Parameter:
505 .  flg - PETSC_TRUE if a transpose operation is defined
506 
507    Level: developer
508 
509 .keywords: PC, apply, transpose
510 
511 .seealso: PCApplyTranspose()
512 @*/
513 PetscErrorCode PCHasApplyTranspose(PC pc,PetscTruth *flg)
514 {
515   PetscFunctionBegin;
516   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
517   PetscValidPointer(flg,2);
518   *flg = (PetscTruth) (pc->ops->applytranspose == 0);
519   PetscFunctionReturn(0);
520 }
521 
522 #undef __FUNCT__
523 #define __FUNCT__ "PCApplyBAorAB"
524 /*@
525    PCApplyBAorAB - Applies the preconditioner and operator to a vector.
526 
527    Collective on PC and Vec
528 
529    Input Parameters:
530 +  pc - the preconditioner context
531 .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
532 .  x - input vector
533 -  work - work vector
534 
535    Output Parameter:
536 .  y - output vector
537 
538    Level: developer
539 
540 .keywords: PC, apply, operator
541 
542 .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
543 @*/
544 PetscErrorCode PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
545 {
546   PetscErrorCode ierr;
547 
548   PetscFunctionBegin;
549   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
550   PetscValidHeaderSpecific(x,VEC_COOKIE,3);
551   PetscValidHeaderSpecific(y,VEC_COOKIE,4);
552   PetscValidHeaderSpecific(work,VEC_COOKIE,5);
553   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
554   if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) {
555     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric");
556   }
557   if (pc->diagonalscale && side == PC_SYMMETRIC) {
558     SETERRQ(PETSC_ERR_SUP,"Cannot include diagonal scaling with symmetric preconditioner application");
559   }
560 
561   if (pc->setupcalled < 2) {
562     ierr = PCSetUp(pc);CHKERRQ(ierr);
563   }
564 
565   if (pc->diagonalscale) {
566     if (pc->ops->applyBA) {
567       Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
568       ierr = VecDuplicate(x,&work2);CHKERRQ(ierr);
569       ierr = PCDiagonalScaleRight(pc,x,work2);CHKERRQ(ierr);
570       ierr = (*pc->ops->applyBA)(pc,side,work2,y,work);CHKERRQ(ierr);
571       ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr);
572       ierr = VecDestroy(work2);CHKERRQ(ierr);
573     } else if (side == PC_RIGHT) {
574       ierr = PCDiagonalScaleRight(pc,x,y);CHKERRQ(ierr);
575       ierr = PCApply(pc,y,work);CHKERRQ(ierr);
576       ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr);
577       ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr);
578     } else if (side == PC_LEFT) {
579       ierr = PCDiagonalScaleRight(pc,x,y);CHKERRQ(ierr);
580       ierr = MatMult(pc->mat,y,work);CHKERRQ(ierr);
581       ierr = PCApply(pc,work,y);CHKERRQ(ierr);
582       ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr);
583     } else if (side == PC_SYMMETRIC) {
584       SETERRQ(PETSC_ERR_SUP,"Cannot provide diagonal scaling with symmetric application of preconditioner");
585     }
586   } else {
587     if (pc->ops->applyBA) {
588       ierr = (*pc->ops->applyBA)(pc,side,x,y,work);CHKERRQ(ierr);
589     } else if (side == PC_RIGHT) {
590       ierr = PCApply(pc,x,work);CHKERRQ(ierr);
591       ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr);
592     } else if (side == PC_LEFT) {
593       ierr = MatMult(pc->mat,x,work);CHKERRQ(ierr);
594       ierr = PCApply(pc,work,y);CHKERRQ(ierr);
595     } else if (side == PC_SYMMETRIC) {
596       /* There's an extra copy here; maybe should provide 2 work vectors instead? */
597       ierr = PCApplySymmetricRight(pc,x,work);CHKERRQ(ierr);
598       ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr);
599       ierr = VecCopy(y,work);CHKERRQ(ierr);
600       ierr = PCApplySymmetricLeft(pc,work,y);CHKERRQ(ierr);
601     }
602   }
603   PetscFunctionReturn(0);
604 }
605 
606 #undef __FUNCT__
607 #define __FUNCT__ "PCApplyBAorABTranspose"
608 /*@
609    PCApplyBAorABTranspose - Applies the transpose of the preconditioner
610    and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
611    not tr(B*A) = tr(A)*tr(B).
612 
613    Collective on PC and Vec
614 
615    Input Parameters:
616 +  pc - the preconditioner context
617 .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
618 .  x - input vector
619 -  work - work vector
620 
621    Output Parameter:
622 .  y - output vector
623 
624    Level: developer
625 
626 .keywords: PC, apply, operator, transpose
627 
628 .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
629 @*/
630 PetscErrorCode PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
631 {
632   PetscErrorCode ierr;
633 
634   PetscFunctionBegin;
635   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
636   PetscValidHeaderSpecific(x,VEC_COOKIE,3);
637   PetscValidHeaderSpecific(y,VEC_COOKIE,4);
638   PetscValidHeaderSpecific(work,VEC_COOKIE,5);
639   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
640   if (pc->ops->applyBAtranspose) {
641     ierr = (*pc->ops->applyBAtranspose)(pc,side,x,y,work);CHKERRQ(ierr);
642     PetscFunctionReturn(0);
643   }
644   if (side != PC_LEFT && side != PC_RIGHT) {
645     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");
646   }
647 
648   if (pc->setupcalled < 2) {
649     ierr = PCSetUp(pc);CHKERRQ(ierr);
650   }
651 
652   if (side == PC_RIGHT) {
653     ierr = PCApplyTranspose(pc,x,work);CHKERRQ(ierr);
654     ierr = MatMultTranspose(pc->mat,work,y);CHKERRQ(ierr);
655   } else if (side == PC_LEFT) {
656     ierr = MatMultTranspose(pc->mat,x,work);CHKERRQ(ierr);
657     ierr = PCApplyTranspose(pc,work,y);CHKERRQ(ierr);
658   }
659   /* add support for PC_SYMMETRIC */
660   PetscFunctionReturn(0); /* actually will never get here */
661 }
662 
663 /* -------------------------------------------------------------------------------*/
664 
665 #undef __FUNCT__
666 #define __FUNCT__ "PCApplyRichardsonExists"
667 /*@
668    PCApplyRichardsonExists - Determines whether a particular preconditioner has a
669    built-in fast application of Richardson's method.
670 
671    Not Collective
672 
673    Input Parameter:
674 .  pc - the preconditioner
675 
676    Output Parameter:
677 .  exists - PETSC_TRUE or PETSC_FALSE
678 
679    Level: developer
680 
681 .keywords: PC, apply, Richardson, exists
682 
683 .seealso: PCApplyRichardson()
684 @*/
685 PetscErrorCode PCApplyRichardsonExists(PC pc,PetscTruth *exists)
686 {
687   PetscFunctionBegin;
688   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
689   PetscValidIntPointer(exists,2);
690   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
691   else                    *exists = PETSC_FALSE;
692   PetscFunctionReturn(0);
693 }
694 
695 #undef __FUNCT__
696 #define __FUNCT__ "PCApplyRichardson"
697 /*@
698    PCApplyRichardson - Applies several steps of Richardson iteration with
699    the particular preconditioner. This routine is usually used by the
700    Krylov solvers and not the application code directly.
701 
702    Collective on PC
703 
704    Input Parameters:
705 +  pc  - the preconditioner context
706 .  x   - the initial guess
707 .  w   - one work vector
708 .  rtol - relative decrease in residual norm convergence criteria
709 .  abstol - absolute residual norm convergence criteria
710 .  dtol - divergence residual norm increase criteria
711 -  its - the number of iterations to apply.
712 
713    Output Parameter:
714 .  y - the solution
715 
716    Notes:
717    Most preconditioners do not support this function. Use the command
718    PCApplyRichardsonExists() to determine if one does.
719 
720    Except for the multigrid PC this routine ignores the convergence tolerances
721    and always runs for the number of iterations
722 
723    Level: developer
724 
725 .keywords: PC, apply, Richardson
726 
727 .seealso: PCApplyRichardsonExists()
728 @*/
729 PetscErrorCode PCApplyRichardson(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its)
730 {
731   PetscErrorCode ierr;
732 
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
735   PetscValidHeaderSpecific(x,VEC_COOKIE,2);
736   PetscValidHeaderSpecific(y,VEC_COOKIE,3);
737   PetscValidHeaderSpecific(w,VEC_COOKIE,4);
738   if (!pc->ops->applyrichardson) SETERRQ(PETSC_ERR_SUP," ");
739 
740   if (pc->setupcalled < 2) {
741     ierr = PCSetUp(pc);CHKERRQ(ierr);
742   }
743 
744   ierr = (*pc->ops->applyrichardson)(pc,x,y,w,rtol,abstol,dtol,its);CHKERRQ(ierr);
745   PetscFunctionReturn(0);
746 }
747 
748 /*
749       a setupcall of 0 indicates never setup,
750                      1 needs to be resetup,
751                      2 does not need any changes.
752 */
753 #undef __FUNCT__
754 #define __FUNCT__ "PCSetUp"
755 /*@
756    PCSetUp - Prepares for the use of a preconditioner.
757 
758    Collective on PC
759 
760    Input Parameter:
761 .  pc - the preconditioner context
762 
763    Level: developer
764 
765 .keywords: PC, setup
766 
767 .seealso: PCCreate(), PCApply(), PCDestroy()
768 @*/
769 PetscErrorCode PCSetUp(PC pc)
770 {
771   PetscErrorCode ierr;
772   const char     *def;
773 
774   PetscFunctionBegin;
775   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
776 
777   if (pc->setupcalled > 1) {
778     PetscLogInfo(pc,"PCSetUp:Setting PC with identical preconditioner\n");
779     PetscFunctionReturn(0);
780   } else if (!pc->setupcalled) {
781     PetscLogInfo(pc,"PCSetUp:Setting up new PC\n");
782   } else if (pc->flag == SAME_NONZERO_PATTERN) {
783     PetscLogInfo(pc,"PCSetUp:Setting up PC with same nonzero pattern\n");
784   } else {
785     PetscLogInfo(pc,"PCSetUp:Setting up PC with different nonzero pattern\n");
786   }
787 
788   ierr = PetscLogEventBegin(PC_SetUp,pc,0,0,0);CHKERRQ(ierr);
789   if (!pc->mat) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");}
790 
791   if (!pc->type_name) {
792     ierr = PCGetDefaultType_Private(pc,&def);CHKERRQ(ierr);
793     ierr = PCSetType(pc,def);CHKERRQ(ierr);
794   }
795 
796   if (pc->ops->setup) {
797     ierr = (*pc->ops->setup)(pc);CHKERRQ(ierr);
798   }
799   pc->setupcalled = 2;
800   ierr = PetscLogEventEnd(PC_SetUp,pc,0,0,0);CHKERRQ(ierr);
801   PetscFunctionReturn(0);
802 }
803 
804 #undef __FUNCT__
805 #define __FUNCT__ "PCSetUpOnBlocks"
806 /*@
807    PCSetUpOnBlocks - Sets up the preconditioner for each block in
808    the block Jacobi, block Gauss-Seidel, and overlapping Schwarz
809    methods.
810 
811    Collective on PC
812 
813    Input Parameters:
814 .  pc - the preconditioner context
815 
816    Level: developer
817 
818 .keywords: PC, setup, blocks
819 
820 .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
821 @*/
822 PetscErrorCode PCSetUpOnBlocks(PC pc)
823 {
824   PetscErrorCode ierr;
825 
826   PetscFunctionBegin;
827   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
828   if (!pc->ops->setuponblocks) PetscFunctionReturn(0);
829   ierr = PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);CHKERRQ(ierr);
830   ierr = (*pc->ops->setuponblocks)(pc);CHKERRQ(ierr);
831   ierr = PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);CHKERRQ(ierr);
832   PetscFunctionReturn(0);
833 }
834 
835 #undef __FUNCT__
836 #define __FUNCT__ "PCSetModifySubMatrices"
837 /*@C
838    PCSetModifySubMatrices - Sets a user-defined routine for modifying the
839    submatrices that arise within certain subdomain-based preconditioners.
840    The basic submatrices are extracted from the preconditioner matrix as
841    usual; the user can then alter these (for example, to set different boundary
842    conditions for each submatrix) before they are used for the local solves.
843 
844    Collective on PC
845 
846    Input Parameters:
847 +  pc - the preconditioner context
848 .  func - routine for modifying the submatrices
849 -  ctx - optional user-defined context (may be null)
850 
851    Calling sequence of func:
852 $     func (PC pc,PetscInt nsub,IS *row,IS *col,Mat *submat,void *ctx);
853 
854 .  row - an array of index sets that contain the global row numbers
855          that comprise each local submatrix
856 .  col - an array of index sets that contain the global column numbers
857          that comprise each local submatrix
858 .  submat - array of local submatrices
859 -  ctx - optional user-defined context for private data for the
860          user-defined func routine (may be null)
861 
862    Notes:
863    PCSetModifySubMatrices() MUST be called before KSPSetUp() and
864    KSPSolve().
865 
866    A routine set by PCSetModifySubMatrices() is currently called within
867    the block Jacobi (PCBJACOBI) and additive Schwarz (PCASM)
868    preconditioners.  All other preconditioners ignore this routine.
869 
870    Level: advanced
871 
872 .keywords: PC, set, modify, submatrices
873 
874 .seealso: PCModifySubMatrices()
875 @*/
876 PetscErrorCode PCSetModifySubMatrices(PC pc,PetscErrorCode (*func)(PC,PetscInt,const IS[],const IS[],Mat[],void*),void *ctx)
877 {
878   PetscFunctionBegin;
879   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
880   pc->modifysubmatrices  = func;
881   pc->modifysubmatricesP = ctx;
882   PetscFunctionReturn(0);
883 }
884 
885 #undef __FUNCT__
886 #define __FUNCT__ "PCModifySubMatrices"
887 /*@C
888    PCModifySubMatrices - Calls an optional user-defined routine within
889    certain preconditioners if one has been set with PCSetModifySubMarices().
890 
891    Collective on PC
892 
893    Input Parameters:
894 +  pc - the preconditioner context
895 .  nsub - the number of local submatrices
896 .  row - an array of index sets that contain the global row numbers
897          that comprise each local submatrix
898 .  col - an array of index sets that contain the global column numbers
899          that comprise each local submatrix
900 .  submat - array of local submatrices
901 -  ctx - optional user-defined context for private data for the
902          user-defined routine (may be null)
903 
904    Output Parameter:
905 .  submat - array of local submatrices (the entries of which may
906             have been modified)
907 
908    Notes:
909    The user should NOT generally call this routine, as it will
910    automatically be called within certain preconditioners (currently
911    block Jacobi, additive Schwarz) if set.
912 
913    The basic submatrices are extracted from the preconditioner matrix
914    as usual; the user can then alter these (for example, to set different
915    boundary conditions for each submatrix) before they are used for the
916    local solves.
917 
918    Level: developer
919 
920 .keywords: PC, modify, submatrices
921 
922 .seealso: PCSetModifySubMatrices()
923 @*/
924 PetscErrorCode PCModifySubMatrices(PC pc,PetscInt nsub,const IS row[],const IS col[],Mat submat[],void *ctx)
925 {
926   PetscErrorCode ierr;
927 
928   PetscFunctionBegin;
929   if (!pc->modifysubmatrices) PetscFunctionReturn(0);
930   ierr = PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);CHKERRQ(ierr);
931   ierr = (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);CHKERRQ(ierr);
932   ierr = PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);CHKERRQ(ierr);
933   PetscFunctionReturn(0);
934 }
935 
936 #undef __FUNCT__
937 #define __FUNCT__ "PCSetOperators"
938 /*@
939    PCSetOperators - Sets the matrix associated with the linear system and
940    a (possibly) different one associated with the preconditioner.
941 
942    Collective on PC and Mat
943 
944    Input Parameters:
945 +  pc - the preconditioner context
946 .  Amat - the matrix associated with the linear system
947 .  Pmat - the matrix to be used in constructing the preconditioner, usually
948           the same as Amat.
949 -  flag - flag indicating information about the preconditioner matrix structure
950    during successive linear solves.  This flag is ignored the first time a
951    linear system is solved, and thus is irrelevant when solving just one linear
952    system.
953 
954    Notes:
955    The flag can be used to eliminate unnecessary work in the preconditioner
956    during the repeated solution of linear systems of the same size.  The
957    available options are
958 +    SAME_PRECONDITIONER -
959        Pmat is identical during successive linear solves.
960        This option is intended for folks who are using
961        different Amat and Pmat matrices and wish to reuse the
962        same preconditioner matrix.  For example, this option
963        saves work by not recomputing incomplete factorization
964        for ILU/ICC preconditioners.
965 .     SAME_NONZERO_PATTERN -
966        Pmat has the same nonzero structure during
967        successive linear solves.
968 -     DIFFERENT_NONZERO_PATTERN -
969        Pmat does not have the same nonzero structure.
970 
971    Caution:
972    If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion
973    and does not check the structure of the matrix.  If you erroneously
974    claim that the structure is the same when it actually is not, the new
975    preconditioner will not function correctly.  Thus, use this optimization
976    feature carefully!
977 
978    If in doubt about whether your preconditioner matrix has changed
979    structure or not, use the flag DIFFERENT_NONZERO_PATTERN.
980 
981    More Notes about Repeated Solution of Linear Systems:
982    PETSc does NOT reset the matrix entries of either Amat or Pmat
983    to zero after a linear solve; the user is completely responsible for
984    matrix assembly.  See the routine MatZeroEntries() if desiring to
985    zero all elements of a matrix.
986 
987    Level: intermediate
988 
989 .keywords: PC, set, operators, matrix, linear system
990 
991 .seealso: PCGetOperators(), MatZeroEntries()
992  @*/
993 PetscErrorCode PCSetOperators(PC pc,Mat Amat,Mat Pmat,MatStructure flag)
994 {
995   PetscErrorCode ierr;
996   PetscTruth     isbjacobi,isrowbs;
997 
998   PetscFunctionBegin;
999   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1000   if (Amat) PetscValidHeaderSpecific(Amat,MAT_COOKIE,2);
1001   if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_COOKIE,3);
1002 
1003   /*
1004       BlockSolve95 cannot use default BJacobi preconditioning
1005   */
1006   if (Amat) {
1007     ierr = PetscTypeCompare((PetscObject)Amat,MATMPIROWBS,&isrowbs);CHKERRQ(ierr);
1008     if (isrowbs) {
1009       ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&isbjacobi);CHKERRQ(ierr);
1010       if (isbjacobi) {
1011         ierr = PCSetType(pc,PCILU);CHKERRQ(ierr);
1012         PetscLogInfo(pc,"PCSetOperators:Switching default PC to PCILU since BS95 doesn't support PCBJACOBI\n");
1013       }
1014     }
1015   }
1016 
1017   pc->mat  = Amat;
1018   pc->pmat = Pmat;
1019   if (pc->setupcalled == 2 && flag != SAME_PRECONDITIONER) {
1020     pc->setupcalled = 1;
1021   }
1022   pc->flag = flag;
1023   PetscFunctionReturn(0);
1024 }
1025 
1026 #undef __FUNCT__
1027 #define __FUNCT__ "PCGetOperators"
1028 /*@C
1029    PCGetOperators - Gets the matrix associated with the linear system and
1030    possibly a different one associated with the preconditioner.
1031 
1032    Not collective, though parallel Mats are returned if the PC is parallel
1033 
1034    Input Parameter:
1035 .  pc - the preconditioner context
1036 
1037    Output Parameters:
1038 +  mat - the matrix associated with the linear system
1039 .  pmat - matrix associated with the preconditioner, usually the same
1040           as mat.
1041 -  flag - flag indicating information about the preconditioner
1042           matrix structure.  See PCSetOperators() for details.
1043 
1044    Level: intermediate
1045 
1046 .keywords: PC, get, operators, matrix, linear system
1047 
1048 .seealso: PCSetOperators()
1049 @*/
1050 PetscErrorCode PCGetOperators(PC pc,Mat *mat,Mat *pmat,MatStructure *flag)
1051 {
1052   PetscFunctionBegin;
1053   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1054   if (mat)  *mat  = pc->mat;
1055   if (pmat) *pmat = pc->pmat;
1056   if (flag) *flag = pc->flag;
1057   PetscFunctionReturn(0);
1058 }
1059 
1060 #undef __FUNCT__
1061 #define __FUNCT__ "PCGetFactoredMatrix"
1062 /*@C
1063    PCGetFactoredMatrix - Gets the factored matrix from the
1064    preconditioner context.  This routine is valid only for the LU,
1065    incomplete LU, Cholesky, and incomplete Cholesky methods.
1066 
1067    Not Collective on PC though Mat is parallel if PC is parallel
1068 
1069    Input Parameters:
1070 .  pc - the preconditioner context
1071 
1072    Output parameters:
1073 .  mat - the factored matrix
1074 
1075    Level: advanced
1076 
1077    Notes: Does not increase the reference count for the matrix so DO NOT destroy it
1078 
1079 .keywords: PC, get, factored, matrix
1080 @*/
1081 PetscErrorCode PCGetFactoredMatrix(PC pc,Mat *mat)
1082 {
1083   PetscErrorCode ierr;
1084 
1085   PetscFunctionBegin;
1086   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1087   PetscValidPointer(mat,2);
1088   if (pc->ops->getfactoredmatrix) {
1089     ierr = (*pc->ops->getfactoredmatrix)(pc,mat);CHKERRQ(ierr);
1090   }
1091   PetscFunctionReturn(0);
1092 }
1093 
1094 #undef __FUNCT__
1095 #define __FUNCT__ "PCSetOptionsPrefix"
1096 /*@C
1097    PCSetOptionsPrefix - Sets the prefix used for searching for all
1098    PC options in the database.
1099 
1100    Collective on PC
1101 
1102    Input Parameters:
1103 +  pc - the preconditioner context
1104 -  prefix - the prefix string to prepend to all PC option requests
1105 
1106    Notes:
1107    A hyphen (-) must NOT be given at the beginning of the prefix name.
1108    The first character of all runtime options is AUTOMATICALLY the
1109    hyphen.
1110 
1111    Level: advanced
1112 
1113 .keywords: PC, set, options, prefix, database
1114 
1115 .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1116 @*/
1117 PetscErrorCode PCSetOptionsPrefix(PC pc,const char prefix[])
1118 {
1119   PetscErrorCode ierr;
1120 
1121   PetscFunctionBegin;
1122   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1123   ierr = PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr);
1124   PetscFunctionReturn(0);
1125 }
1126 
1127 #undef __FUNCT__
1128 #define __FUNCT__ "PCAppendOptionsPrefix"
1129 /*@C
1130    PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1131    PC options in the database.
1132 
1133    Collective on PC
1134 
1135    Input Parameters:
1136 +  pc - the preconditioner context
1137 -  prefix - the prefix string to prepend to all PC option requests
1138 
1139    Notes:
1140    A hyphen (-) must NOT be given at the beginning of the prefix name.
1141    The first character of all runtime options is AUTOMATICALLY the
1142    hyphen.
1143 
1144    Level: advanced
1145 
1146 .keywords: PC, append, options, prefix, database
1147 
1148 .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1149 @*/
1150 PetscErrorCode PCAppendOptionsPrefix(PC pc,const char prefix[])
1151 {
1152   PetscErrorCode ierr;
1153 
1154   PetscFunctionBegin;
1155   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1156   ierr = PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr);
1157   PetscFunctionReturn(0);
1158 }
1159 
1160 #undef __FUNCT__
1161 #define __FUNCT__ "PCGetOptionsPrefix"
1162 /*@C
1163    PCGetOptionsPrefix - Gets the prefix used for searching for all
1164    PC options in the database.
1165 
1166    Not Collective
1167 
1168    Input Parameters:
1169 .  pc - the preconditioner context
1170 
1171    Output Parameters:
1172 .  prefix - pointer to the prefix string used, is returned
1173 
1174    Notes: On the fortran side, the user should pass in a string 'prifix' of
1175    sufficient length to hold the prefix.
1176 
1177    Level: advanced
1178 
1179 .keywords: PC, get, options, prefix, database
1180 
1181 .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1182 @*/
1183 PetscErrorCode PCGetOptionsPrefix(PC pc,char *prefix[])
1184 {
1185   PetscErrorCode ierr;
1186 
1187   PetscFunctionBegin;
1188   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1189   PetscValidPointer(prefix,2);
1190   ierr = PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr);
1191   PetscFunctionReturn(0);
1192 }
1193 
1194 #undef __FUNCT__
1195 #define __FUNCT__ "PCPreSolve"
1196 /*@
1197    PCPreSolve - Optional pre-solve phase, intended for any
1198    preconditioner-specific actions that must be performed before
1199    the iterative solve itself.
1200 
1201    Collective on PC
1202 
1203    Input Parameters:
1204 +  pc - the preconditioner context
1205 -  ksp - the Krylov subspace context
1206 
1207    Level: developer
1208 
1209    Sample of Usage:
1210 .vb
1211     PCPreSolve(pc,ksp);
1212     KSPSolve(ksp,b,x);
1213     PCPostSolve(pc,ksp);
1214 .ve
1215 
1216    Notes:
1217    The pre-solve phase is distinct from the PCSetUp() phase.
1218 
1219    KSPSolve() calls this directly, so is rarely called by the user.
1220 
1221 .keywords: PC, pre-solve
1222 
1223 .seealso: PCPostSolve()
1224 @*/
1225 PetscErrorCode PCPreSolve(PC pc,KSP ksp)
1226 {
1227   PetscErrorCode ierr;
1228   Vec            x,rhs;
1229   Mat            A,B;
1230 
1231   PetscFunctionBegin;
1232   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1233   PetscValidHeaderSpecific(ksp,KSP_COOKIE,2);
1234   ierr = KSPGetSolution(ksp,&x);CHKERRQ(ierr);
1235   ierr = KSPGetRhs(ksp,&rhs);CHKERRQ(ierr);
1236   /*
1237       Scale the system and have the matrices use the scaled form
1238     only if the two matrices are actually the same (and hence
1239     have the same scaling
1240   */
1241   ierr = PCGetOperators(pc,&A,&B,PETSC_NULL);CHKERRQ(ierr);
1242   if (A == B) {
1243     ierr = MatScaleSystem(pc->mat,x,rhs);CHKERRQ(ierr);
1244     ierr = MatUseScaledForm(pc->mat,PETSC_TRUE);CHKERRQ(ierr);
1245   }
1246 
1247   if (pc->ops->presolve) {
1248     ierr = (*pc->ops->presolve)(pc,ksp,x,rhs);CHKERRQ(ierr);
1249   }
1250   PetscFunctionReturn(0);
1251 }
1252 
1253 #undef __FUNCT__
1254 #define __FUNCT__ "PCPostSolve"
1255 /*@
1256    PCPostSolve - Optional post-solve phase, intended for any
1257    preconditioner-specific actions that must be performed after
1258    the iterative solve itself.
1259 
1260    Collective on PC
1261 
1262    Input Parameters:
1263 +  pc - the preconditioner context
1264 -  ksp - the Krylov subspace context
1265 
1266    Sample of Usage:
1267 .vb
1268     PCPreSolve(pc,ksp);
1269     KSPSolve(ksp,b,x);
1270     PCPostSolve(pc,ksp);
1271 .ve
1272 
1273    Note:
1274    KSPSolve() calls this routine directly, so it is rarely called by the user.
1275 
1276    Level: developer
1277 
1278 .keywords: PC, post-solve
1279 
1280 .seealso: PCPreSolve(), KSPSolve()
1281 @*/
1282 PetscErrorCode PCPostSolve(PC pc,KSP ksp)
1283 {
1284   PetscErrorCode ierr;
1285   Vec            x,rhs;
1286   Mat            A,B;
1287 
1288   PetscFunctionBegin;
1289   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1290   PetscValidHeaderSpecific(ksp,KSP_COOKIE,2);
1291   ierr = KSPGetSolution(ksp,&x);CHKERRQ(ierr);
1292   ierr = KSPGetRhs(ksp,&rhs);CHKERRQ(ierr);
1293   if (pc->ops->postsolve) {
1294     ierr =  (*pc->ops->postsolve)(pc,ksp,x,rhs);CHKERRQ(ierr);
1295   }
1296 
1297   /*
1298       Scale the system and have the matrices use the scaled form
1299     only if the two matrices are actually the same (and hence
1300     have the same scaling
1301   */
1302   ierr = PCGetOperators(pc,&A,&B,PETSC_NULL);CHKERRQ(ierr);
1303   if (A == B) {
1304     ierr = MatUnScaleSystem(pc->mat,x,rhs);CHKERRQ(ierr);
1305     ierr = MatUseScaledForm(pc->mat,PETSC_FALSE);CHKERRQ(ierr);
1306   }
1307   PetscFunctionReturn(0);
1308 }
1309 
1310 #undef __FUNCT__
1311 #define __FUNCT__ "PCView"
1312 /*@C
1313    PCView - Prints the PC data structure.
1314 
1315    Collective on PC
1316 
1317    Input Parameters:
1318 +  PC - the PC context
1319 -  viewer - optional visualization context
1320 
1321    Note:
1322    The available visualization contexts include
1323 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
1324 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1325          output where only the first processor opens
1326          the file.  All other processors send their
1327          data to the first processor to print.
1328 
1329    The user can open an alternative visualization contexts with
1330    PetscViewerASCIIOpen() (output to a specified file).
1331 
1332    Level: developer
1333 
1334 .keywords: PC, view
1335 
1336 .seealso: KSPView(), PetscViewerASCIIOpen()
1337 @*/
1338 PetscErrorCode PCView(PC pc,PetscViewer viewer)
1339 {
1340   PCType            cstr;
1341   PetscErrorCode    ierr;
1342   PetscTruth        mat_exists,iascii,isstring;
1343   PetscViewerFormat format;
1344 
1345   PetscFunctionBegin;
1346   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1347   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pc->comm);
1348   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2);
1349   PetscCheckSameComm(pc,1,viewer,2);
1350 
1351   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
1352   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr);
1353   if (iascii) {
1354     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1355     if (pc->prefix) {
1356       ierr = PetscViewerASCIIPrintf(viewer,"PC Object:(%s)\n",pc->prefix);CHKERRQ(ierr);
1357     } else {
1358       ierr = PetscViewerASCIIPrintf(viewer,"PC Object:\n");CHKERRQ(ierr);
1359     }
1360     ierr = PCGetType(pc,&cstr);CHKERRQ(ierr);
1361     if (cstr) {
1362       ierr = PetscViewerASCIIPrintf(viewer,"  type: %s\n",cstr);CHKERRQ(ierr);
1363     } else {
1364       ierr = PetscViewerASCIIPrintf(viewer,"  type: not yet set\n");CHKERRQ(ierr);
1365     }
1366     if (pc->ops->view) {
1367       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1368       ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr);
1369       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1370     }
1371     ierr = PetscObjectExists((PetscObject)pc->mat,&mat_exists);CHKERRQ(ierr);
1372     if (mat_exists) {
1373       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
1374       if (pc->pmat == pc->mat) {
1375         ierr = PetscViewerASCIIPrintf(viewer,"  linear system matrix = precond matrix:\n");CHKERRQ(ierr);
1376         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1377         ierr = MatView(pc->mat,viewer);CHKERRQ(ierr);
1378         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1379       } else {
1380         ierr = PetscObjectExists((PetscObject)pc->pmat,&mat_exists);CHKERRQ(ierr);
1381         if (mat_exists) {
1382           ierr = PetscViewerASCIIPrintf(viewer,"  linear system matrix followed by preconditioner matrix:\n");CHKERRQ(ierr);
1383         } else {
1384           ierr = PetscViewerASCIIPrintf(viewer,"  linear system matrix:\n");CHKERRQ(ierr);
1385         }
1386         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1387         ierr = MatView(pc->mat,viewer);CHKERRQ(ierr);
1388         if (mat_exists) {ierr = MatView(pc->pmat,viewer);CHKERRQ(ierr);}
1389         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1390       }
1391       ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1392     }
1393   } else if (isstring) {
1394     ierr = PCGetType(pc,&cstr);CHKERRQ(ierr);
1395     ierr = PetscViewerStringSPrintf(viewer," %-7.7s",cstr);CHKERRQ(ierr);
1396     if (pc->ops->view) {ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr);}
1397   } else {
1398     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by PC",((PetscObject)viewer)->type_name);
1399   }
1400   PetscFunctionReturn(0);
1401 }
1402 
1403 #undef __FUNCT__
1404 #define __FUNCT__ "PCRegister"
1405 /*@C
1406   PCRegister - See PCRegisterDynamic()
1407 
1408   Level: advanced
1409 @*/
1410 PetscErrorCode PCRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PC))
1411 {
1412   PetscErrorCode ierr;
1413   char           fullname[PETSC_MAX_PATH_LEN];
1414 
1415   PetscFunctionBegin;
1416 
1417   ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr);
1418   ierr = PetscFListAdd(&PCList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr);
1419   PetscFunctionReturn(0);
1420 }
1421 
1422 #undef __FUNCT__
1423 #define __FUNCT__ "PCComputeExplicitOperator"
1424 /*@
1425     PCComputeExplicitOperator - Computes the explicit preconditioned operator.
1426 
1427     Collective on PC
1428 
1429     Input Parameter:
1430 .   pc - the preconditioner object
1431 
1432     Output Parameter:
1433 .   mat - the explict preconditioned operator
1434 
1435     Notes:
1436     This computation is done by applying the operators to columns of the
1437     identity matrix.
1438 
1439     Currently, this routine uses a dense matrix format when 1 processor
1440     is used and a sparse format otherwise.  This routine is costly in general,
1441     and is recommended for use only with relatively small systems.
1442 
1443     Level: advanced
1444 
1445 .keywords: PC, compute, explicit, operator
1446 
1447 @*/
1448 PetscErrorCode PCComputeExplicitOperator(PC pc,Mat *mat)
1449 {
1450   Vec            in,out;
1451   PetscErrorCode ierr;
1452   PetscInt       i,M,m,*rows,start,end;
1453   PetscMPIInt    size;
1454   MPI_Comm       comm;
1455   PetscScalar    *array,zero = 0.0,one = 1.0;
1456 
1457   PetscFunctionBegin;
1458   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1459   PetscValidPointer(mat,2);
1460 
1461   comm = pc->comm;
1462   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1463 
1464   if (!pc->pmat) SETERRQ(PETSC_ERR_ORDER,"You must call KSPSetOperators() or PCSetOperators() before this call");
1465   ierr = MatGetVecs(pc->pmat,&in,0);CHKERRQ(ierr);
1466   ierr = VecDuplicate(in,&out);CHKERRQ(ierr);
1467   ierr = VecGetOwnershipRange(in,&start,&end);CHKERRQ(ierr);
1468   ierr = VecGetSize(in,&M);CHKERRQ(ierr);
1469   ierr = VecGetLocalSize(in,&m);CHKERRQ(ierr);
1470   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&rows);CHKERRQ(ierr);
1471   for (i=0; i<m; i++) {rows[i] = start + i;}
1472 
1473   ierr = MatCreate(comm,m,m,M,M,mat);CHKERRQ(ierr);
1474   if (size == 1) {
1475     ierr = MatSetType(*mat,MATSEQDENSE);CHKERRQ(ierr);
1476     ierr = MatSeqDenseSetPreallocation(*mat,PETSC_NULL);CHKERRQ(ierr);
1477   } else {
1478     ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr);
1479     ierr = MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
1480   }
1481 
1482   for (i=0; i<M; i++) {
1483 
1484     ierr = VecSet(&zero,in);CHKERRQ(ierr);
1485     ierr = VecSetValues(in,1,&i,&one,INSERT_VALUES);CHKERRQ(ierr);
1486     ierr = VecAssemblyBegin(in);CHKERRQ(ierr);
1487     ierr = VecAssemblyEnd(in);CHKERRQ(ierr);
1488 
1489     /* should fix, allowing user to choose side */
1490     ierr = PCApply(pc,in,out);CHKERRQ(ierr);
1491 
1492     ierr = VecGetArray(out,&array);CHKERRQ(ierr);
1493     ierr = MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1494     ierr = VecRestoreArray(out,&array);CHKERRQ(ierr);
1495 
1496   }
1497   ierr = PetscFree(rows);CHKERRQ(ierr);
1498   ierr = VecDestroy(out);CHKERRQ(ierr);
1499   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1500   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1501   PetscFunctionReturn(0);
1502 }
1503 
1504