Actual source code: precon.c
1: /*$Id: precon.c,v 1.216 2001/08/21 21:03:13 bsmith Exp $*/
2: /*
3: The PC (preconditioner) interface routines, callable by users.
4: */
5: #include src/ksp/pc/pcimpl.h
7: /* Logging support */
8: int PC_COOKIE = 0;
9: int PC_SetUp = 0, PC_SetUpOnBlocks = 0, PC_Apply = 0, PC_ApplyCoarse = 0, PC_ApplyMultiple = 0, PC_ApplySymmetricLeft = 0;
10: int PC_ApplySymmetricRight = 0, PC_ModifySubMatrices = 0;
14: int PCGetDefaultType_Private(PC pc,const char* type[])
15: {
16: int ierr,size;
17: PetscTruth flg1,flg2;
20: MPI_Comm_size(pc->comm,&size);
21: if (pc->pmat) {
22: int (*f)(Mat,PetscTruth*,MatReuse,Mat*);
23: PetscObjectQueryFunction((PetscObject)pc->pmat,"MatGetDiagonalBlock_C",(void (**)(void))&f);
24: if (size == 1) {
25: MatHasOperation(pc->pmat,MATOP_ICCFACTOR_SYMBOLIC,&flg1);
26: MatHasOperation(pc->pmat,MATOP_ILUFACTOR_SYMBOLIC,&flg2);
27: if (flg1 && !flg2) { /* for sbaij mat */
28: *type = PCICC;
29: } else if (flg2) {
30: *type = PCILU;
31: } else if (f) { /* likely is a parallel matrix run on one processor */
32: *type = PCBJACOBI;
33: } else {
34: *type = PCNONE;
35: }
36: } else {
37: if (f) {
38: *type = PCBJACOBI;
39: } else {
40: *type = PCNONE;
41: }
42: }
43: } else {
44: if (size == 1) {
45: *type = PCILU;
46: } else {
47: *type = PCBJACOBI;
48: }
49: }
50: return(0);
51: }
55: /*@C
56: PCNullSpaceAttach - attaches a null space to a preconditioner object.
57: This null space will be removed from the resulting vector whenever
58: the preconditioner is applied.
60: Collective on PC
62: Input Parameters:
63: + pc - the preconditioner context
64: - nullsp - the null space object
66: Level: developer
68: Notes:
69: Overwrites any previous null space that may have been attached
71: Users manual sections:
72: . Section 4.15 Solving Singular Systems
74: .keywords: PC, destroy, null space
76: .seealso: PCCreate(), PCSetUp(), MatNullSpaceCreate(), MatNullSpace
78: @*/
79: int PCNullSpaceAttach(PC pc,MatNullSpace nullsp)
80: {
87: if (pc->nullsp) {
88: MatNullSpaceDestroy(pc->nullsp);
89: }
90: pc->nullsp = nullsp;
91: PetscObjectReference((PetscObject)nullsp);
92: return(0);
93: }
97: /*@C
98: PCDestroy - Destroys PC context that was created with PCCreate().
100: Collective on PC
102: Input Parameter:
103: . pc - the preconditioner context
105: Level: developer
107: .keywords: PC, destroy
109: .seealso: PCCreate(), PCSetUp()
110: @*/
111: int PCDestroy(PC pc)
112: {
117: if (--pc->refct > 0) return(0);
119: /* if memory was published with AMS then destroy it */
120: PetscObjectDepublish(pc);
122: if (pc->ops->destroy) { (*pc->ops->destroy)(pc);}
123: if (pc->nullsp) {MatNullSpaceDestroy(pc->nullsp);}
124: if (pc->diagonalscaleright) {VecDestroy(pc->diagonalscaleright);}
125: if (pc->diagonalscaleleft) {VecDestroy(pc->diagonalscaleleft);}
127: PetscLogObjectDestroy(pc);
128: PetscHeaderDestroy(pc);
129: return(0);
130: }
134: /*@C
135: PCDiagonalScale - Indicates if the preconditioner applies an additional left and right
136: scaling as needed by certain time-stepping codes.
138: Collective on PC
140: Input Parameter:
141: . pc - the preconditioner context
143: Output Parameter:
144: . flag - PETSC_TRUE if it applies the scaling
146: Level: developer
148: Notes: If this returns PETSC_TRUE then the system solved via the Krylov method is
149: $ D M A D^{-1} y = D M b for left preconditioning or
150: $ D A M D^{-1} z = D b for right preconditioning
152: .keywords: PC
154: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScaleSet()
155: @*/
156: int PCDiagonalScale(PC pc,PetscTruth *flag)
157: {
161: *flag = pc->diagonalscale;
162: return(0);
163: }
167: /*@
168: PCDiagonalScaleSet - Indicates the left scaling to use to apply an additional left and right
169: scaling as needed by certain time-stepping codes.
171: Collective on PC
173: Input Parameters:
174: + pc - the preconditioner context
175: - s - scaling vector
177: Level: intermediate
179: Notes: The system solved via the Krylov method is
180: $ D M A D^{-1} y = D M b for left preconditioning or
181: $ D A M D^{-1} z = D b for right preconditioning
183: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
185: .keywords: PC
187: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScale()
188: @*/
189: int PCDiagonalScaleSet(PC pc,Vec s)
190: {
196: pc->diagonalscale = PETSC_TRUE;
197: if (pc->diagonalscaleleft) {
198: VecDestroy(pc->diagonalscaleleft);
199: }
200: pc->diagonalscaleleft = s;
201: PetscObjectReference((PetscObject)s);
202: if (!pc->diagonalscaleright) {
203: VecDuplicate(s,&pc->diagonalscaleright);
204: }
205: VecCopy(s,pc->diagonalscaleright);
206: VecReciprocal(pc->diagonalscaleright);
207: return(0);
208: }
212: /*@C
213: PCDiagonalScaleLeft - Indicates the left scaling to use to apply an additional left and right
214: scaling as needed by certain time-stepping codes.
216: Collective on PC
218: Input Parameters:
219: + pc - the preconditioner context
220: . in - input vector
221: + out - scaled vector (maybe the same as in)
223: Level: intermediate
225: Notes: The system solved via the Krylov method is
226: $ D M A D^{-1} y = D M b for left preconditioning or
227: $ D A M D^{-1} z = D b for right preconditioning
229: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
231: If diagonal scaling is turned off and in is not out then in is copied to out
233: .keywords: PC
235: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
236: @*/
237: int PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
238: {
245: if (pc->diagonalscale) {
246: VecPointwiseMult(pc->diagonalscaleleft,in,out);
247: } else if (in != out) {
248: VecCopy(in,out);
249: }
250: return(0);
251: }
255: /*@C
256: PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.
258: Collective on PC
260: Input Parameters:
261: + pc - the preconditioner context
262: . in - input vector
263: + out - scaled vector (maybe the same as in)
265: Level: intermediate
267: Notes: The system solved via the Krylov method is
268: $ D M A D^{-1} y = D M b for left preconditioning or
269: $ D A M D^{-1} z = D b for right preconditioning
271: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
273: If diagonal scaling is turned off and in is not out then in is copied to out
275: .keywords: PC
277: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
278: @*/
279: int PCDiagonalScaleRight(PC pc,Vec in,Vec out)
280: {
287: if (pc->diagonalscale) {
288: VecPointwiseMult(pc->diagonalscaleright,in,out);
289: } else if (in != out) {
290: VecCopy(in,out);
291: }
292: return(0);
293: }
297: static int PCPublish_Petsc(PetscObject obj)
298: {
299: #if defined(PETSC_HAVE_AMS)
300: PC v = (PC) obj;
301: int ierr;
302: #endif
306: #if defined(PETSC_HAVE_AMS)
307: /* if it is already published then return */
308: if (v->amem >=0) return(0);
310: PetscObjectPublishBaseBegin(obj);
311: PetscObjectPublishBaseEnd(obj);
312: #endif
314: return(0);
315: }
319: /*@C
320: PCCreate - Creates a preconditioner context.
322: Collective on MPI_Comm
324: Input Parameter:
325: . comm - MPI communicator
327: Output Parameter:
328: . pc - location to put the preconditioner context
330: Notes:
331: The default preconditioner on one processor is PCILU with 0 fill on more
332: then one it is PCBJACOBI with ILU() on each processor.
334: Level: developer
336: .keywords: PC, create, context
338: .seealso: PCSetUp(), PCApply(), PCDestroy()
339: @*/
340: int PCCreate(MPI_Comm comm,PC *newpc)
341: {
342: PC pc;
347: *newpc = 0;
348: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
349: PCInitializePackage(PETSC_NULL);
350: #endif
352: PetscHeaderCreate(pc,_p_PC,struct _PCOps,PC_COOKIE,-1,"PC",comm,PCDestroy,PCView);
353: PetscLogObjectCreate(pc);
354: pc->bops->publish = PCPublish_Petsc;
355: pc->vec = 0;
356: pc->mat = 0;
357: pc->setupcalled = 0;
358: pc->nullsp = 0;
359: pc->data = 0;
360: pc->diagonalscale = PETSC_FALSE;
361: pc->diagonalscaleleft = 0;
362: pc->diagonalscaleright = 0;
364: pc->ops->destroy = 0;
365: pc->ops->apply = 0;
366: pc->ops->applytranspose = 0;
367: pc->ops->applyBA = 0;
368: pc->ops->applyBAtranspose = 0;
369: pc->ops->applyrichardson = 0;
370: pc->ops->view = 0;
371: pc->ops->getfactoredmatrix = 0;
372: pc->ops->applysymmetricright = 0;
373: pc->ops->applysymmetricleft = 0;
374: pc->ops->setuponblocks = 0;
376: pc->modifysubmatrices = 0;
377: pc->modifysubmatricesP = 0;
378: *newpc = pc;
379: PetscPublishAll(pc);
380: return(0);
382: }
384: /* -------------------------------------------------------------------------------*/
388: /*@
389: PCApply - Applies the preconditioner to a vector.
391: Collective on PC and Vec
393: Input Parameters:
394: + pc - the preconditioner context
395: - x - input vector
397: Output Parameter:
398: . y - output vector
400: Level: developer
402: .keywords: PC, apply
404: .seealso: PCApplyTranspose(), PCApplyBAorAB()
405: @*/
406: int PCApply(PC pc,Vec x,Vec y,PCSide side)
407: {
408: int ierr;
414: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
416: if (pc->setupcalled < 2) {
417: PCSetUp(pc);
418: }
420: /* Remove null space from input vector y */
421: if (side == PC_RIGHT && pc->nullsp) {
422: Vec tmp;
423: MatNullSpaceRemove(pc->nullsp,x,&tmp);
424: x = tmp;
425: SETERRQ(1,"Cannot deflate out null space if using right preconditioner!");
426: }
428: PetscLogEventBegin(PC_Apply,pc,x,y,0);
429: (*pc->ops->apply)(pc,x,y);
430: PetscLogEventEnd(PC_Apply,pc,x,y,0);
432: /* Remove null space from preconditioned vector y */
433: if (side == PC_LEFT && pc->nullsp) {
434: MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
435: }
436: return(0);
437: }
441: /*@
442: PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.
444: Collective on PC and Vec
446: Input Parameters:
447: + pc - the preconditioner context
448: - x - input vector
450: Output Parameter:
451: . y - output vector
453: Notes:
454: Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
456: Level: developer
458: .keywords: PC, apply, symmetric, left
460: .seealso: PCApply(), PCApplySymmetricRight()
461: @*/
462: int PCApplySymmetricLeft(PC pc,Vec x,Vec y)
463: {
470: if (!pc->ops->applysymmetricleft) SETERRQ(1,"PC does not have left symmetric apply");
472: if (pc->setupcalled < 2) {
473: PCSetUp(pc);
474: }
476: PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);
477: (*pc->ops->applysymmetricleft)(pc,x,y);
478: PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);
479: return(0);
480: }
484: /*@
485: PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.
487: Collective on PC and Vec
489: Input Parameters:
490: + pc - the preconditioner context
491: - x - input vector
493: Output Parameter:
494: . y - output vector
496: Level: developer
498: Notes:
499: Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
501: .keywords: PC, apply, symmetric, right
503: .seealso: PCApply(), PCApplySymmetricLeft()
504: @*/
505: int PCApplySymmetricRight(PC pc,Vec x,Vec y)
506: {
513: if (!pc->ops->applysymmetricright) SETERRQ(1,"PC does not have left symmetric apply");
515: if (pc->setupcalled < 2) {
516: PCSetUp(pc);
517: }
519: PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);
520: (*pc->ops->applysymmetricright)(pc,x,y);
521: PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);
522: return(0);
523: }
527: /*@
528: PCApplyTranspose - Applies the transpose of preconditioner to a vector.
530: Collective on PC and Vec
532: Input Parameters:
533: + pc - the preconditioner context
534: - x - input vector
536: Output Parameter:
537: . y - output vector
539: Level: developer
541: .keywords: PC, apply, transpose
543: .seealso: PCApply(), PCApplyBAorAB(), PCApplyBAorABTranspose(), PCHasApplyTranspose()
544: @*/
545: int PCApplyTranspose(PC pc,Vec x,Vec y)
546: {
553: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
554: if (!pc->ops->applytranspose) SETERRQ(PETSC_ERR_SUP," ");
556: if (pc->setupcalled < 2) {
557: PCSetUp(pc);
558: }
560: PetscLogEventBegin(PC_Apply,pc,x,y,0);
561: (*pc->ops->applytranspose)(pc,x,y);
562: PetscLogEventEnd(PC_Apply,pc,x,y,0);
563: return(0);
564: }
568: /*@
569: PCHasApplyTranspose - Test whether the preconditioner has a transpose apply operation
571: Collective on PC and Vec
573: Input Parameters:
574: . pc - the preconditioner context
576: Output Parameter:
577: . flg - PETSC_TRUE if a transpose operation is defined
579: Level: developer
581: .keywords: PC, apply, transpose
583: .seealso: PCApplyTranspose()
584: @*/
585: int PCHasApplyTranspose(PC pc,PetscTruth *flg)
586: {
590: *flg = (PetscTruth) (pc->ops->applytranspose == 0);
591: return(0);
592: }
596: /*@
597: PCApplyBAorAB - Applies the preconditioner and operator to a vector.
599: Collective on PC and Vec
601: Input Parameters:
602: + pc - the preconditioner context
603: . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
604: . x - input vector
605: - work - work vector
607: Output Parameter:
608: . y - output vector
610: Level: developer
612: .keywords: PC, apply, operator
614: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
615: @*/
616: int PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
617: {
618: int ierr;
625: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
626: if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) {
627: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric");
628: }
629: if (pc->diagonalscale && side == PC_SYMMETRIC) {
630: SETERRQ(1,"Cannot include diagonal scaling with symmetric preconditioner application");
631: }
633: if (pc->setupcalled < 2) {
634: PCSetUp(pc);
635: }
637: if (pc->diagonalscale) {
638: if (pc->ops->applyBA) {
639: Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
640: VecDuplicate(x,&work2);
641: PCDiagonalScaleRight(pc,x,work2);
642: (*pc->ops->applyBA)(pc,side,work2,y,work);
643: /* Remove null space from preconditioned vector y */
644: if (pc->nullsp) {
645: MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
646: }
647: PCDiagonalScaleLeft(pc,y,y);
648: VecDestroy(work2);
649: } else if (side == PC_RIGHT) {
650: PCDiagonalScaleRight(pc,x,y);
651: PCApply(pc,y,work,side);
652: MatMult(pc->mat,work,y);
653: PCDiagonalScaleLeft(pc,y,y);
654: } else if (side == PC_LEFT) {
655: PCDiagonalScaleRight(pc,x,y);
656: MatMult(pc->mat,y,work);
657: PCApply(pc,work,y,side);
658: PCDiagonalScaleLeft(pc,y,y);
659: } else if (side == PC_SYMMETRIC) {
660: SETERRQ(1,"Cannot provide diagonal scaling with symmetric application of preconditioner");
661: }
662: } else {
663: if (pc->ops->applyBA) {
664: (*pc->ops->applyBA)(pc,side,x,y,work);
665: /* Remove null space from preconditioned vector y */
666: if (pc->nullsp) {
667: MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
668: }
669: } else if (side == PC_RIGHT) {
670: PCApply(pc,x,work,side);
671: MatMult(pc->mat,work,y);
672: } else if (side == PC_LEFT) {
673: MatMult(pc->mat,x,work);
674: PCApply(pc,work,y,side);
675: } else if (side == PC_SYMMETRIC) {
676: /* There's an extra copy here; maybe should provide 2 work vectors instead? */
677: PCApplySymmetricRight(pc,x,work);
678: MatMult(pc->mat,work,y);
679: VecCopy(y,work);
680: PCApplySymmetricLeft(pc,work,y);
681: }
682: }
683: return(0);
684: }
688: /*@
689: PCApplyBAorABTranspose - Applies the transpose of the preconditioner
690: and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
691: not tr(B*A) = tr(A)*tr(B).
693: Collective on PC and Vec
695: Input Parameters:
696: + pc - the preconditioner context
697: . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
698: . x - input vector
699: - work - work vector
701: Output Parameter:
702: . y - output vector
704: Level: developer
706: .keywords: PC, apply, operator, transpose
708: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
709: @*/
710: int PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
711: {
719: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
720: if (pc->ops->applyBAtranspose) {
721: (*pc->ops->applyBAtranspose)(pc,side,x,y,work);
722: return(0);
723: }
724: if (side != PC_LEFT && side != PC_RIGHT) {
725: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");
726: }
728: if (pc->setupcalled < 2) {
729: PCSetUp(pc);
730: }
732: if (side == PC_RIGHT) {
733: PCApplyTranspose(pc,x,work);
734: MatMultTranspose(pc->mat,work,y);
735: } else if (side == PC_LEFT) {
736: MatMultTranspose(pc->mat,x,work);
737: PCApplyTranspose(pc,work,y);
738: }
739: /* add support for PC_SYMMETRIC */
740: return(0); /* actually will never get here */
741: }
743: /* -------------------------------------------------------------------------------*/
747: /*@
748: PCApplyRichardsonExists - Determines whether a particular preconditioner has a
749: built-in fast application of Richardson's method.
751: Not Collective
753: Input Parameter:
754: . pc - the preconditioner
756: Output Parameter:
757: . exists - PETSC_TRUE or PETSC_FALSE
759: Level: developer
761: .keywords: PC, apply, Richardson, exists
763: .seealso: PCApplyRichardson()
764: @*/
765: int PCApplyRichardsonExists(PC pc,PetscTruth *exists)
766: {
770: if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
771: else *exists = PETSC_FALSE;
772: return(0);
773: }
777: /*@
778: PCApplyRichardson - Applies several steps of Richardson iteration with
779: the particular preconditioner. This routine is usually used by the
780: Krylov solvers and not the application code directly.
782: Collective on PC
784: Input Parameters:
785: + pc - the preconditioner context
786: . x - the initial guess
787: . w - one work vector
788: . rtol - relative decrease in residual norm convergence criteria
789: . atol - absolute residual norm convergence criteria
790: . dtol - divergence residual norm increase criteria
791: - its - the number of iterations to apply.
793: Output Parameter:
794: . y - the solution
796: Notes:
797: Most preconditioners do not support this function. Use the command
798: PCApplyRichardsonExists() to determine if one does.
800: Except for the multigrid PC this routine ignores the convergence tolerances
801: and always runs for the number of iterations
802:
803: Level: developer
805: .keywords: PC, apply, Richardson
807: .seealso: PCApplyRichardsonExists()
808: @*/
809: int PCApplyRichardson(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int its)
810: {
818: if (!pc->ops->applyrichardson) SETERRQ(PETSC_ERR_SUP," ");
820: if (pc->setupcalled < 2) {
821: PCSetUp(pc);
822: }
824: (*pc->ops->applyrichardson)(pc,x,y,w,rtol,atol,dtol,its);
825: return(0);
826: }
828: /*
829: a setupcall of 0 indicates never setup,
830: 1 needs to be resetup,
831: 2 does not need any changes.
832: */
835: /*@
836: PCSetUp - Prepares for the use of a preconditioner.
838: Collective on PC
840: Input Parameter:
841: . pc - the preconditioner context
843: Level: developer
845: .keywords: PC, setup
847: .seealso: PCCreate(), PCApply(), PCDestroy()
848: @*/
849: int PCSetUp(PC pc)
850: {
851: int ierr;
852: const char *def;
857: if (pc->setupcalled > 1) {
858: PetscLogInfo(pc,"PCSetUp:Setting PC with identical preconditioner\n");
859: return(0);
860: } else if (pc->setupcalled == 0) {
861: PetscLogInfo(pc,"PCSetUp:Setting up new PC\n");
862: } else if (pc->flag == SAME_NONZERO_PATTERN) {
863: PetscLogInfo(pc,"PCSetUp:Setting up PC with same nonzero pattern\n");
864: } else {
865: PetscLogInfo(pc,"PCSetUp:Setting up PC with different nonzero pattern\n");
866: }
868: PetscLogEventBegin(PC_SetUp,pc,0,0,0);
869: if (!pc->vec) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Vector must be set first");}
870: if (!pc->mat) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");}
872: if (!pc->type_name) {
873: PCGetDefaultType_Private(pc,&def);
874: PCSetType(pc,def);
875: }
877: if (pc->ops->setup) {
878: (*pc->ops->setup)(pc);
879: }
880: pc->setupcalled = 2;
881: if (pc->nullsp) {
882: PetscTruth test;
883: PetscOptionsHasName(pc->prefix,"-pc_test_null_space",&test);
884: if (test) {
885: MatNullSpaceTest(pc->nullsp,pc->mat);
886: }
887: }
888: PetscLogEventEnd(PC_SetUp,pc,0,0,0);
889: return(0);
890: }
894: /*@
895: PCSetUpOnBlocks - Sets up the preconditioner for each block in
896: the block Jacobi, block Gauss-Seidel, and overlapping Schwarz
897: methods.
899: Collective on PC
901: Input Parameters:
902: . pc - the preconditioner context
904: Level: developer
906: .keywords: PC, setup, blocks
908: .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
909: @*/
910: int PCSetUpOnBlocks(PC pc)
911: {
916: if (!pc->ops->setuponblocks) return(0);
917: PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);
918: (*pc->ops->setuponblocks)(pc);
919: PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);
920: return(0);
921: }
925: /*@C
926: PCSetModifySubMatrices - Sets a user-defined routine for modifying the
927: submatrices that arise within certain subdomain-based preconditioners.
928: The basic submatrices are extracted from the preconditioner matrix as
929: usual; the user can then alter these (for example, to set different boundary
930: conditions for each submatrix) before they are used for the local solves.
932: Collective on PC
934: Input Parameters:
935: + pc - the preconditioner context
936: . func - routine for modifying the submatrices
937: - ctx - optional user-defined context (may be null)
939: Calling sequence of func:
940: $ func (PC pc,int nsub,IS *row,IS *col,Mat *submat,void *ctx);
942: . row - an array of index sets that contain the global row numbers
943: that comprise each local submatrix
944: . col - an array of index sets that contain the global column numbers
945: that comprise each local submatrix
946: . submat - array of local submatrices
947: - ctx - optional user-defined context for private data for the
948: user-defined func routine (may be null)
950: Notes:
951: PCSetModifySubMatrices() MUST be called before KSPSetUp() and
952: KSPSolve().
954: A routine set by PCSetModifySubMatrices() is currently called within
955: the block Jacobi (PCBJACOBI) and additive Schwarz (PCASM)
956: preconditioners. All other preconditioners ignore this routine.
958: Level: advanced
960: .keywords: PC, set, modify, submatrices
962: .seealso: PCModifySubMatrices()
963: @*/
964: int PCSetModifySubMatrices(PC pc,int(*func)(PC,int,const IS[],const IS[],Mat[],void*),void *ctx)
965: {
968: pc->modifysubmatrices = func;
969: pc->modifysubmatricesP = ctx;
970: return(0);
971: }
975: /*@C
976: PCModifySubMatrices - Calls an optional user-defined routine within
977: certain preconditioners if one has been set with PCSetModifySubMarices().
979: Collective on PC
981: Input Parameters:
982: + pc - the preconditioner context
983: . nsub - the number of local submatrices
984: . row - an array of index sets that contain the global row numbers
985: that comprise each local submatrix
986: . col - an array of index sets that contain the global column numbers
987: that comprise each local submatrix
988: . submat - array of local submatrices
989: - ctx - optional user-defined context for private data for the
990: user-defined routine (may be null)
992: Output Parameter:
993: . submat - array of local submatrices (the entries of which may
994: have been modified)
996: Notes:
997: The user should NOT generally call this routine, as it will
998: automatically be called within certain preconditioners (currently
999: block Jacobi, additive Schwarz) if set.
1001: The basic submatrices are extracted from the preconditioner matrix
1002: as usual; the user can then alter these (for example, to set different
1003: boundary conditions for each submatrix) before they are used for the
1004: local solves.
1006: Level: developer
1008: .keywords: PC, modify, submatrices
1010: .seealso: PCSetModifySubMatrices()
1011: @*/
1012: int PCModifySubMatrices(PC pc,int nsub,const IS row[],const IS col[],Mat submat[],void *ctx)
1013: {
1017: if (!pc->modifysubmatrices) return(0);
1018: PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);
1019: (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);
1020: PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);
1021: return(0);
1022: }
1026: /*@
1027: PCSetOperators - Sets the matrix associated with the linear system and
1028: a (possibly) different one associated with the preconditioner.
1030: Collective on PC and Mat
1032: Input Parameters:
1033: + pc - the preconditioner context
1034: . Amat - the matrix associated with the linear system
1035: . Pmat - the matrix to be used in constructing the preconditioner, usually
1036: the same as Amat.
1037: - flag - flag indicating information about the preconditioner matrix structure
1038: during successive linear solves. This flag is ignored the first time a
1039: linear system is solved, and thus is irrelevant when solving just one linear
1040: system.
1042: Notes:
1043: The flag can be used to eliminate unnecessary work in the preconditioner
1044: during the repeated solution of linear systems of the same size. The
1045: available options are
1046: + SAME_PRECONDITIONER -
1047: Pmat is identical during successive linear solves.
1048: This option is intended for folks who are using
1049: different Amat and Pmat matrices and wish to reuse the
1050: same preconditioner matrix. For example, this option
1051: saves work by not recomputing incomplete factorization
1052: for ILU/ICC preconditioners.
1053: . SAME_NONZERO_PATTERN -
1054: Pmat has the same nonzero structure during
1055: successive linear solves.
1056: - DIFFERENT_NONZERO_PATTERN -
1057: Pmat does not have the same nonzero structure.
1059: Caution:
1060: If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion
1061: and does not check the structure of the matrix. If you erroneously
1062: claim that the structure is the same when it actually is not, the new
1063: preconditioner will not function correctly. Thus, use this optimization
1064: feature carefully!
1066: If in doubt about whether your preconditioner matrix has changed
1067: structure or not, use the flag DIFFERENT_NONZERO_PATTERN.
1069: More Notes about Repeated Solution of Linear Systems:
1070: PETSc does NOT reset the matrix entries of either Amat or Pmat
1071: to zero after a linear solve; the user is completely responsible for
1072: matrix assembly. See the routine MatZeroEntries() if desiring to
1073: zero all elements of a matrix.
1075: Level: intermediate
1077: .keywords: PC, set, operators, matrix, linear system
1079: .seealso: PCGetOperators(), MatZeroEntries()
1080: @*/
1081: int PCSetOperators(PC pc,Mat Amat,Mat Pmat,MatStructure flag)
1082: {
1083: int ierr;
1084: PetscTruth isbjacobi,isrowbs;
1091: /*
1092: BlockSolve95 cannot use default BJacobi preconditioning
1093: */
1094: PetscTypeCompare((PetscObject)Amat,MATMPIROWBS,&isrowbs);
1095: if (isrowbs) {
1096: PetscTypeCompare((PetscObject)pc,PCBJACOBI,&isbjacobi);
1097: if (isbjacobi) {
1098: PCSetType(pc,PCILU);
1099: PetscLogInfo(pc,"PCSetOperators:Switching default PC to PCILU since BS95 doesn't support PCBJACOBI\n");
1100: }
1101: }
1103: pc->mat = Amat;
1104: pc->pmat = Pmat;
1105: if (pc->setupcalled == 2 && flag != SAME_PRECONDITIONER) {
1106: pc->setupcalled = 1;
1107: }
1108: pc->flag = flag;
1109: return(0);
1110: }
1114: /*@C
1115: PCGetOperators - Gets the matrix associated with the linear system and
1116: possibly a different one associated with the preconditioner.
1118: Not collective, though parallel Mats are returned if the PC is parallel
1120: Input Parameter:
1121: . pc - the preconditioner context
1123: Output Parameters:
1124: + mat - the matrix associated with the linear system
1125: . pmat - matrix associated with the preconditioner, usually the same
1126: as mat.
1127: - flag - flag indicating information about the preconditioner
1128: matrix structure. See PCSetOperators() for details.
1130: Level: intermediate
1132: .keywords: PC, get, operators, matrix, linear system
1134: .seealso: PCSetOperators()
1135: @*/
1136: int PCGetOperators(PC pc,Mat *mat,Mat *pmat,MatStructure *flag)
1137: {
1140: if (mat) *mat = pc->mat;
1141: if (pmat) *pmat = pc->pmat;
1142: if (flag) *flag = pc->flag;
1143: return(0);
1144: }
1148: /*@
1149: PCSetVector - Sets a vector associated with the preconditioner.
1151: Collective on PC and Vec
1153: Input Parameters:
1154: + pc - the preconditioner context
1155: - vec - the vector
1157: Notes:
1158: The vector must be set so that the preconditioner knows what type
1159: of vector to allocate if necessary.
1161: Level: intermediate
1163: .keywords: PC, set, vector
1165: .seealso: PCGetVector()
1167: @*/
1168: int PCSetVector(PC pc,Vec vec)
1169: {
1174: pc->vec = vec;
1175: return(0);
1176: }
1180: /*@
1181: PCGetVector - Gets a vector associated with the preconditioner; if the
1182: vector was not get set it will return a 0 pointer.
1184: Not collective, but vector is shared by all processors that share the PC
1186: Input Parameter:
1187: . pc - the preconditioner context
1189: Output Parameter:
1190: . vec - the vector
1192: Level: intermediate
1194: .keywords: PC, get, vector
1196: .seealso: PCSetVector()
1198: @*/
1199: int PCGetVector(PC pc,Vec *vec)
1200: {
1203: *vec = pc->vec;
1204: return(0);
1205: }
1209: /*@C
1210: PCGetFactoredMatrix - Gets the factored matrix from the
1211: preconditioner context. This routine is valid only for the LU,
1212: incomplete LU, Cholesky, and incomplete Cholesky methods.
1214: Not Collective on PC though Mat is parallel if PC is parallel
1216: Input Parameters:
1217: . pc - the preconditioner context
1219: Output parameters:
1220: . mat - the factored matrix
1222: Level: advanced
1224: .keywords: PC, get, factored, matrix
1225: @*/
1226: int PCGetFactoredMatrix(PC pc,Mat *mat)
1227: {
1233: if (pc->ops->getfactoredmatrix) {
1234: (*pc->ops->getfactoredmatrix)(pc,mat);
1235: }
1236: return(0);
1237: }
1241: /*@C
1242: PCSetOptionsPrefix - Sets the prefix used for searching for all
1243: PC options in the database.
1245: Collective on PC
1247: Input Parameters:
1248: + pc - the preconditioner context
1249: - prefix - the prefix string to prepend to all PC option requests
1251: Notes:
1252: A hyphen (-) must NOT be given at the beginning of the prefix name.
1253: The first character of all runtime options is AUTOMATICALLY the
1254: hyphen.
1256: Level: advanced
1258: .keywords: PC, set, options, prefix, database
1260: .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1261: @*/
1262: int PCSetOptionsPrefix(PC pc,const char prefix[])
1263: {
1268: PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);
1269: return(0);
1270: }
1274: /*@C
1275: PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1276: PC options in the database.
1278: Collective on PC
1280: Input Parameters:
1281: + pc - the preconditioner context
1282: - prefix - the prefix string to prepend to all PC option requests
1284: Notes:
1285: A hyphen (-) must NOT be given at the beginning of the prefix name.
1286: The first character of all runtime options is AUTOMATICALLY the
1287: hyphen.
1289: Level: advanced
1291: .keywords: PC, append, options, prefix, database
1293: .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1294: @*/
1295: int PCAppendOptionsPrefix(PC pc,const char prefix[])
1296: {
1301: PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);
1302: return(0);
1303: }
1307: /*@C
1308: PCGetOptionsPrefix - Gets the prefix used for searching for all
1309: PC options in the database.
1311: Not Collective
1313: Input Parameters:
1314: . pc - the preconditioner context
1316: Output Parameters:
1317: . prefix - pointer to the prefix string used, is returned
1319: Notes: On the fortran side, the user should pass in a string 'prifix' of
1320: sufficient length to hold the prefix.
1322: Level: advanced
1324: .keywords: PC, get, options, prefix, database
1326: .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1327: @*/
1328: int PCGetOptionsPrefix(PC pc,char *prefix[])
1329: {
1335: PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);
1336: return(0);
1337: }
1341: /*@
1342: PCPreSolve - Optional pre-solve phase, intended for any
1343: preconditioner-specific actions that must be performed before
1344: the iterative solve itself.
1346: Collective on PC
1348: Input Parameters:
1349: + pc - the preconditioner context
1350: - ksp - the Krylov subspace context
1352: Level: developer
1354: Sample of Usage:
1355: .vb
1356: PCPreSolve(pc,ksp);
1357: KSPSolve(ksp,its);
1358: PCPostSolve(pc,ksp);
1359: .ve
1361: Notes:
1362: The pre-solve phase is distinct from the PCSetUp() phase.
1364: KSPSolve() calls this directly, so is rarely called by the user.
1366: .keywords: PC, pre-solve
1368: .seealso: PCPostSolve()
1369: @*/
1370: int PCPreSolve(PC pc,KSP ksp)
1371: {
1373: Vec x,rhs;
1374: Mat A,B;
1379: KSPGetSolution(ksp,&x);
1380: KSPGetRhs(ksp,&rhs);
1381: /*
1382: Scale the system and have the matrices use the scaled form
1383: only if the two matrices are actually the same (and hence
1384: have the same scaling
1385: */
1386: PCGetOperators(pc,&A,&B,PETSC_NULL);
1387: if (A == B) {
1388: MatScaleSystem(pc->mat,x,rhs);
1389: MatUseScaledForm(pc->mat,PETSC_TRUE);
1390: }
1392: if (pc->ops->presolve) {
1393: (*pc->ops->presolve)(pc,ksp,x,rhs);
1394: }
1395: return(0);
1396: }
1400: /*@
1401: PCPostSolve - Optional post-solve phase, intended for any
1402: preconditioner-specific actions that must be performed after
1403: the iterative solve itself.
1405: Collective on PC
1407: Input Parameters:
1408: + pc - the preconditioner context
1409: - ksp - the Krylov subspace context
1411: Sample of Usage:
1412: .vb
1413: PCPreSolve(pc,ksp);
1414: KSPSolve(ksp,its);
1415: PCPostSolve(pc,ksp);
1416: .ve
1418: Note:
1419: KSPSolve() calls this routine directly, so it is rarely called by the user.
1421: Level: developer
1423: .keywords: PC, post-solve
1425: .seealso: PCPreSolve(), KSPSolve()
1426: @*/
1427: int PCPostSolve(PC pc,KSP ksp)
1428: {
1430: Vec x,rhs;
1431: Mat A,B;
1436: KSPGetSolution(ksp,&x);
1437: KSPGetRhs(ksp,&rhs);
1438: if (pc->ops->postsolve) {
1439: (*pc->ops->postsolve)(pc,ksp,x,rhs);
1440: }
1442: /*
1443: Scale the system and have the matrices use the scaled form
1444: only if the two matrices are actually the same (and hence
1445: have the same scaling
1446: */
1447: PCGetOperators(pc,&A,&B,PETSC_NULL);
1448: if (A == B) {
1449: MatUnScaleSystem(pc->mat,x,rhs);
1450: MatUseScaledForm(pc->mat,PETSC_FALSE);
1451: }
1452: return(0);
1453: }
1457: /*@C
1458: PCView - Prints the PC data structure.
1460: Collective on PC
1462: Input Parameters:
1463: + PC - the PC context
1464: - viewer - optional visualization context
1466: Note:
1467: The available visualization contexts include
1468: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
1469: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1470: output where only the first processor opens
1471: the file. All other processors send their
1472: data to the first processor to print.
1474: The user can open an alternative visualization contexts with
1475: PetscViewerASCIIOpen() (output to a specified file).
1477: Level: developer
1479: .keywords: PC, view
1481: .seealso: KSPView(), PetscViewerASCIIOpen()
1482: @*/
1483: int PCView(PC pc,PetscViewer viewer)
1484: {
1485: PCType cstr;
1486: int ierr;
1487: PetscTruth mat_exists,isascii,isstring;
1488: PetscViewerFormat format;
1492: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pc->comm);
1496: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
1497: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
1498: if (isascii) {
1499: PetscViewerGetFormat(viewer,&format);
1500: if (pc->prefix) {
1501: PetscViewerASCIIPrintf(viewer,"PC Object:(%s)\n",pc->prefix);
1502: } else {
1503: PetscViewerASCIIPrintf(viewer,"PC Object:\n");
1504: }
1505: PCGetType(pc,&cstr);
1506: if (cstr) {
1507: PetscViewerASCIIPrintf(viewer," type: %s\n",cstr);
1508: } else {
1509: PetscViewerASCIIPrintf(viewer," type: not yet set\n");
1510: }
1511: if (pc->ops->view) {
1512: PetscViewerASCIIPushTab(viewer);
1513: (*pc->ops->view)(pc,viewer);
1514: PetscViewerASCIIPopTab(viewer);
1515: }
1516: PetscObjectExists((PetscObject)pc->mat,&mat_exists);
1517: if (mat_exists) {
1518: PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
1519: if (pc->pmat == pc->mat) {
1520: PetscViewerASCIIPrintf(viewer," linear system matrix = precond matrix:\n");
1521: PetscViewerASCIIPushTab(viewer);
1522: MatView(pc->mat,viewer);
1523: PetscViewerASCIIPopTab(viewer);
1524: } else {
1525: PetscObjectExists((PetscObject)pc->pmat,&mat_exists);
1526: if (mat_exists) {
1527: PetscViewerASCIIPrintf(viewer," linear system matrix followed by preconditioner matrix:\n");
1528: } else {
1529: PetscViewerASCIIPrintf(viewer," linear system matrix:\n");
1530: }
1531: PetscViewerASCIIPushTab(viewer);
1532: MatView(pc->mat,viewer);
1533: if (mat_exists) {MatView(pc->pmat,viewer);}
1534: PetscViewerASCIIPopTab(viewer);
1535: }
1536: PetscViewerPopFormat(viewer);
1537: }
1538: } else if (isstring) {
1539: PCGetType(pc,&cstr);
1540: PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
1541: if (pc->ops->view) {(*pc->ops->view)(pc,viewer);}
1542: } else {
1543: SETERRQ1(1,"Viewer type %s not supported by PC",((PetscObject)viewer)->type_name);
1544: }
1545: return(0);
1546: }
1550: /*@C
1551: PCRegister - See PCRegisterDynamic()
1553: Level: advanced
1554: @*/
1555: int PCRegister(const char sname[],const char path[],const char name[],int (*function)(PC))
1556: {
1557: int ierr;
1558: char fullname[256];
1562: PetscFListConcat(path,name,fullname);
1563: PetscFListAdd(&PCList,sname,fullname,(void (*)(void))function);
1564: return(0);
1565: }
1569: /*@
1570: PCComputeExplicitOperator - Computes the explicit preconditioned operator.
1572: Collective on PC
1574: Input Parameter:
1575: . pc - the preconditioner object
1577: Output Parameter:
1578: . mat - the explict preconditioned operator
1580: Notes:
1581: This computation is done by applying the operators to columns of the
1582: identity matrix.
1584: Currently, this routine uses a dense matrix format when 1 processor
1585: is used and a sparse format otherwise. This routine is costly in general,
1586: and is recommended for use only with relatively small systems.
1588: Level: advanced
1589:
1590: .keywords: PC, compute, explicit, operator
1592: @*/
1593: int PCComputeExplicitOperator(PC pc,Mat *mat)
1594: {
1595: Vec in,out;
1596: int ierr,i,M,m,size,*rows,start,end;
1597: MPI_Comm comm;
1598: PetscScalar *array,zero = 0.0,one = 1.0;
1604: comm = pc->comm;
1605: MPI_Comm_size(comm,&size);
1607: PCGetVector(pc,&in);
1608: VecDuplicate(in,&out);
1609: VecGetOwnershipRange(in,&start,&end);
1610: VecGetSize(in,&M);
1611: VecGetLocalSize(in,&m);
1612: PetscMalloc((m+1)*sizeof(int),&rows);
1613: for (i=0; i<m; i++) {rows[i] = start + i;}
1615: MatCreate(comm,m,m,M,M,mat);
1616: if (size == 1) {
1617: MatSetType(*mat,MATSEQDENSE);
1618: MatSeqDenseSetPreallocation(*mat,PETSC_NULL);
1619: } else {
1620: MatSetType(*mat,MATMPIAIJ);
1621: MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);
1622: }
1624: for (i=0; i<M; i++) {
1626: VecSet(&zero,in);
1627: VecSetValues(in,1,&i,&one,INSERT_VALUES);
1628: VecAssemblyBegin(in);
1629: VecAssemblyEnd(in);
1631: /* should fix, allowing user to choose side */
1632: PCApply(pc,in,out,PC_LEFT);
1633:
1634: VecGetArray(out,&array);
1635: MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
1636: VecRestoreArray(out,&array);
1638: }
1639: PetscFree(rows);
1640: VecDestroy(out);
1641: MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
1642: MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
1643: return(0);
1644: }