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