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