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/sles/pc/pcimpl.h
7: /* Logging support */
8: int PC_COOKIE;
9: int PC_SetUp, PC_SetUpOnBlocks, PC_Apply, PC_ApplyCoarse, PC_ApplyMultiple, PC_ApplySymmetricLeft;
10: int PC_ApplySymmetricRight, PC_ModifySubMatrices;
12: EXTERN int SLESInitializePackage(char *);
14: /*@C
15: PCNullSpaceAttach - attaches a null space to a preconditioner object.
16: This null space will be removed from the resulting vector whenever
17: the preconditioner is applied.
19: Collective on PC
21: Input Parameters:
22: + pc - the preconditioner context
23: - nullsp - the null space object
25: Level: developer
27: Notes:
28: Overwrites any previous null space that may have been attached
30: .keywords: PC, destroy, null space
32: .seealso: PCCreate(), PCSetUp()
33: @*/
34: int PCNullSpaceAttach(PC pc,MatNullSpace nullsp)
35: {
42: if (pc->nullsp) {
43: MatNullSpaceDestroy(pc->nullsp);
44: }
45: pc->nullsp = nullsp;
46: PetscObjectReference((PetscObject)nullsp);
47: return(0);
48: }
50: /*@C
51: PCDestroy - Destroys PC context that was created with PCCreate().
53: Collective on PC
55: Input Parameter:
56: . pc - the preconditioner context
58: Level: developer
60: .keywords: PC, destroy
62: .seealso: PCCreate(), PCSetUp()
63: @*/
64: int PCDestroy(PC pc)
65: {
70: if (--pc->refct > 0) return(0);
72: /* if memory was published with AMS then destroy it */
73: PetscObjectDepublish(pc);
75: if (pc->ops->destroy) { (*pc->ops->destroy)(pc);}
76: if (pc->nullsp) {MatNullSpaceDestroy(pc->nullsp);}
77: if (pc->diagonalscaleright) {VecDestroy(pc->diagonalscaleright);}
78: if (pc->diagonalscaleleft) {VecDestroy(pc->diagonalscaleleft);}
80: PetscLogObjectDestroy(pc);
81: PetscHeaderDestroy(pc);
82: return(0);
83: }
85: /*@C
86: PCDiagonalScale - Indicates if the preconditioner applies an additional left and right
87: scaling as needed by certain time-stepping codes.
89: Collective on PC
91: Input Parameter:
92: . pc - the preconditioner context
94: Output Parameter:
95: . flag - PETSC_TRUE if it applies the scaling
97: Level: developer
99: Notes: If this returns PETSC_TRUE then the system solved via the Krylov method is
100: $ D M A D^{-1} y = D M b for left preconditioning or
101: $ D A M D^{-1} z = D b for right preconditioning
103: .keywords: PC
105: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScaleSet()
106: @*/
107: int PCDiagonalScale(PC pc,PetscTruth *flag)
108: {
111: *flag = pc->diagonalscale;
112: return(0);
113: }
115: /*@C
116: PCDiagonalScaleSet - Indicates the left scaling to use to apply an additional left and right
117: scaling as needed by certain time-stepping codes.
119: Collective on PC
121: Input Parameters:
122: + pc - the preconditioner context
123: - s - scaling vector
125: Level: intermediate
127: Notes: The system solved via the Krylov method is
128: $ D M A D^{-1} y = D M b for left preconditioning or
129: $ D A M D^{-1} z = D b for right preconditioning
131: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
133: .keywords: PC
135: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScale()
136: @*/
137: int PCDiagonalScaleSet(PC pc,Vec s)
138: {
144: pc->diagonalscale = PETSC_TRUE;
145: if (pc->diagonalscaleleft) {
146: VecDestroy(pc->diagonalscaleleft);
147: }
148: pc->diagonalscaleleft = s;
149: ierr = PetscObjectReference((PetscObject)s);
150: if (!pc->diagonalscaleright) {
151: VecDuplicate(s,&pc->diagonalscaleright);
152: }
153: VecCopy(s,pc->diagonalscaleright);
154: VecReciprocal(pc->diagonalscaleright);
155: return(0);
156: }
158: /*@C
159: PCDiagonalScaleLeft - Indicates the left scaling to use to apply an additional left and right
160: scaling as needed by certain time-stepping codes.
162: Collective on PC
164: Input Parameters:
165: + pc - the preconditioner context
166: . in - input vector
167: + out - scaled vector (maybe the same as in)
169: Level: intermediate
171: Notes: The system solved via the Krylov method is
172: $ D M A D^{-1} y = D M b for left preconditioning or
173: $ D A M D^{-1} z = D b for right preconditioning
175: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
177: If diagonal scaling is turned off and in is not out then in is copied to out
179: .keywords: PC
181: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
182: @*/
183: int PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
184: {
191: if (pc->diagonalscale) {
192: VecPointwiseMult(pc->diagonalscaleleft,in,out);
193: } else if (in != out) {
194: VecCopy(in,out);
195: }
196: return(0);
197: }
199: /*@C
200: PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.
202: Collective on PC
204: Input Parameters:
205: + pc - the preconditioner context
206: . in - input vector
207: + out - scaled vector (maybe the same as in)
209: Level: intermediate
211: Notes: The system solved via the Krylov method is
212: $ D M A D^{-1} y = D M b for left preconditioning or
213: $ D A M D^{-1} z = D b for right preconditioning
215: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
217: If diagonal scaling is turned off and in is not out then in is copied to out
219: .keywords: PC
221: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
222: @*/
223: int PCDiagonalScaleRight(PC pc,Vec in,Vec out)
224: {
231: if (pc->diagonalscale) {
232: VecPointwiseMult(pc->diagonalscaleright,in,out);
233: } else if (in != out) {
234: VecCopy(in,out);
235: }
236: return(0);
237: }
239: static int PCPublish_Petsc(PetscObject obj)
240: {
241: #if defined(PETSC_HAVE_AMS)
242: PC v = (PC) obj;
243: int ierr;
244: #endif
248: #if defined(PETSC_HAVE_AMS)
249: /* if it is already published then return */
250: if (v->amem >=0) return(0);
252: PetscObjectPublishBaseBegin(obj);
253: PetscObjectPublishBaseEnd(obj);
254: #endif
256: return(0);
257: }
259: /*@C
260: PCCreate - Creates a preconditioner context.
262: Collective on MPI_Comm
264: Input Parameter:
265: . comm - MPI communicator
267: Output Parameter:
268: . pc - location to put the preconditioner context
270: Notes:
271: The default preconditioner on one processor is PCILU with 0 fill on more
272: then one it is PCBJACOBI with ILU() on each processor.
274: Level: developer
276: .keywords: PC, create, context
278: .seealso: PCSetUp(), PCApply(), PCDestroy()
279: @*/
280: int PCCreate(MPI_Comm comm,PC *newpc)
281: {
282: PC pc;
287: *newpc = 0;
288: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
289: SLESInitializePackage(PETSC_NULL);
290: #endif
292: PetscHeaderCreate(pc,_p_PC,struct _PCOps,PC_COOKIE,-1,"PC",comm,PCDestroy,PCView);
293: PetscLogObjectCreate(pc);
294: pc->bops->publish = PCPublish_Petsc;
295: pc->vec = 0;
296: pc->mat = 0;
297: pc->setupcalled = 0;
298: pc->nullsp = 0;
299: pc->data = 0;
300: pc->diagonalscale = PETSC_FALSE;
301: pc->diagonalscaleleft = 0;
302: pc->diagonalscaleright = 0;
304: pc->ops->destroy = 0;
305: pc->ops->apply = 0;
306: pc->ops->applytranspose = 0;
307: pc->ops->applyBA = 0;
308: pc->ops->applyBAtranspose = 0;
309: pc->ops->applyrichardson = 0;
310: pc->ops->view = 0;
311: pc->ops->getfactoredmatrix = 0;
312: pc->ops->applysymmetricright = 0;
313: pc->ops->applysymmetricleft = 0;
314: pc->ops->setuponblocks = 0;
316: pc->modifysubmatrices = 0;
317: pc->modifysubmatricesP = 0;
318: *newpc = pc;
319: PetscPublishAll(pc);
320: return(0);
322: }
324: /* -------------------------------------------------------------------------------*/
326: /*@
327: PCApply - Applies the preconditioner to a vector.
329: Collective on PC and Vec
331: Input Parameters:
332: + pc - the preconditioner context
333: - x - input vector
335: Output Parameter:
336: . y - output vector
338: Level: developer
340: .keywords: PC, apply
342: .seealso: PCApplyTranspose(), PCApplyBAorAB()
343: @*/
344: int PCApply(PC pc,Vec x,Vec y)
345: {
346: int ierr;
352: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
354: if (pc->setupcalled < 2) {
355: PCSetUp(pc);
356: }
358: PetscLogEventBegin(PC_Apply,pc,x,y,0);
359: (*pc->ops->apply)(pc,x,y);
360: PetscLogEventEnd(PC_Apply,pc,x,y,0);
362: /* Remove null space from preconditioned vector y */
363: if (pc->nullsp) {
364: MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
365: }
366: return(0);
367: }
369: /*@
370: PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.
372: Collective on PC and Vec
374: Input Parameters:
375: + pc - the preconditioner context
376: - x - input vector
378: Output Parameter:
379: . y - output vector
381: Notes:
382: Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
384: Level: developer
386: .keywords: PC, apply, symmetric, left
388: .seealso: PCApply(), PCApplySymmetricRight()
389: @*/
390: int PCApplySymmetricLeft(PC pc,Vec x,Vec y)
391: {
398: if (!pc->ops->applysymmetricleft) SETERRQ(1,"PC does not have left symmetric apply");
400: if (pc->setupcalled < 2) {
401: PCSetUp(pc);
402: }
404: PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);
405: (*pc->ops->applysymmetricleft)(pc,x,y);
406: PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);
407: return(0);
408: }
410: /*@
411: PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.
413: Collective on PC and Vec
415: Input Parameters:
416: + pc - the preconditioner context
417: - x - input vector
419: Output Parameter:
420: . y - output vector
422: Level: developer
424: Notes:
425: Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
427: .keywords: PC, apply, symmetric, right
429: .seealso: PCApply(), PCApplySymmetricLeft()
430: @*/
431: int PCApplySymmetricRight(PC pc,Vec x,Vec y)
432: {
439: if (!pc->ops->applysymmetricright) SETERRQ(1,"PC does not have left symmetric apply");
441: if (pc->setupcalled < 2) {
442: PCSetUp(pc);
443: }
445: PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);
446: (*pc->ops->applysymmetricright)(pc,x,y);
447: PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);
448: return(0);
449: }
451: /*@
452: PCApplyTranspose - Applies the transpose of preconditioner to a vector.
454: Collective on PC and Vec
456: Input Parameters:
457: + pc - the preconditioner context
458: - x - input vector
460: Output Parameter:
461: . y - output vector
463: Level: developer
465: .keywords: PC, apply, transpose
467: .seealso: PCApplyTranspose(), PCApplyBAorAB(), PCApplyBAorABTranspose()
468: @*/
469: int PCApplyTranspose(PC pc,Vec x,Vec y)
470: {
477: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
478: if (!pc->ops->applytranspose) SETERRQ(PETSC_ERR_SUP," ");
480: if (pc->setupcalled < 2) {
481: PCSetUp(pc);
482: }
484: PetscLogEventBegin(PC_Apply,pc,x,y,0);
485: (*pc->ops->applytranspose)(pc,x,y);
486: PetscLogEventEnd(PC_Apply,pc,x,y,0);
487: return(0);
488: }
490: /*@
491: PCApplyBAorAB - Applies the preconditioner and operator to a vector.
493: Collective on PC and Vec
495: Input Parameters:
496: + pc - the preconditioner context
497: . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
498: . x - input vector
499: - work - work vector
501: Output Parameter:
502: . y - output vector
504: Level: developer
506: .keywords: PC, apply, operator
508: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
509: @*/
510: int PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
511: {
512: int ierr;
519: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
520: if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) {
521: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric");
522: }
523: if (pc->diagonalscale && side == PC_SYMMETRIC) {
524: SETERRQ(1,"Cannot include diagonal scaling with symmetric preconditioner application");
525: }
527: if (pc->setupcalled < 2) {
528: PCSetUp(pc);
529: }
531: if (pc->diagonalscale) {
532: if (pc->ops->applyBA) {
533: Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
534: VecDuplicate(x,&work2);
535: PCDiagonalScaleRight(pc,x,work2);
536: (*pc->ops->applyBA)(pc,side,work2,y,work);
537: /* Remove null space from preconditioned vector y */
538: if (pc->nullsp) {
539: MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
540: }
541: PCDiagonalScaleLeft(pc,y,y);
542: VecDestroy(work2);
543: } else if (side == PC_RIGHT) {
544: PCDiagonalScaleRight(pc,x,y);
545: PCApply(pc,y,work);
546: MatMult(pc->mat,work,y);
547: PCDiagonalScaleLeft(pc,y,y);
548: } else if (side == PC_LEFT) {
549: PCDiagonalScaleRight(pc,x,y);
550: MatMult(pc->mat,y,work);
551: PCApply(pc,work,y);
552: PCDiagonalScaleLeft(pc,y,y);
553: } else if (side == PC_SYMMETRIC) {
554: SETERRQ(1,"Cannot provide diagonal scaling with symmetric application of preconditioner");
555: }
556: } else {
557: if (pc->ops->applyBA) {
558: (*pc->ops->applyBA)(pc,side,x,y,work);
559: /* Remove null space from preconditioned vector y */
560: if (pc->nullsp) {
561: MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
562: }
563: } else if (side == PC_RIGHT) {
564: PCApply(pc,x,work);
565: MatMult(pc->mat,work,y);
566: } else if (side == PC_LEFT) {
567: MatMult(pc->mat,x,work);
568: PCApply(pc,work,y);
569: } else if (side == PC_SYMMETRIC) {
570: /* There's an extra copy here; maybe should provide 2 work vectors instead? */
571: PCApplySymmetricRight(pc,x,work);
572: MatMult(pc->mat,work,y);
573: VecCopy(y,work);
574: PCApplySymmetricLeft(pc,work,y);
575: }
576: }
577: return(0);
578: }
580: /*@
581: PCApplyBAorABTranspose - Applies the transpose of the preconditioner
582: and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
583: not tr(B*A) = tr(A)*tr(B).
585: Collective on PC and Vec
587: Input Parameters:
588: + pc - the preconditioner context
589: . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
590: . x - input vector
591: - work - work vector
593: Output Parameter:
594: . y - output vector
596: Level: developer
598: .keywords: PC, apply, operator, transpose
600: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
601: @*/
602: int PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
603: {
611: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
612: if (pc->ops->applyBAtranspose) {
613: (*pc->ops->applyBAtranspose)(pc,side,x,y,work);
614: return(0);
615: }
616: if (side != PC_LEFT && side != PC_RIGHT) {
617: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");
618: }
620: if (pc->setupcalled < 2) {
621: PCSetUp(pc);
622: }
624: if (side == PC_RIGHT) {
625: PCApplyTranspose(pc,x,work);
626: MatMultTranspose(pc->mat,work,y);
627: } else if (side == PC_LEFT) {
628: MatMultTranspose(pc->mat,x,work);
629: PCApplyTranspose(pc,work,y);
630: }
631: /* add support for PC_SYMMETRIC */
632: return(0); /* actually will never get here */
633: }
635: /* -------------------------------------------------------------------------------*/
637: /*@
638: PCApplyRichardsonExists - Determines whether a particular preconditioner has a
639: built-in fast application of Richardson's method.
641: Not Collective
643: Input Parameter:
644: . pc - the preconditioner
646: Output Parameter:
647: . exists - PETSC_TRUE or PETSC_FALSE
649: Level: developer
651: .keywords: PC, apply, Richardson, exists
653: .seealso: PCApplyRichardson()
654: @*/
655: int PCApplyRichardsonExists(PC pc,PetscTruth *exists)
656: {
660: if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
661: else *exists = PETSC_FALSE;
662: return(0);
663: }
665: /*@
666: PCApplyRichardson - Applies several steps of Richardson iteration with
667: the particular preconditioner. This routine is usually used by the
668: Krylov solvers and not the application code directly.
670: Collective on PC
672: Input Parameters:
673: + pc - the preconditioner context
674: . x - the initial guess
675: . w - one work vector
676: . rtol - relative decrease in residual norm convergence criteria
677: . atol - absolute residual norm convergence criteria
678: . dtol - divergence residual norm increase criteria
679: - its - the number of iterations to apply.
681: Output Parameter:
682: . y - the solution
684: Notes:
685: Most preconditioners do not support this function. Use the command
686: PCApplyRichardsonExists() to determine if one does.
688: Except for the multigrid PC this routine ignores the convergence tolerances
689: and always runs for the number of iterations
690:
691: Level: developer
693: .keywords: PC, apply, Richardson
695: .seealso: PCApplyRichardsonExists()
696: @*/
697: int PCApplyRichardson(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int its)
698: {
706: if (!pc->ops->applyrichardson) SETERRQ(PETSC_ERR_SUP," ");
708: if (pc->setupcalled < 2) {
709: PCSetUp(pc);
710: }
712: (*pc->ops->applyrichardson)(pc,x,y,w,rtol,atol,dtol,its);
713: return(0);
714: }
716: /*
717: a setupcall of 0 indicates never setup,
718: 1 needs to be resetup,
719: 2 does not need any changes.
720: */
721: /*@
722: PCSetUp - Prepares for the use of a preconditioner.
724: Collective on PC
726: Input Parameter:
727: . pc - the preconditioner context
729: Level: developer
731: .keywords: PC, setup
733: .seealso: PCCreate(), PCApply(), PCDestroy()
734: @*/
735: int PCSetUp(PC pc)
736: {
742: if (pc->setupcalled > 1) {
743: PetscLogInfo(pc,"PCSetUp:Setting PC with identical preconditionern");
744: return(0);
745: } else if (pc->setupcalled == 0) {
746: PetscLogInfo(pc,"PCSetUp:Setting up new PCn");
747: } else if (pc->flag == SAME_NONZERO_PATTERN) {
748: PetscLogInfo(pc,"PCSetUp:Setting up PC with same nonzero patternn");
749: } else {
750: PetscLogInfo(pc,"PCSetUp:Setting up PC with different nonzero patternn");
751: }
753: PetscLogEventBegin(PC_SetUp,pc,0,0,0);
754: if (!pc->vec) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Vector must be set first");}
755: if (!pc->mat) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");}
756: if (!pc->type_name) {
757: int size;
759: MPI_Comm_size(pc->comm,&size);
760: if (size == 1) {
761: PCSetType(pc,PCILU);
762: } else {
763: PCSetType(pc,PCBJACOBI);
764: }
765: }
766: if (pc->ops->setup) {
767: (*pc->ops->setup)(pc);
768: }
769: pc->setupcalled = 2;
770: if (pc->nullsp) {
771: PetscTruth test;
772: PetscOptionsHasName(pc->prefix,"-pc_test_null_space",&test);
773: if (test) {
774: MatNullSpaceTest(pc->nullsp,pc->mat);
775: }
776: }
777: PetscLogEventEnd(PC_SetUp,pc,0,0,0);
778: return(0);
779: }
781: /*@
782: PCSetUpOnBlocks - Sets up the preconditioner for each block in
783: the block Jacobi, block Gauss-Seidel, and overlapping Schwarz
784: methods.
786: Collective on PC
788: Input Parameters:
789: . pc - the preconditioner context
791: Level: developer
793: .keywords: PC, setup, blocks
795: .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
796: @*/
797: int PCSetUpOnBlocks(PC pc)
798: {
803: if (!pc->ops->setuponblocks) return(0);
804: PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);
805: (*pc->ops->setuponblocks)(pc);
806: PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);
807: return(0);
808: }
810: /*@
811: PCSetModifySubMatrices - Sets a user-defined routine for modifying the
812: submatrices that arise within certain subdomain-based preconditioners.
813: The basic submatrices are extracted from the preconditioner matrix as
814: usual; the user can then alter these (for example, to set different boundary
815: conditions for each submatrix) before they are used for the local solves.
817: Collective on PC
819: Input Parameters:
820: + pc - the preconditioner context
821: . func - routine for modifying the submatrices
822: - ctx - optional user-defined context (may be null)
824: Calling sequence of func:
825: $ func (PC pc,int nsub,IS *row,IS *col,Mat *submat,void *ctx);
827: . row - an array of index sets that contain the global row numbers
828: that comprise each local submatrix
829: . col - an array of index sets that contain the global column numbers
830: that comprise each local submatrix
831: . submat - array of local submatrices
832: - ctx - optional user-defined context for private data for the
833: user-defined func routine (may be null)
835: Notes:
836: PCSetModifySubMatrices() MUST be called before SLESSetUp() and
837: SLESSolve().
839: A routine set by PCSetModifySubMatrices() is currently called within
840: the block Jacobi (PCBJACOBI) and additive Schwarz (PCASM)
841: preconditioners. All other preconditioners ignore this routine.
843: Level: advanced
845: .keywords: PC, set, modify, submatrices
847: .seealso: PCModifySubMatrices()
848: @*/
849: int PCSetModifySubMatrices(PC pc,int(*func)(PC,int,IS*,IS*,Mat*,void*),void *ctx)
850: {
853: pc->modifysubmatrices = func;
854: pc->modifysubmatricesP = ctx;
855: return(0);
856: }
858: /*@
859: PCModifySubMatrices - Calls an optional user-defined routine within
860: certain preconditioners if one has been set with PCSetModifySubMarices().
862: Collective on PC
864: Input Parameters:
865: + pc - the preconditioner context
866: . nsub - the number of local submatrices
867: . row - an array of index sets that contain the global row numbers
868: that comprise each local submatrix
869: . col - an array of index sets that contain the global column numbers
870: that comprise each local submatrix
871: . submat - array of local submatrices
872: - ctx - optional user-defined context for private data for the
873: user-defined routine (may be null)
875: Output Parameter:
876: . submat - array of local submatrices (the entries of which may
877: have been modified)
879: Notes:
880: The user should NOT generally call this routine, as it will
881: automatically be called within certain preconditioners (currently
882: block Jacobi, additive Schwarz) if set.
884: The basic submatrices are extracted from the preconditioner matrix
885: as usual; the user can then alter these (for example, to set different
886: boundary conditions for each submatrix) before they are used for the
887: local solves.
889: Level: developer
891: .keywords: PC, modify, submatrices
893: .seealso: PCSetModifySubMatrices()
894: @*/
895: int PCModifySubMatrices(PC pc,int nsub,IS *row,IS *col,Mat *submat,void *ctx)
896: {
900: if (!pc->modifysubmatrices) return(0);
901: PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);
902: (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);
903: PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);
904: return(0);
905: }
907: /*@
908: PCSetOperators - Sets the matrix associated with the linear system and
909: a (possibly) different one associated with the preconditioner.
911: Collective on PC and Mat
913: Input Parameters:
914: + pc - the preconditioner context
915: . Amat - the matrix associated with the linear system
916: . Pmat - the matrix to be used in constructing the preconditioner, usually
917: the same as Amat.
918: - flag - flag indicating information about the preconditioner matrix structure
919: during successive linear solves. This flag is ignored the first time a
920: linear system is solved, and thus is irrelevant when solving just one linear
921: system.
923: Notes:
924: The flag can be used to eliminate unnecessary work in the preconditioner
925: during the repeated solution of linear systems of the same size. The
926: available options are
927: + SAME_PRECONDITIONER -
928: Pmat is identical during successive linear solves.
929: This option is intended for folks who are using
930: different Amat and Pmat matrices and wish to reuse the
931: same preconditioner matrix. For example, this option
932: saves work by not recomputing incomplete factorization
933: for ILU/ICC preconditioners.
934: . SAME_NONZERO_PATTERN -
935: Pmat has the same nonzero structure during
936: successive linear solves.
937: - DIFFERENT_NONZERO_PATTERN -
938: Pmat does not have the same nonzero structure.
940: Caution:
941: If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion
942: and does not check the structure of the matrix. If you erroneously
943: claim that the structure is the same when it actually is not, the new
944: preconditioner will not function correctly. Thus, use this optimization
945: feature carefully!
947: If in doubt about whether your preconditioner matrix has changed
948: structure or not, use the flag DIFFERENT_NONZERO_PATTERN.
950: More Notes about Repeated Solution of Linear Systems:
951: PETSc does NOT reset the matrix entries of either Amat or Pmat
952: to zero after a linear solve; the user is completely responsible for
953: matrix assembly. See the routine MatZeroEntries() if desiring to
954: zero all elements of a matrix.
956: Level: developer
958: .keywords: PC, set, operators, matrix, linear system
960: .seealso: PCGetOperators(), MatZeroEntries()
961: @*/
962: int PCSetOperators(PC pc,Mat Amat,Mat Pmat,MatStructure flag)
963: {
964: int ierr;
965: PetscTruth isbjacobi,isrowbs;
972: /*
973: BlockSolve95 cannot use default BJacobi preconditioning
974: */
975: PetscTypeCompare((PetscObject)Amat,MATMPIROWBS,&isrowbs);
976: if (isrowbs) {
977: PetscTypeCompare((PetscObject)pc,PCBJACOBI,&isbjacobi);
978: if (isbjacobi) {
979: PCSetType(pc,PCILU);
980: PetscLogInfo(pc,"PCSetOperators:Switching default PC to PCILU since BS95 doesn't support PCBJACOBIn");
981: }
982: }
984: pc->mat = Amat;
985: pc->pmat = Pmat;
986: if (pc->setupcalled == 2 && flag != SAME_PRECONDITIONER) {
987: pc->setupcalled = 1;
988: }
989: pc->flag = flag;
990: return(0);
991: }
993: /*@C
994: PCGetOperators - Gets the matrix associated with the linear system and
995: possibly a different one associated with the preconditioner.
997: Not collective, though parallel Mats are returned if the PC is parallel
999: Input Parameter:
1000: . pc - the preconditioner context
1002: Output Parameters:
1003: + mat - the matrix associated with the linear system
1004: . pmat - matrix associated with the preconditioner, usually the same
1005: as mat.
1006: - flag - flag indicating information about the preconditioner
1007: matrix structure. See PCSetOperators() for details.
1009: Level: developer
1011: .keywords: PC, get, operators, matrix, linear system
1013: .seealso: PCSetOperators()
1014: @*/
1015: int PCGetOperators(PC pc,Mat *mat,Mat *pmat,MatStructure *flag)
1016: {
1019: if (mat) *mat = pc->mat;
1020: if (pmat) *pmat = pc->pmat;
1021: if (flag) *flag = pc->flag;
1022: return(0);
1023: }
1025: /*@
1026: PCSetVector - Sets a vector associated with the preconditioner.
1028: Collective on PC and Vec
1030: Input Parameters:
1031: + pc - the preconditioner context
1032: - vec - the vector
1034: Notes:
1035: The vector must be set so that the preconditioner knows what type
1036: of vector to allocate if necessary.
1038: Level: developer
1040: .keywords: PC, set, vector
1042: .seealso: PCGetVector()
1044: @*/
1045: int PCSetVector(PC pc,Vec vec)
1046: {
1051: pc->vec = vec;
1052: return(0);
1053: }
1055: /*@
1056: PCGetVector - Gets a vector associated with the preconditioner; if the
1057: vector was not get set it will return a 0 pointer.
1059: Not collective, but vector is shared by all processors that share the PC
1061: Input Parameter:
1062: . pc - the preconditioner context
1064: Output Parameter:
1065: . vec - the vector
1067: Level: developer
1069: .keywords: PC, get, vector
1071: .seealso: PCSetVector()
1073: @*/
1074: int PCGetVector(PC pc,Vec *vec)
1075: {
1078: *vec = pc->vec;
1079: return(0);
1080: }
1082: /*@C
1083: PCGetFactoredMatrix - Gets the factored matrix from the
1084: preconditioner context. This routine is valid only for the LU,
1085: incomplete LU, Cholesky, and incomplete Cholesky methods.
1087: Not Collective on PC though Mat is parallel if PC is parallel
1089: Input Parameters:
1090: . pc - the preconditioner context
1092: Output parameters:
1093: . mat - the factored matrix
1095: Level: advanced
1097: .keywords: PC, get, factored, matrix
1098: @*/
1099: int PCGetFactoredMatrix(PC pc,Mat *mat)
1100: {
1105: if (pc->ops->getfactoredmatrix) {
1106: (*pc->ops->getfactoredmatrix)(pc,mat);
1107: }
1108: return(0);
1109: }
1111: /*@C
1112: PCSetOptionsPrefix - Sets the prefix used for searching for all
1113: PC options in the database.
1115: Collective on PC
1117: Input Parameters:
1118: + pc - the preconditioner context
1119: - prefix - the prefix string to prepend to all PC option requests
1121: Notes:
1122: A hyphen (-) must NOT be given at the beginning of the prefix name.
1123: The first character of all runtime options is AUTOMATICALLY the
1124: hyphen.
1126: Level: advanced
1128: .keywords: PC, set, options, prefix, database
1130: .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1131: @*/
1132: int PCSetOptionsPrefix(PC pc,char *prefix)
1133: {
1138: PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);
1139: return(0);
1140: }
1142: /*@C
1143: PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1144: PC options in the database.
1146: Collective on PC
1148: Input Parameters:
1149: + pc - the preconditioner context
1150: - prefix - the prefix string to prepend to all PC option requests
1152: Notes:
1153: A hyphen (-) must NOT be given at the beginning of the prefix name.
1154: The first character of all runtime options is AUTOMATICALLY the
1155: hyphen.
1157: Level: advanced
1159: .keywords: PC, append, options, prefix, database
1161: .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1162: @*/
1163: int PCAppendOptionsPrefix(PC pc,char *prefix)
1164: {
1169: PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);
1170: return(0);
1171: }
1173: /*@C
1174: PCGetOptionsPrefix - Gets the prefix used for searching for all
1175: PC options in the database.
1177: Not Collective
1179: Input Parameters:
1180: . pc - the preconditioner context
1182: Output Parameters:
1183: . prefix - pointer to the prefix string used, is returned
1185: Notes: On the fortran side, the user should pass in a string 'prifix' of
1186: sufficient length to hold the prefix.
1188: Level: advanced
1190: .keywords: PC, get, options, prefix, database
1192: .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1193: @*/
1194: int PCGetOptionsPrefix(PC pc,char **prefix)
1195: {
1200: PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);
1201: return(0);
1202: }
1204: /*@
1205: PCPreSolve - Optional pre-solve phase, intended for any
1206: preconditioner-specific actions that must be performed before
1207: the iterative solve itself.
1209: Collective on PC
1211: Input Parameters:
1212: + pc - the preconditioner context
1213: - ksp - the Krylov subspace context
1215: Level: developer
1217: Sample of Usage:
1218: .vb
1219: PCPreSolve(pc,ksp);
1220: KSPSolve(ksp,its);
1221: PCPostSolve(pc,ksp);
1222: .ve
1224: Notes:
1225: The pre-solve phase is distinct from the PCSetUp() phase.
1227: SLESSolve() calls this directly, so is rarely called by the user.
1229: .keywords: PC, pre-solve
1231: .seealso: PCPostSolve()
1232: @*/
1233: int PCPreSolve(PC pc,KSP ksp)
1234: {
1236: Vec x,rhs;
1237: Mat A,B;
1242: KSPGetSolution(ksp,&x);
1243: KSPGetRhs(ksp,&rhs);
1244: /*
1245: Scale the system and have the matrices use the scaled form
1246: only if the two matrices are actually the same (and hence
1247: have the same scaling
1248: */
1249: PCGetOperators(pc,&A,&B,PETSC_NULL);
1250: if (A == B) {
1251: MatScaleSystem(pc->mat,x,rhs);
1252: MatUseScaledForm(pc->mat,PETSC_TRUE);
1253: }
1255: if (pc->ops->presolve) {
1256: (*pc->ops->presolve)(pc,ksp,x,rhs);
1257: }
1258: return(0);
1259: }
1261: /*@
1262: PCPostSolve - Optional post-solve phase, intended for any
1263: preconditioner-specific actions that must be performed after
1264: the iterative solve itself.
1266: Collective on PC
1268: Input Parameters:
1269: + pc - the preconditioner context
1270: - ksp - the Krylov subspace context
1272: Sample of Usage:
1273: .vb
1274: PCPreSolve(pc,ksp);
1275: KSPSolve(ksp,its);
1276: PCPostSolve(pc,ksp);
1277: .ve
1279: Note:
1280: SLESSolve() calls this routine directly, so it is rarely called by the user.
1282: Level: developer
1284: .keywords: PC, post-solve
1286: .seealso: PCPreSolve(), SLESSolve()
1287: @*/
1288: int PCPostSolve(PC pc,KSP ksp)
1289: {
1291: Vec x,rhs;
1292: Mat A,B;
1296: KSPGetSolution(ksp,&x);
1297: KSPGetRhs(ksp,&rhs);
1298: if (pc->ops->postsolve) {
1299: (*pc->ops->postsolve)(pc,ksp,x,rhs);
1300: }
1302: /*
1303: Scale the system and have the matrices use the scaled form
1304: only if the two matrices are actually the same (and hence
1305: have the same scaling
1306: */
1307: PCGetOperators(pc,&A,&B,PETSC_NULL);
1308: if (A == B) {
1309: MatUnScaleSystem(pc->mat,x,rhs);
1310: MatUseScaledForm(pc->mat,PETSC_FALSE);
1311: }
1312: return(0);
1313: }
1315: /*@C
1316: PCView - Prints the PC data structure.
1318: Collective on PC
1320: Input Parameters:
1321: + PC - the PC context
1322: - viewer - optional visualization context
1324: Note:
1325: The available visualization contexts include
1326: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
1327: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1328: output where only the first processor opens
1329: the file. All other processors send their
1330: data to the first processor to print.
1332: The user can open an alternative visualization contexts with
1333: PetscViewerASCIIOpen() (output to a specified file).
1335: Level: developer
1337: .keywords: PC, view
1339: .seealso: KSPView(), PetscViewerASCIIOpen()
1340: @*/
1341: int PCView(PC pc,PetscViewer viewer)
1342: {
1343: PCType cstr;
1344: int ierr;
1345: PetscTruth mat_exists,isascii,isstring;
1346: PetscViewerFormat format;
1350: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pc->comm);
1354: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
1355: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
1356: if (isascii) {
1357: PetscViewerGetFormat(viewer,&format);
1358: if (pc->prefix) {
1359: PetscViewerASCIIPrintf(viewer,"PC Object:(%s)n",pc->prefix);
1360: } else {
1361: PetscViewerASCIIPrintf(viewer,"PC Object:n");
1362: }
1363: PCGetType(pc,&cstr);
1364: if (cstr) {
1365: PetscViewerASCIIPrintf(viewer," type: %sn",cstr);
1366: } else {
1367: PetscViewerASCIIPrintf(viewer," type: not yet setn");
1368: }
1369: if (pc->ops->view) {
1370: PetscViewerASCIIPushTab(viewer);
1371: (*pc->ops->view)(pc,viewer);
1372: PetscViewerASCIIPopTab(viewer);
1373: }
1374: PetscObjectExists((PetscObject)pc->mat,&mat_exists);
1375: if (mat_exists) {
1376: PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
1377: if (pc->pmat == pc->mat) {
1378: PetscViewerASCIIPrintf(viewer," linear system matrix = precond matrix:n");
1379: PetscViewerASCIIPushTab(viewer);
1380: MatView(pc->mat,viewer);
1381: PetscViewerASCIIPopTab(viewer);
1382: } else {
1383: PetscObjectExists((PetscObject)pc->pmat,&mat_exists);
1384: if (mat_exists) {
1385: PetscViewerASCIIPrintf(viewer," linear system matrix followed by preconditioner matrix:n");
1386: } else {
1387: PetscViewerASCIIPrintf(viewer," linear system matrix:n");
1388: }
1389: PetscViewerASCIIPushTab(viewer);
1390: MatView(pc->mat,viewer);
1391: if (mat_exists) {MatView(pc->pmat,viewer);}
1392: PetscViewerASCIIPopTab(viewer);
1393: }
1394: PetscViewerPopFormat(viewer);
1395: }
1396: } else if (isstring) {
1397: PCGetType(pc,&cstr);
1398: PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
1399: if (pc->ops->view) {(*pc->ops->view)(pc,viewer);}
1400: } else {
1401: SETERRQ1(1,"Viewer type %s not supported by PC",((PetscObject)viewer)->type_name);
1402: }
1403: return(0);
1404: }
1406: /*MC
1407: PCRegisterDynamic - Adds a method to the preconditioner package.
1409: Synopsis:
1410: int PCRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(PC))
1412: Not collective
1414: Input Parameters:
1415: + name_solver - name of a new user-defined solver
1416: . path - path (either absolute or relative) the library containing this solver
1417: . name_create - name of routine to create method context
1418: - routine_create - routine to create method context
1420: Notes:
1421: PCRegisterDynamic() may be called multiple times to add several user-defined preconditioners.
1423: If dynamic libraries are used, then the fourth input argument (routine_create)
1424: is ignored.
1426: Sample usage:
1427: .vb
1428: PCRegisterDynamic("my_solver","/home/username/my_lib/lib/libO/solaris/mylib",
1429: "MySolverCreate",MySolverCreate);
1430: .ve
1432: Then, your solver can be chosen with the procedural interface via
1433: $ PCSetType(pc,"my_solver")
1434: or at runtime via the option
1435: $ -pc_type my_solver
1437: Level: advanced
1439: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
1440: occuring in pathname will be replaced with appropriate values.
1442: .keywords: PC, register
1444: .seealso: PCRegisterAll(), PCRegisterDestroy(), PCRegister()
1445: M*/
1447: int PCRegister(char *sname,char *path,char *name,int (*function)(PC))
1448: {
1449: int ierr;
1450: char fullname[256];
1454: PetscFListConcat(path,name,fullname);
1455: PetscFListAdd(&PCList,sname,fullname,(void (*)(void))function);
1456: return(0);
1457: }
1459: /*@
1460: PCComputeExplicitOperator - Computes the explicit preconditioned operator.
1462: Collective on PC
1464: Input Parameter:
1465: . pc - the preconditioner object
1467: Output Parameter:
1468: . mat - the explict preconditioned operator
1470: Notes:
1471: This computation is done by applying the operators to columns of the
1472: identity matrix.
1474: Currently, this routine uses a dense matrix format when 1 processor
1475: is used and a sparse format otherwise. This routine is costly in general,
1476: and is recommended for use only with relatively small systems.
1478: Level: advanced
1479:
1480: .keywords: PC, compute, explicit, operator
1482: @*/
1483: int PCComputeExplicitOperator(PC pc,Mat *mat)
1484: {
1485: Vec in,out;
1486: int ierr,i,M,m,size,*rows,start,end;
1487: MPI_Comm comm;
1488: PetscScalar *array,zero = 0.0,one = 1.0;
1494: comm = pc->comm;
1495: MPI_Comm_size(comm,&size);
1497: PCGetVector(pc,&in);
1498: VecDuplicate(in,&out);
1499: VecGetOwnershipRange(in,&start,&end);
1500: VecGetSize(in,&M);
1501: VecGetLocalSize(in,&m);
1502: PetscMalloc((m+1)*sizeof(int),&rows);
1503: for (i=0; i<m; i++) {rows[i] = start + i;}
1505: if (size == 1) {
1506: MatCreateSeqDense(comm,M,M,PETSC_NULL,mat);
1507: } else {
1508: MatCreateMPIAIJ(comm,m,m,M,M,0,0,0,0,mat);
1509: }
1511: for (i=0; i<M; i++) {
1513: VecSet(&zero,in);
1514: VecSetValues(in,1,&i,&one,INSERT_VALUES);
1515: VecAssemblyBegin(in);
1516: VecAssemblyEnd(in);
1518: PCApply(pc,in,out);
1519:
1520: VecGetArray(out,&array);
1521: MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
1522: VecRestoreArray(out,&array);
1524: }
1525: PetscFree(rows);
1526: VecDestroy(out);
1527: MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
1528: MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
1529: return(0);
1530: }