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