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: Users manual sections:
31: . Section 4.15 Solving Singular Systems
33: .keywords: PC, destroy, null space
35: .seealso: PCCreate(), PCSetUp(), MatNullSpaceCreate(), MatNullSpace
37: @*/
38: int PCNullSpaceAttach(PC pc,MatNullSpace nullsp)
39: {
46: if (pc->nullsp) {
47: MatNullSpaceDestroy(pc->nullsp);
48: }
49: pc->nullsp = nullsp;
50: PetscObjectReference((PetscObject)nullsp);
51: return(0);
52: }
54: /*@C
55: PCDestroy - Destroys PC context that was created with PCCreate().
57: Collective on PC
59: Input Parameter:
60: . pc - the preconditioner context
62: Level: developer
64: .keywords: PC, destroy
66: .seealso: PCCreate(), PCSetUp()
67: @*/
68: int PCDestroy(PC pc)
69: {
74: if (--pc->refct > 0) return(0);
76: /* if memory was published with AMS then destroy it */
77: PetscObjectDepublish(pc);
79: if (pc->ops->destroy) { (*pc->ops->destroy)(pc);}
80: if (pc->nullsp) {MatNullSpaceDestroy(pc->nullsp);}
81: if (pc->diagonalscaleright) {VecDestroy(pc->diagonalscaleright);}
82: if (pc->diagonalscaleleft) {VecDestroy(pc->diagonalscaleleft);}
84: PetscLogObjectDestroy(pc);
85: PetscHeaderDestroy(pc);
86: return(0);
87: }
89: /*@C
90: PCDiagonalScale - Indicates if the preconditioner applies an additional left and right
91: scaling as needed by certain time-stepping codes.
93: Collective on PC
95: Input Parameter:
96: . pc - the preconditioner context
98: Output Parameter:
99: . flag - PETSC_TRUE if it applies the scaling
101: Level: developer
103: Notes: If this returns PETSC_TRUE then the system solved via the Krylov method is
104: $ D M A D^{-1} y = D M b for left preconditioning or
105: $ D A M D^{-1} z = D b for right preconditioning
107: .keywords: PC
109: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScaleSet()
110: @*/
111: int PCDiagonalScale(PC pc,PetscTruth *flag)
112: {
115: *flag = pc->diagonalscale;
116: return(0);
117: }
119: /*@C
120: PCDiagonalScaleSet - Indicates the left scaling to use to apply an additional left and right
121: scaling as needed by certain time-stepping codes.
123: Collective on PC
125: Input Parameters:
126: + pc - the preconditioner context
127: - s - scaling vector
129: Level: intermediate
131: Notes: The system solved via the Krylov method is
132: $ D M A D^{-1} y = D M b for left preconditioning or
133: $ D A M D^{-1} z = D b for right preconditioning
135: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
137: .keywords: PC
139: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScale()
140: @*/
141: int PCDiagonalScaleSet(PC pc,Vec s)
142: {
148: pc->diagonalscale = PETSC_TRUE;
149: if (pc->diagonalscaleleft) {
150: VecDestroy(pc->diagonalscaleleft);
151: }
152: pc->diagonalscaleleft = s;
153: ierr = PetscObjectReference((PetscObject)s);
154: if (!pc->diagonalscaleright) {
155: VecDuplicate(s,&pc->diagonalscaleright);
156: }
157: VecCopy(s,pc->diagonalscaleright);
158: VecReciprocal(pc->diagonalscaleright);
159: return(0);
160: }
162: /*@C
163: PCDiagonalScaleLeft - Indicates the left scaling to use to apply an additional left and right
164: scaling as needed by certain time-stepping codes.
166: Collective on PC
168: Input Parameters:
169: + pc - the preconditioner context
170: . in - input vector
171: + out - scaled vector (maybe the same as in)
173: Level: intermediate
175: Notes: The system solved via the Krylov method is
176: $ D M A D^{-1} y = D M b for left preconditioning or
177: $ D A M D^{-1} z = D b for right preconditioning
179: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
181: If diagonal scaling is turned off and in is not out then in is copied to out
183: .keywords: PC
185: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
186: @*/
187: int PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
188: {
195: if (pc->diagonalscale) {
196: VecPointwiseMult(pc->diagonalscaleleft,in,out);
197: } else if (in != out) {
198: VecCopy(in,out);
199: }
200: return(0);
201: }
203: /*@C
204: PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.
206: Collective on PC
208: Input Parameters:
209: + pc - the preconditioner context
210: . in - input vector
211: + out - scaled vector (maybe the same as in)
213: Level: intermediate
215: Notes: The system solved via the Krylov method is
216: $ D M A D^{-1} y = D M b for left preconditioning or
217: $ D A M D^{-1} z = D b for right preconditioning
219: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
221: If diagonal scaling is turned off and in is not out then in is copied to out
223: .keywords: PC
225: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
226: @*/
227: int PCDiagonalScaleRight(PC pc,Vec in,Vec out)
228: {
235: if (pc->diagonalscale) {
236: VecPointwiseMult(pc->diagonalscaleright,in,out);
237: } else if (in != out) {
238: VecCopy(in,out);
239: }
240: return(0);
241: }
243: static int PCPublish_Petsc(PetscObject obj)
244: {
245: #if defined(PETSC_HAVE_AMS)
246: PC v = (PC) obj;
247: int ierr;
248: #endif
252: #if defined(PETSC_HAVE_AMS)
253: /* if it is already published then return */
254: if (v->amem >=0) return(0);
256: PetscObjectPublishBaseBegin(obj);
257: PetscObjectPublishBaseEnd(obj);
258: #endif
260: return(0);
261: }
263: /*@C
264: PCCreate - Creates a preconditioner context.
266: Collective on MPI_Comm
268: Input Parameter:
269: . comm - MPI communicator
271: Output Parameter:
272: . pc - location to put the preconditioner context
274: Notes:
275: The default preconditioner on one processor is PCILU with 0 fill on more
276: then one it is PCBJACOBI with ILU() on each processor.
278: Level: developer
280: .keywords: PC, create, context
282: .seealso: PCSetUp(), PCApply(), PCDestroy()
283: @*/
284: int PCCreate(MPI_Comm comm,PC *newpc)
285: {
286: PC pc;
291: *newpc = 0;
292: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
293: SLESInitializePackage(PETSC_NULL);
294: #endif
296: PetscHeaderCreate(pc,_p_PC,struct _PCOps,PC_COOKIE,-1,"PC",comm,PCDestroy,PCView);
297: PetscLogObjectCreate(pc);
298: pc->bops->publish = PCPublish_Petsc;
299: pc->vec = 0;
300: pc->mat = 0;
301: pc->setupcalled = 0;
302: pc->nullsp = 0;
303: pc->data = 0;
304: pc->diagonalscale = PETSC_FALSE;
305: pc->diagonalscaleleft = 0;
306: pc->diagonalscaleright = 0;
308: pc->ops->destroy = 0;
309: pc->ops->apply = 0;
310: pc->ops->applytranspose = 0;
311: pc->ops->applyBA = 0;
312: pc->ops->applyBAtranspose = 0;
313: pc->ops->applyrichardson = 0;
314: pc->ops->view = 0;
315: pc->ops->getfactoredmatrix = 0;
316: pc->ops->applysymmetricright = 0;
317: pc->ops->applysymmetricleft = 0;
318: pc->ops->setuponblocks = 0;
320: pc->modifysubmatrices = 0;
321: pc->modifysubmatricesP = 0;
322: *newpc = pc;
323: PetscPublishAll(pc);
324: return(0);
326: }
328: /* -------------------------------------------------------------------------------*/
330: /*@
331: PCApply - Applies the preconditioner to a vector.
333: Collective on PC and Vec
335: Input Parameters:
336: + pc - the preconditioner context
337: - x - input vector
339: Output Parameter:
340: . y - output vector
342: Level: developer
344: .keywords: PC, apply
346: .seealso: PCApplyTranspose(), PCApplyBAorAB()
347: @*/
348: int PCApply(PC pc,Vec x,Vec y)
349: {
350: int ierr;
356: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
358: if (pc->setupcalled < 2) {
359: PCSetUp(pc);
360: }
362: PetscLogEventBegin(PC_Apply,pc,x,y,0);
363: (*pc->ops->apply)(pc,x,y);
364: PetscLogEventEnd(PC_Apply,pc,x,y,0);
366: /* Remove null space from preconditioned vector y */
367: if (pc->nullsp) {
368: MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
369: }
370: return(0);
371: }
373: /*@
374: PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.
376: Collective on PC and Vec
378: Input Parameters:
379: + pc - the preconditioner context
380: - x - input vector
382: Output Parameter:
383: . y - output vector
385: Notes:
386: Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
388: Level: developer
390: .keywords: PC, apply, symmetric, left
392: .seealso: PCApply(), PCApplySymmetricRight()
393: @*/
394: int PCApplySymmetricLeft(PC pc,Vec x,Vec y)
395: {
402: if (!pc->ops->applysymmetricleft) SETERRQ(1,"PC does not have left symmetric apply");
404: if (pc->setupcalled < 2) {
405: PCSetUp(pc);
406: }
408: PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);
409: (*pc->ops->applysymmetricleft)(pc,x,y);
410: PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);
411: return(0);
412: }
414: /*@
415: PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.
417: Collective on PC and Vec
419: Input Parameters:
420: + pc - the preconditioner context
421: - x - input vector
423: Output Parameter:
424: . y - output vector
426: Level: developer
428: Notes:
429: Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
431: .keywords: PC, apply, symmetric, right
433: .seealso: PCApply(), PCApplySymmetricLeft()
434: @*/
435: int PCApplySymmetricRight(PC pc,Vec x,Vec y)
436: {
443: if (!pc->ops->applysymmetricright) SETERRQ(1,"PC does not have left symmetric apply");
445: if (pc->setupcalled < 2) {
446: PCSetUp(pc);
447: }
449: PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);
450: (*pc->ops->applysymmetricright)(pc,x,y);
451: PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);
452: return(0);
453: }
455: /*@
456: PCApplyTranspose - Applies the transpose of preconditioner to a vector.
458: Collective on PC and Vec
460: Input Parameters:
461: + pc - the preconditioner context
462: - x - input vector
464: Output Parameter:
465: . y - output vector
467: Level: developer
469: .keywords: PC, apply, transpose
471: .seealso: PCApplyTranspose(), PCApplyBAorAB(), PCApplyBAorABTranspose()
472: @*/
473: int PCApplyTranspose(PC pc,Vec x,Vec y)
474: {
481: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
482: if (!pc->ops->applytranspose) SETERRQ(PETSC_ERR_SUP," ");
484: if (pc->setupcalled < 2) {
485: PCSetUp(pc);
486: }
488: PetscLogEventBegin(PC_Apply,pc,x,y,0);
489: (*pc->ops->applytranspose)(pc,x,y);
490: PetscLogEventEnd(PC_Apply,pc,x,y,0);
491: return(0);
492: }
494: /*@
495: PCApplyBAorAB - Applies the preconditioner and operator to a vector.
497: Collective on PC and Vec
499: Input Parameters:
500: + pc - the preconditioner context
501: . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
502: . x - input vector
503: - work - work vector
505: Output Parameter:
506: . y - output vector
508: Level: developer
510: .keywords: PC, apply, operator
512: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
513: @*/
514: int PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
515: {
516: int ierr;
523: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
524: if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) {
525: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric");
526: }
527: if (pc->diagonalscale && side == PC_SYMMETRIC) {
528: SETERRQ(1,"Cannot include diagonal scaling with symmetric preconditioner application");
529: }
531: if (pc->setupcalled < 2) {
532: PCSetUp(pc);
533: }
535: if (pc->diagonalscale) {
536: if (pc->ops->applyBA) {
537: Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
538: VecDuplicate(x,&work2);
539: PCDiagonalScaleRight(pc,x,work2);
540: (*pc->ops->applyBA)(pc,side,work2,y,work);
541: /* Remove null space from preconditioned vector y */
542: if (pc->nullsp) {
543: MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
544: }
545: PCDiagonalScaleLeft(pc,y,y);
546: VecDestroy(work2);
547: } else if (side == PC_RIGHT) {
548: PCDiagonalScaleRight(pc,x,y);
549: PCApply(pc,y,work);
550: MatMult(pc->mat,work,y);
551: PCDiagonalScaleLeft(pc,y,y);
552: } else if (side == PC_LEFT) {
553: PCDiagonalScaleRight(pc,x,y);
554: MatMult(pc->mat,y,work);
555: PCApply(pc,work,y);
556: PCDiagonalScaleLeft(pc,y,y);
557: } else if (side == PC_SYMMETRIC) {
558: SETERRQ(1,"Cannot provide diagonal scaling with symmetric application of preconditioner");
559: }
560: } else {
561: if (pc->ops->applyBA) {
562: (*pc->ops->applyBA)(pc,side,x,y,work);
563: /* Remove null space from preconditioned vector y */
564: if (pc->nullsp) {
565: MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
566: }
567: } else if (side == PC_RIGHT) {
568: PCApply(pc,x,work);
569: MatMult(pc->mat,work,y);
570: } else if (side == PC_LEFT) {
571: MatMult(pc->mat,x,work);
572: PCApply(pc,work,y);
573: } else if (side == PC_SYMMETRIC) {
574: /* There's an extra copy here; maybe should provide 2 work vectors instead? */
575: PCApplySymmetricRight(pc,x,work);
576: MatMult(pc->mat,work,y);
577: VecCopy(y,work);
578: PCApplySymmetricLeft(pc,work,y);
579: }
580: }
581: return(0);
582: }
584: /*@
585: PCApplyBAorABTranspose - Applies the transpose of the preconditioner
586: and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
587: not tr(B*A) = tr(A)*tr(B).
589: Collective on PC and Vec
591: Input Parameters:
592: + pc - the preconditioner context
593: . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
594: . x - input vector
595: - work - work vector
597: Output Parameter:
598: . y - output vector
600: Level: developer
602: .keywords: PC, apply, operator, transpose
604: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
605: @*/
606: int PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
607: {
615: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
616: if (pc->ops->applyBAtranspose) {
617: (*pc->ops->applyBAtranspose)(pc,side,x,y,work);
618: return(0);
619: }
620: if (side != PC_LEFT && side != PC_RIGHT) {
621: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");
622: }
624: if (pc->setupcalled < 2) {
625: PCSetUp(pc);
626: }
628: if (side == PC_RIGHT) {
629: PCApplyTranspose(pc,x,work);
630: MatMultTranspose(pc->mat,work,y);
631: } else if (side == PC_LEFT) {
632: MatMultTranspose(pc->mat,x,work);
633: PCApplyTranspose(pc,work,y);
634: }
635: /* add support for PC_SYMMETRIC */
636: return(0); /* actually will never get here */
637: }
639: /* -------------------------------------------------------------------------------*/
641: /*@
642: PCApplyRichardsonExists - Determines whether a particular preconditioner has a
643: built-in fast application of Richardson's method.
645: Not Collective
647: Input Parameter:
648: . pc - the preconditioner
650: Output Parameter:
651: . exists - PETSC_TRUE or PETSC_FALSE
653: Level: developer
655: .keywords: PC, apply, Richardson, exists
657: .seealso: PCApplyRichardson()
658: @*/
659: int PCApplyRichardsonExists(PC pc,PetscTruth *exists)
660: {
664: if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
665: else *exists = PETSC_FALSE;
666: return(0);
667: }
669: /*@
670: PCApplyRichardson - Applies several steps of Richardson iteration with
671: the particular preconditioner. This routine is usually used by the
672: Krylov solvers and not the application code directly.
674: Collective on PC
676: Input Parameters:
677: + pc - the preconditioner context
678: . x - the initial guess
679: . w - one work vector
680: . rtol - relative decrease in residual norm convergence criteria
681: . atol - absolute residual norm convergence criteria
682: . dtol - divergence residual norm increase criteria
683: - its - the number of iterations to apply.
685: Output Parameter:
686: . y - the solution
688: Notes:
689: Most preconditioners do not support this function. Use the command
690: PCApplyRichardsonExists() to determine if one does.
692: Except for the multigrid PC this routine ignores the convergence tolerances
693: and always runs for the number of iterations
694:
695: Level: developer
697: .keywords: PC, apply, Richardson
699: .seealso: PCApplyRichardsonExists()
700: @*/
701: int PCApplyRichardson(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int its)
702: {
710: if (!pc->ops->applyrichardson) SETERRQ(PETSC_ERR_SUP," ");
712: if (pc->setupcalled < 2) {
713: PCSetUp(pc);
714: }
716: (*pc->ops->applyrichardson)(pc,x,y,w,rtol,atol,dtol,its);
717: return(0);
718: }
720: /*
721: a setupcall of 0 indicates never setup,
722: 1 needs to be resetup,
723: 2 does not need any changes.
724: */
725: /*@
726: PCSetUp - Prepares for the use of a preconditioner.
728: Collective on PC
730: Input Parameter:
731: . pc - the preconditioner context
733: Level: developer
735: .keywords: PC, setup
737: .seealso: PCCreate(), PCApply(), PCDestroy()
738: @*/
739: int PCSetUp(PC pc)
740: {
746: if (pc->setupcalled > 1) {
747: PetscLogInfo(pc,"PCSetUp:Setting PC with identical preconditionern");
748: return(0);
749: } else if (pc->setupcalled == 0) {
750: PetscLogInfo(pc,"PCSetUp:Setting up new PCn");
751: } else if (pc->flag == SAME_NONZERO_PATTERN) {
752: PetscLogInfo(pc,"PCSetUp:Setting up PC with same nonzero patternn");
753: } else {
754: PetscLogInfo(pc,"PCSetUp:Setting up PC with different nonzero patternn");
755: }
757: PetscLogEventBegin(PC_SetUp,pc,0,0,0);
758: if (!pc->vec) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Vector must be set first");}
759: if (!pc->mat) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");}
760: if (!pc->type_name) {
761: int size;
763: MPI_Comm_size(pc->comm,&size);
764: if (size == 1) {
765: PCSetType(pc,PCILU);
766: } else {
767: PCSetType(pc,PCBJACOBI);
768: }
769: }
770: if (pc->ops->setup) {
771: (*pc->ops->setup)(pc);
772: }
773: pc->setupcalled = 2;
774: if (pc->nullsp) {
775: PetscTruth test;
776: PetscOptionsHasName(pc->prefix,"-pc_test_null_space",&test);
777: if (test) {
778: MatNullSpaceTest(pc->nullsp,pc->mat);
779: }
780: }
781: PetscLogEventEnd(PC_SetUp,pc,0,0,0);
782: return(0);
783: }
785: /*@
786: PCSetUpOnBlocks - Sets up the preconditioner for each block in
787: the block Jacobi, block Gauss-Seidel, and overlapping Schwarz
788: methods.
790: Collective on PC
792: Input Parameters:
793: . pc - the preconditioner context
795: Level: developer
797: .keywords: PC, setup, blocks
799: .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
800: @*/
801: int PCSetUpOnBlocks(PC pc)
802: {
807: if (!pc->ops->setuponblocks) return(0);
808: PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);
809: (*pc->ops->setuponblocks)(pc);
810: PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);
811: return(0);
812: }
814: /*@
815: PCSetModifySubMatrices - Sets a user-defined routine for modifying the
816: submatrices that arise within certain subdomain-based preconditioners.
817: The basic submatrices are extracted from the preconditioner matrix as
818: usual; the user can then alter these (for example, to set different boundary
819: conditions for each submatrix) before they are used for the local solves.
821: Collective on PC
823: Input Parameters:
824: + pc - the preconditioner context
825: . func - routine for modifying the submatrices
826: - ctx - optional user-defined context (may be null)
828: Calling sequence of func:
829: $ func (PC pc,int nsub,IS *row,IS *col,Mat *submat,void *ctx);
831: . row - an array of index sets that contain the global row numbers
832: that comprise each local submatrix
833: . col - an array of index sets that contain the global column numbers
834: that comprise each local submatrix
835: . submat - array of local submatrices
836: - ctx - optional user-defined context for private data for the
837: user-defined func routine (may be null)
839: Notes:
840: PCSetModifySubMatrices() MUST be called before SLESSetUp() and
841: SLESSolve().
843: A routine set by PCSetModifySubMatrices() is currently called within
844: the block Jacobi (PCBJACOBI) and additive Schwarz (PCASM)
845: preconditioners. All other preconditioners ignore this routine.
847: Level: advanced
849: .keywords: PC, set, modify, submatrices
851: .seealso: PCModifySubMatrices()
852: @*/
853: int PCSetModifySubMatrices(PC pc,int(*func)(PC,int,IS*,IS*,Mat*,void*),void *ctx)
854: {
857: pc->modifysubmatrices = func;
858: pc->modifysubmatricesP = ctx;
859: return(0);
860: }
862: /*@
863: PCModifySubMatrices - Calls an optional user-defined routine within
864: certain preconditioners if one has been set with PCSetModifySubMarices().
866: Collective on PC
868: Input Parameters:
869: + pc - the preconditioner context
870: . nsub - the number of local submatrices
871: . row - an array of index sets that contain the global row numbers
872: that comprise each local submatrix
873: . col - an array of index sets that contain the global column numbers
874: that comprise each local submatrix
875: . submat - array of local submatrices
876: - ctx - optional user-defined context for private data for the
877: user-defined routine (may be null)
879: Output Parameter:
880: . submat - array of local submatrices (the entries of which may
881: have been modified)
883: Notes:
884: The user should NOT generally call this routine, as it will
885: automatically be called within certain preconditioners (currently
886: block Jacobi, additive Schwarz) if set.
888: The basic submatrices are extracted from the preconditioner matrix
889: as usual; the user can then alter these (for example, to set different
890: boundary conditions for each submatrix) before they are used for the
891: local solves.
893: Level: developer
895: .keywords: PC, modify, submatrices
897: .seealso: PCSetModifySubMatrices()
898: @*/
899: int PCModifySubMatrices(PC pc,int nsub,IS *row,IS *col,Mat *submat,void *ctx)
900: {
904: if (!pc->modifysubmatrices) return(0);
905: PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);
906: (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);
907: PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);
908: return(0);
909: }
911: /*@
912: PCSetOperators - Sets the matrix associated with the linear system and
913: a (possibly) different one associated with the preconditioner.
915: Collective on PC and Mat
917: Input Parameters:
918: + pc - the preconditioner context
919: . Amat - the matrix associated with the linear system
920: . Pmat - the matrix to be used in constructing the preconditioner, usually
921: the same as Amat.
922: - flag - flag indicating information about the preconditioner matrix structure
923: during successive linear solves. This flag is ignored the first time a
924: linear system is solved, and thus is irrelevant when solving just one linear
925: system.
927: Notes:
928: The flag can be used to eliminate unnecessary work in the preconditioner
929: during the repeated solution of linear systems of the same size. The
930: available options are
931: + SAME_PRECONDITIONER -
932: Pmat is identical during successive linear solves.
933: This option is intended for folks who are using
934: different Amat and Pmat matrices and wish to reuse the
935: same preconditioner matrix. For example, this option
936: saves work by not recomputing incomplete factorization
937: for ILU/ICC preconditioners.
938: . SAME_NONZERO_PATTERN -
939: Pmat has the same nonzero structure during
940: successive linear solves.
941: - DIFFERENT_NONZERO_PATTERN -
942: Pmat does not have the same nonzero structure.
944: Caution:
945: If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion
946: and does not check the structure of the matrix. If you erroneously
947: claim that the structure is the same when it actually is not, the new
948: preconditioner will not function correctly. Thus, use this optimization
949: feature carefully!
951: If in doubt about whether your preconditioner matrix has changed
952: structure or not, use the flag DIFFERENT_NONZERO_PATTERN.
954: More Notes about Repeated Solution of Linear Systems:
955: PETSc does NOT reset the matrix entries of either Amat or Pmat
956: to zero after a linear solve; the user is completely responsible for
957: matrix assembly. See the routine MatZeroEntries() if desiring to
958: zero all elements of a matrix.
960: Level: developer
962: .keywords: PC, set, operators, matrix, linear system
964: .seealso: PCGetOperators(), MatZeroEntries()
965: @*/
966: int PCSetOperators(PC pc,Mat Amat,Mat Pmat,MatStructure flag)
967: {
968: int ierr;
969: PetscTruth isbjacobi,isrowbs;
976: /*
977: BlockSolve95 cannot use default BJacobi preconditioning
978: */
979: PetscTypeCompare((PetscObject)Amat,MATMPIROWBS,&isrowbs);
980: if (isrowbs) {
981: PetscTypeCompare((PetscObject)pc,PCBJACOBI,&isbjacobi);
982: if (isbjacobi) {
983: PCSetType(pc,PCILU);
984: PetscLogInfo(pc,"PCSetOperators:Switching default PC to PCILU since BS95 doesn't support PCBJACOBIn");
985: }
986: }
988: pc->mat = Amat;
989: pc->pmat = Pmat;
990: if (pc->setupcalled == 2 && flag != SAME_PRECONDITIONER) {
991: pc->setupcalled = 1;
992: }
993: pc->flag = flag;
994: return(0);
995: }
997: /*@C
998: PCGetOperators - Gets the matrix associated with the linear system and
999: possibly a different one associated with the preconditioner.
1001: Not collective, though parallel Mats are returned if the PC is parallel
1003: Input Parameter:
1004: . pc - the preconditioner context
1006: Output Parameters:
1007: + mat - the matrix associated with the linear system
1008: . pmat - matrix associated with the preconditioner, usually the same
1009: as mat.
1010: - flag - flag indicating information about the preconditioner
1011: matrix structure. See PCSetOperators() for details.
1013: Level: developer
1015: .keywords: PC, get, operators, matrix, linear system
1017: .seealso: PCSetOperators()
1018: @*/
1019: int PCGetOperators(PC pc,Mat *mat,Mat *pmat,MatStructure *flag)
1020: {
1023: if (mat) *mat = pc->mat;
1024: if (pmat) *pmat = pc->pmat;
1025: if (flag) *flag = pc->flag;
1026: return(0);
1027: }
1029: /*@
1030: PCSetVector - Sets a vector associated with the preconditioner.
1032: Collective on PC and Vec
1034: Input Parameters:
1035: + pc - the preconditioner context
1036: - vec - the vector
1038: Notes:
1039: The vector must be set so that the preconditioner knows what type
1040: of vector to allocate if necessary.
1042: Level: developer
1044: .keywords: PC, set, vector
1046: .seealso: PCGetVector()
1048: @*/
1049: int PCSetVector(PC pc,Vec vec)
1050: {
1055: pc->vec = vec;
1056: return(0);
1057: }
1059: /*@
1060: PCGetVector - Gets a vector associated with the preconditioner; if the
1061: vector was not get set it will return a 0 pointer.
1063: Not collective, but vector is shared by all processors that share the PC
1065: Input Parameter:
1066: . pc - the preconditioner context
1068: Output Parameter:
1069: . vec - the vector
1071: Level: developer
1073: .keywords: PC, get, vector
1075: .seealso: PCSetVector()
1077: @*/
1078: int PCGetVector(PC pc,Vec *vec)
1079: {
1082: *vec = pc->vec;
1083: return(0);
1084: }
1086: /*@C
1087: PCGetFactoredMatrix - Gets the factored matrix from the
1088: preconditioner context. This routine is valid only for the LU,
1089: incomplete LU, Cholesky, and incomplete Cholesky methods.
1091: Not Collective on PC though Mat is parallel if PC is parallel
1093: Input Parameters:
1094: . pc - the preconditioner context
1096: Output parameters:
1097: . mat - the factored matrix
1099: Level: advanced
1101: .keywords: PC, get, factored, matrix
1102: @*/
1103: int PCGetFactoredMatrix(PC pc,Mat *mat)
1104: {
1109: if (pc->ops->getfactoredmatrix) {
1110: (*pc->ops->getfactoredmatrix)(pc,mat);
1111: }
1112: return(0);
1113: }
1115: /*@C
1116: PCSetOptionsPrefix - Sets the prefix used for searching for all
1117: PC options in the database.
1119: Collective on PC
1121: Input Parameters:
1122: + pc - the preconditioner context
1123: - prefix - the prefix string to prepend to all PC option requests
1125: Notes:
1126: A hyphen (-) must NOT be given at the beginning of the prefix name.
1127: The first character of all runtime options is AUTOMATICALLY the
1128: hyphen.
1130: Level: advanced
1132: .keywords: PC, set, options, prefix, database
1134: .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1135: @*/
1136: int PCSetOptionsPrefix(PC pc,char *prefix)
1137: {
1142: PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);
1143: return(0);
1144: }
1146: /*@C
1147: PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1148: PC options in the database.
1150: Collective on PC
1152: Input Parameters:
1153: + pc - the preconditioner context
1154: - prefix - the prefix string to prepend to all PC option requests
1156: Notes:
1157: A hyphen (-) must NOT be given at the beginning of the prefix name.
1158: The first character of all runtime options is AUTOMATICALLY the
1159: hyphen.
1161: Level: advanced
1163: .keywords: PC, append, options, prefix, database
1165: .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1166: @*/
1167: int PCAppendOptionsPrefix(PC pc,char *prefix)
1168: {
1173: PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);
1174: return(0);
1175: }
1177: /*@C
1178: PCGetOptionsPrefix - Gets the prefix used for searching for all
1179: PC options in the database.
1181: Not Collective
1183: Input Parameters:
1184: . pc - the preconditioner context
1186: Output Parameters:
1187: . prefix - pointer to the prefix string used, is returned
1189: Notes: On the fortran side, the user should pass in a string 'prifix' of
1190: sufficient length to hold the prefix.
1192: Level: advanced
1194: .keywords: PC, get, options, prefix, database
1196: .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1197: @*/
1198: int PCGetOptionsPrefix(PC pc,char **prefix)
1199: {
1204: PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);
1205: return(0);
1206: }
1208: /*@
1209: PCPreSolve - Optional pre-solve phase, intended for any
1210: preconditioner-specific actions that must be performed before
1211: the iterative solve itself.
1213: Collective on PC
1215: Input Parameters:
1216: + pc - the preconditioner context
1217: - ksp - the Krylov subspace context
1219: Level: developer
1221: Sample of Usage:
1222: .vb
1223: PCPreSolve(pc,ksp);
1224: KSPSolve(ksp,its);
1225: PCPostSolve(pc,ksp);
1226: .ve
1228: Notes:
1229: The pre-solve phase is distinct from the PCSetUp() phase.
1231: SLESSolve() calls this directly, so is rarely called by the user.
1233: .keywords: PC, pre-solve
1235: .seealso: PCPostSolve()
1236: @*/
1237: int PCPreSolve(PC pc,KSP ksp)
1238: {
1240: Vec x,rhs;
1241: Mat A,B;
1246: KSPGetSolution(ksp,&x);
1247: KSPGetRhs(ksp,&rhs);
1248: /*
1249: Scale the system and have the matrices use the scaled form
1250: only if the two matrices are actually the same (and hence
1251: have the same scaling
1252: */
1253: PCGetOperators(pc,&A,&B,PETSC_NULL);
1254: if (A == B) {
1255: MatScaleSystem(pc->mat,x,rhs);
1256: MatUseScaledForm(pc->mat,PETSC_TRUE);
1257: }
1259: if (pc->ops->presolve) {
1260: (*pc->ops->presolve)(pc,ksp,x,rhs);
1261: }
1262: return(0);
1263: }
1265: /*@
1266: PCPostSolve - Optional post-solve phase, intended for any
1267: preconditioner-specific actions that must be performed after
1268: the iterative solve itself.
1270: Collective on PC
1272: Input Parameters:
1273: + pc - the preconditioner context
1274: - ksp - the Krylov subspace context
1276: Sample of Usage:
1277: .vb
1278: PCPreSolve(pc,ksp);
1279: KSPSolve(ksp,its);
1280: PCPostSolve(pc,ksp);
1281: .ve
1283: Note:
1284: SLESSolve() calls this routine directly, so it is rarely called by the user.
1286: Level: developer
1288: .keywords: PC, post-solve
1290: .seealso: PCPreSolve(), SLESSolve()
1291: @*/
1292: int PCPostSolve(PC pc,KSP ksp)
1293: {
1295: Vec x,rhs;
1296: Mat A,B;
1300: KSPGetSolution(ksp,&x);
1301: KSPGetRhs(ksp,&rhs);
1302: if (pc->ops->postsolve) {
1303: (*pc->ops->postsolve)(pc,ksp,x,rhs);
1304: }
1306: /*
1307: Scale the system and have the matrices use the scaled form
1308: only if the two matrices are actually the same (and hence
1309: have the same scaling
1310: */
1311: PCGetOperators(pc,&A,&B,PETSC_NULL);
1312: if (A == B) {
1313: MatUnScaleSystem(pc->mat,x,rhs);
1314: MatUseScaledForm(pc->mat,PETSC_FALSE);
1315: }
1316: return(0);
1317: }
1319: /*@C
1320: PCView - Prints the PC data structure.
1322: Collective on PC
1324: Input Parameters:
1325: + PC - the PC context
1326: - viewer - optional visualization context
1328: Note:
1329: The available visualization contexts include
1330: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
1331: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1332: output where only the first processor opens
1333: the file. All other processors send their
1334: data to the first processor to print.
1336: The user can open an alternative visualization contexts with
1337: PetscViewerASCIIOpen() (output to a specified file).
1339: Level: developer
1341: .keywords: PC, view
1343: .seealso: KSPView(), PetscViewerASCIIOpen()
1344: @*/
1345: int PCView(PC pc,PetscViewer viewer)
1346: {
1347: PCType cstr;
1348: int ierr;
1349: PetscTruth mat_exists,isascii,isstring;
1350: PetscViewerFormat format;
1354: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pc->comm);
1358: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
1359: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
1360: if (isascii) {
1361: PetscViewerGetFormat(viewer,&format);
1362: if (pc->prefix) {
1363: PetscViewerASCIIPrintf(viewer,"PC Object:(%s)n",pc->prefix);
1364: } else {
1365: PetscViewerASCIIPrintf(viewer,"PC Object:n");
1366: }
1367: PCGetType(pc,&cstr);
1368: if (cstr) {
1369: PetscViewerASCIIPrintf(viewer," type: %sn",cstr);
1370: } else {
1371: PetscViewerASCIIPrintf(viewer," type: not yet setn");
1372: }
1373: if (pc->ops->view) {
1374: PetscViewerASCIIPushTab(viewer);
1375: (*pc->ops->view)(pc,viewer);
1376: PetscViewerASCIIPopTab(viewer);
1377: }
1378: PetscObjectExists((PetscObject)pc->mat,&mat_exists);
1379: if (mat_exists) {
1380: PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
1381: if (pc->pmat == pc->mat) {
1382: PetscViewerASCIIPrintf(viewer," linear system matrix = precond matrix:n");
1383: PetscViewerASCIIPushTab(viewer);
1384: MatView(pc->mat,viewer);
1385: PetscViewerASCIIPopTab(viewer);
1386: } else {
1387: PetscObjectExists((PetscObject)pc->pmat,&mat_exists);
1388: if (mat_exists) {
1389: PetscViewerASCIIPrintf(viewer," linear system matrix followed by preconditioner matrix:n");
1390: } else {
1391: PetscViewerASCIIPrintf(viewer," linear system matrix:n");
1392: }
1393: PetscViewerASCIIPushTab(viewer);
1394: MatView(pc->mat,viewer);
1395: if (mat_exists) {MatView(pc->pmat,viewer);}
1396: PetscViewerASCIIPopTab(viewer);
1397: }
1398: PetscViewerPopFormat(viewer);
1399: }
1400: } else if (isstring) {
1401: PCGetType(pc,&cstr);
1402: PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
1403: if (pc->ops->view) {(*pc->ops->view)(pc,viewer);}
1404: } else {
1405: SETERRQ1(1,"Viewer type %s not supported by PC",((PetscObject)viewer)->type_name);
1406: }
1407: return(0);
1408: }
1410: /*MC
1411: PCRegisterDynamic - Adds a method to the preconditioner package.
1413: Synopsis:
1414: int PCRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(PC))
1416: Not collective
1418: Input Parameters:
1419: + name_solver - name of a new user-defined solver
1420: . path - path (either absolute or relative) the library containing this solver
1421: . name_create - name of routine to create method context
1422: - routine_create - routine to create method context
1424: Notes:
1425: PCRegisterDynamic() may be called multiple times to add several user-defined preconditioners.
1427: If dynamic libraries are used, then the fourth input argument (routine_create)
1428: is ignored.
1430: Sample usage:
1431: .vb
1432: PCRegisterDynamic("my_solver","/home/username/my_lib/lib/libO/solaris/mylib",
1433: "MySolverCreate",MySolverCreate);
1434: .ve
1436: Then, your solver can be chosen with the procedural interface via
1437: $ PCSetType(pc,"my_solver")
1438: or at runtime via the option
1439: $ -pc_type my_solver
1441: Level: advanced
1443: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
1444: occuring in pathname will be replaced with appropriate values.
1446: .keywords: PC, register
1448: .seealso: PCRegisterAll(), PCRegisterDestroy(), PCRegister()
1449: M*/
1451: int PCRegister(char *sname,char *path,char *name,int (*function)(PC))
1452: {
1453: int ierr;
1454: char fullname[256];
1458: PetscFListConcat(path,name,fullname);
1459: PetscFListAdd(&PCList,sname,fullname,(void (*)(void))function);
1460: return(0);
1461: }
1463: /*@
1464: PCComputeExplicitOperator - Computes the explicit preconditioned operator.
1466: Collective on PC
1468: Input Parameter:
1469: . pc - the preconditioner object
1471: Output Parameter:
1472: . mat - the explict preconditioned operator
1474: Notes:
1475: This computation is done by applying the operators to columns of the
1476: identity matrix.
1478: Currently, this routine uses a dense matrix format when 1 processor
1479: is used and a sparse format otherwise. This routine is costly in general,
1480: and is recommended for use only with relatively small systems.
1482: Level: advanced
1483:
1484: .keywords: PC, compute, explicit, operator
1486: @*/
1487: int PCComputeExplicitOperator(PC pc,Mat *mat)
1488: {
1489: Vec in,out;
1490: int ierr,i,M,m,size,*rows,start,end;
1491: MPI_Comm comm;
1492: PetscScalar *array,zero = 0.0,one = 1.0;
1498: comm = pc->comm;
1499: MPI_Comm_size(comm,&size);
1501: PCGetVector(pc,&in);
1502: VecDuplicate(in,&out);
1503: VecGetOwnershipRange(in,&start,&end);
1504: VecGetSize(in,&M);
1505: VecGetLocalSize(in,&m);
1506: PetscMalloc((m+1)*sizeof(int),&rows);
1507: for (i=0; i<m; i++) {rows[i] = start + i;}
1509: if (size == 1) {
1510: MatCreateSeqDense(comm,M,M,PETSC_NULL,mat);
1511: } else {
1512: MatCreateMPIAIJ(comm,m,m,M,M,0,0,0,0,mat);
1513: }
1515: for (i=0; i<M; i++) {
1517: VecSet(&zero,in);
1518: VecSetValues(in,1,&i,&one,INSERT_VALUES);
1519: VecAssemblyBegin(in);
1520: VecAssemblyEnd(in);
1522: PCApply(pc,in,out);
1523:
1524: VecGetArray(out,&array);
1525: MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
1526: VecRestoreArray(out,&array);
1528: }
1529: PetscFree(rows);
1530: VecDestroy(out);
1531: MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
1532: MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
1533: return(0);
1534: }