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