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