Actual source code: precon.c
1: #define PETSCKSP_DLL
3: /*
4: The PC (preconditioner) interface routines, callable by users.
5: */
6: #include private/pcimpl.h
8: /* Logging support */
9: PetscCookie PC_COOKIE = 0;
10: PetscEvent PC_SetUp = 0, PC_SetUpOnBlocks = 0, PC_Apply = 0, PC_ApplyCoarse = 0, PC_ApplyMultiple = 0, PC_ApplySymmetricLeft = 0;
11: PetscEvent PC_ApplySymmetricRight = 0, PC_ModifySubMatrices = 0;
15: PetscErrorCode PCGetDefaultType_Private(PC pc,const char* type[])
16: {
18: PetscMPIInt size;
19: PetscTruth flg1,flg2,set,flg3;
22: MPI_Comm_size(pc->comm,&size);
23: if (pc->pmat) {
24: PetscErrorCode (*f)(Mat,PetscTruth*,MatReuse,Mat*);
25: PetscObjectQueryFunction((PetscObject)pc->pmat,"MatGetDiagonalBlock_C",(void (**)(void))&f);
26: if (size == 1) {
27: MatHasOperation(pc->pmat,MATOP_ICCFACTOR_SYMBOLIC,&flg1);
28: MatHasOperation(pc->pmat,MATOP_ILUFACTOR_SYMBOLIC,&flg2);
29: MatIsSymmetricKnown(pc->pmat,&set,&flg3);
30: if (flg1 && (!flg2 || (set && flg3))) {
31: *type = PCICC;
32: } else if (flg2) {
33: *type = PCILU;
34: } else if (f) { /* likely is a parallel matrix run on one processor */
35: *type = PCBJACOBI;
36: } else {
37: *type = PCNONE;
38: }
39: } else {
40: if (f) {
41: *type = PCBJACOBI;
42: } else {
43: *type = PCNONE;
44: }
45: }
46: } else {
47: if (size == 1) {
48: *type = PCILU;
49: } else {
50: *type = PCBJACOBI;
51: }
52: }
53: return(0);
54: }
58: /*@
59: PCDestroy - Destroys PC context that was created with PCCreate().
61: Collective on PC
63: Input Parameter:
64: . pc - the preconditioner context
66: Level: developer
68: .keywords: PC, destroy
70: .seealso: PCCreate(), PCSetUp()
71: @*/
72: PetscErrorCode PETSCKSP_DLLEXPORT PCDestroy(PC pc)
73: {
78: if (--pc->refct > 0) return(0);
80: /* if memory was published with AMS then destroy it */
81: PetscObjectDepublish(pc);
83: if (pc->ops->destroy) { (*pc->ops->destroy)(pc);}
84: if (pc->diagonalscaleright) {VecDestroy(pc->diagonalscaleright);}
85: if (pc->diagonalscaleleft) {VecDestroy(pc->diagonalscaleleft);}
87: PetscHeaderDestroy(pc);
88: return(0);
89: }
93: /*@C
94: PCDiagonalScale - Indicates if the preconditioner applies an additional left and right
95: scaling as needed by certain time-stepping codes.
97: Collective on PC
99: Input Parameter:
100: . pc - the preconditioner context
102: Output Parameter:
103: . flag - PETSC_TRUE if it applies the scaling
105: Level: developer
107: Notes: If this returns PETSC_TRUE then the system solved via the Krylov method is
108: $ D M A D^{-1} y = D M b for left preconditioning or
109: $ D A M D^{-1} z = D b for right preconditioning
111: .keywords: PC
113: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScaleSet()
114: @*/
115: PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScale(PC pc,PetscTruth *flag)
116: {
120: *flag = pc->diagonalscale;
121: return(0);
122: }
126: /*@
127: PCDiagonalScaleSet - Indicates the left scaling to use to apply an additional left and right
128: scaling as needed by certain time-stepping codes.
130: Collective on PC
132: Input Parameters:
133: + pc - the preconditioner context
134: - s - scaling vector
136: Level: intermediate
138: Notes: The system solved via the Krylov method is
139: $ D M A D^{-1} y = D M b for left preconditioning or
140: $ D A M D^{-1} z = D b for right preconditioning
142: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
144: .keywords: PC
146: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScale()
147: @*/
148: PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScaleSet(PC pc,Vec s)
149: {
155: pc->diagonalscale = PETSC_TRUE;
156: if (pc->diagonalscaleleft) {
157: VecDestroy(pc->diagonalscaleleft);
158: }
159: pc->diagonalscaleleft = s;
160: PetscObjectReference((PetscObject)s);
161: if (!pc->diagonalscaleright) {
162: VecDuplicate(s,&pc->diagonalscaleright);
163: }
164: VecCopy(s,pc->diagonalscaleright);
165: VecReciprocal(pc->diagonalscaleright);
166: return(0);
167: }
171: /*@C
172: PCDiagonalScaleLeft - Indicates the left scaling to use to apply an additional left and right
173: scaling as needed by certain time-stepping codes.
175: Collective on PC
177: Input Parameters:
178: + pc - the preconditioner context
179: . in - input vector
180: + out - scaled vector (maybe the same as in)
182: Level: intermediate
184: Notes: The system solved via the Krylov method is
185: $ D M A D^{-1} y = D M b for left preconditioning or
186: $ D A M D^{-1} z = D b for right preconditioning
188: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
190: If diagonal scaling is turned off and in is not out then in is copied to out
192: .keywords: PC
194: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
195: @*/
196: PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
197: {
204: if (pc->diagonalscale) {
205: VecPointwiseMult(out,pc->diagonalscaleleft,in);
206: } else if (in != out) {
207: VecCopy(in,out);
208: }
209: return(0);
210: }
214: /*@C
215: PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.
217: Collective on PC
219: Input Parameters:
220: + pc - the preconditioner context
221: . in - input vector
222: + out - scaled vector (maybe the same as in)
224: Level: intermediate
226: Notes: The system solved via the Krylov method is
227: $ D M A D^{-1} y = D M b for left preconditioning or
228: $ D A M D^{-1} z = D b for right preconditioning
230: PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.
232: If diagonal scaling is turned off and in is not out then in is copied to out
234: .keywords: PC
236: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
237: @*/
238: PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScaleRight(PC pc,Vec in,Vec out)
239: {
246: if (pc->diagonalscale) {
247: VecPointwiseMult(out,pc->diagonalscaleright,in);
248: } else if (in != out) {
249: VecCopy(in,out);
250: }
251: return(0);
252: }
256: static PetscErrorCode PCPublish_Petsc(PetscObject obj)
257: {
259: return(0);
260: }
264: /*@
265: PCCreate - Creates a preconditioner context.
267: Collective on MPI_Comm
269: Input Parameter:
270: . comm - MPI communicator
272: Output Parameter:
273: . pc - location to put the preconditioner context
275: Notes:
276: The default preconditioner on one processor is PCILU with 0 fill on more
277: then one it is PCBJACOBI with ILU() on each processor.
279: Level: developer
281: .keywords: PC, create, context
283: .seealso: PCSetUp(), PCApply(), PCDestroy()
284: @*/
285: PetscErrorCode PETSCKSP_DLLEXPORT PCCreate(MPI_Comm comm,PC *newpc)
286: {
287: PC pc;
292: *newpc = 0;
293: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
294: PCInitializePackage(PETSC_NULL);
295: #endif
297: PetscHeaderCreate(pc,_p_PC,struct _PCOps,PC_COOKIE,-1,"PC",comm,PCDestroy,PCView);
298: pc->bops->publish = PCPublish_Petsc;
299: pc->mat = 0;
300: pc->pmat = 0;
301: pc->setupcalled = 0;
302: pc->data = 0;
303: pc->diagonalscale = PETSC_FALSE;
304: pc->diagonalscaleleft = 0;
305: pc->diagonalscaleright = 0;
307: pc->ops->destroy = 0;
308: pc->ops->apply = 0;
309: pc->ops->applytranspose = 0;
310: pc->ops->applyBA = 0;
311: pc->ops->applyBAtranspose = 0;
312: pc->ops->applyrichardson = 0;
313: pc->ops->view = 0;
314: pc->ops->getfactoredmatrix = 0;
315: pc->ops->applysymmetricright = 0;
316: pc->ops->applysymmetricleft = 0;
317: pc->ops->setuponblocks = 0;
319: pc->modifysubmatrices = 0;
320: pc->modifysubmatricesP = 0;
321: *newpc = pc;
322: PetscPublishAll(pc);
323: return(0);
325: }
327: /* -------------------------------------------------------------------------------*/
331: /*@
332: PCApply - Applies the preconditioner to a vector.
334: Collective on PC and Vec
336: Input Parameters:
337: + pc - the preconditioner context
338: - x - input vector
340: Output Parameter:
341: . y - output vector
343: Level: developer
345: .keywords: PC, apply
347: .seealso: PCApplyTranspose(), PCApplyBAorAB()
348: @*/
349: PetscErrorCode PETSCKSP_DLLEXPORT PCApply(PC pc,Vec x,Vec y)
350: {
357: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
359: if (pc->setupcalled < 2) {
360: PCSetUp(pc);
361: }
362: PetscLogEventBegin(PC_Apply,pc,x,y,0);
363: (*pc->ops->apply)(pc,x,y);
364: PetscLogEventEnd(PC_Apply,pc,x,y,0);
365: return(0);
366: }
370: /*@
371: PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.
373: Collective on PC and Vec
375: Input Parameters:
376: + pc - the preconditioner context
377: - x - input vector
379: Output Parameter:
380: . y - output vector
382: Notes:
383: Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
385: Level: developer
387: .keywords: PC, apply, symmetric, left
389: .seealso: PCApply(), PCApplySymmetricRight()
390: @*/
391: PetscErrorCode PETSCKSP_DLLEXPORT PCApplySymmetricLeft(PC pc,Vec x,Vec y)
392: {
399: if (!pc->ops->applysymmetricleft) SETERRQ(PETSC_ERR_SUP,"PC does not have left symmetric apply");
401: if (pc->setupcalled < 2) {
402: PCSetUp(pc);
403: }
405: PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);
406: (*pc->ops->applysymmetricleft)(pc,x,y);
407: PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);
408: return(0);
409: }
413: /*@
414: PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.
416: Collective on PC and Vec
418: Input Parameters:
419: + pc - the preconditioner context
420: - x - input vector
422: Output Parameter:
423: . y - output vector
425: Level: developer
427: Notes:
428: Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.
430: .keywords: PC, apply, symmetric, right
432: .seealso: PCApply(), PCApplySymmetricLeft()
433: @*/
434: PetscErrorCode PETSCKSP_DLLEXPORT PCApplySymmetricRight(PC pc,Vec x,Vec y)
435: {
442: if (!pc->ops->applysymmetricright) SETERRQ(PETSC_ERR_SUP,"PC does not have left symmetric apply");
444: if (pc->setupcalled < 2) {
445: PCSetUp(pc);
446: }
448: PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);
449: (*pc->ops->applysymmetricright)(pc,x,y);
450: PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);
451: return(0);
452: }
456: /*@
457: PCApplyTranspose - Applies the transpose of preconditioner to a vector.
459: Collective on PC and Vec
461: Input Parameters:
462: + pc - the preconditioner context
463: - x - input vector
465: Output Parameter:
466: . y - output vector
468: Level: developer
470: .keywords: PC, apply, transpose
472: .seealso: PCApply(), PCApplyBAorAB(), PCApplyBAorABTranspose(), PCHasApplyTranspose()
473: @*/
474: PetscErrorCode PETSCKSP_DLLEXPORT PCApplyTranspose(PC pc,Vec x,Vec y)
475: {
482: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
483: if (!pc->ops->applytranspose) SETERRQ(PETSC_ERR_SUP," ");
485: if (pc->setupcalled < 2) {
486: PCSetUp(pc);
487: }
489: PetscLogEventBegin(PC_Apply,pc,x,y,0);
490: (*pc->ops->applytranspose)(pc,x,y);
491: PetscLogEventEnd(PC_Apply,pc,x,y,0);
492: return(0);
493: }
497: /*@
498: PCHasApplyTranspose - Test whether the preconditioner has a transpose apply operation
500: Collective on PC and Vec
502: Input Parameters:
503: . pc - the preconditioner context
505: Output Parameter:
506: . flg - PETSC_TRUE if a transpose operation is defined
508: Level: developer
510: .keywords: PC, apply, transpose
512: .seealso: PCApplyTranspose()
513: @*/
514: PetscErrorCode PETSCKSP_DLLEXPORT PCHasApplyTranspose(PC pc,PetscTruth *flg)
515: {
519: *flg = (PetscTruth) (pc->ops->applytranspose == 0);
520: return(0);
521: }
525: /*@
526: PCApplyBAorAB - Applies the preconditioner and operator to a vector.
528: Collective on PC and Vec
530: Input Parameters:
531: + pc - the preconditioner context
532: . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
533: . x - input vector
534: - work - work vector
536: Output Parameter:
537: . y - output vector
539: Level: developer
541: .keywords: PC, apply, operator
543: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
544: @*/
545: PetscErrorCode PETSCKSP_DLLEXPORT PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
546: {
554: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
555: if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) {
556: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric");
557: }
558: if (pc->diagonalscale && side == PC_SYMMETRIC) {
559: SETERRQ(PETSC_ERR_SUP,"Cannot include diagonal scaling with symmetric preconditioner application");
560: }
562: if (pc->setupcalled < 2) {
563: PCSetUp(pc);
564: }
566: if (pc->diagonalscale) {
567: if (pc->ops->applyBA) {
568: Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
569: VecDuplicate(x,&work2);
570: PCDiagonalScaleRight(pc,x,work2);
571: (*pc->ops->applyBA)(pc,side,work2,y,work);
572: PCDiagonalScaleLeft(pc,y,y);
573: VecDestroy(work2);
574: } else if (side == PC_RIGHT) {
575: PCDiagonalScaleRight(pc,x,y);
576: PCApply(pc,y,work);
577: MatMult(pc->mat,work,y);
578: PCDiagonalScaleLeft(pc,y,y);
579: } else if (side == PC_LEFT) {
580: PCDiagonalScaleRight(pc,x,y);
581: MatMult(pc->mat,y,work);
582: PCApply(pc,work,y);
583: PCDiagonalScaleLeft(pc,y,y);
584: } else if (side == PC_SYMMETRIC) {
585: SETERRQ(PETSC_ERR_SUP,"Cannot provide diagonal scaling with symmetric application of preconditioner");
586: }
587: } else {
588: if (pc->ops->applyBA) {
589: (*pc->ops->applyBA)(pc,side,x,y,work);
590: } else if (side == PC_RIGHT) {
591: PCApply(pc,x,work);
592: MatMult(pc->mat,work,y);
593: } else if (side == PC_LEFT) {
594: MatMult(pc->mat,x,work);
595: PCApply(pc,work,y);
596: } else if (side == PC_SYMMETRIC) {
597: /* There's an extra copy here; maybe should provide 2 work vectors instead? */
598: PCApplySymmetricRight(pc,x,work);
599: MatMult(pc->mat,work,y);
600: VecCopy(y,work);
601: PCApplySymmetricLeft(pc,work,y);
602: }
603: }
604: return(0);
605: }
609: /*@
610: PCApplyBAorABTranspose - Applies the transpose of the preconditioner
611: and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
612: not tr(B*A) = tr(A)*tr(B).
614: Collective on PC and Vec
616: Input Parameters:
617: + pc - the preconditioner context
618: . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
619: . x - input vector
620: - work - work vector
622: Output Parameter:
623: . y - output vector
625: Level: developer
627: .keywords: PC, apply, operator, transpose
629: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
630: @*/
631: PetscErrorCode PETSCKSP_DLLEXPORT PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
632: {
640: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
641: if (pc->ops->applyBAtranspose) {
642: (*pc->ops->applyBAtranspose)(pc,side,x,y,work);
643: return(0);
644: }
645: if (side != PC_LEFT && side != PC_RIGHT) {
646: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");
647: }
649: if (pc->setupcalled < 2) {
650: PCSetUp(pc);
651: }
653: if (side == PC_RIGHT) {
654: PCApplyTranspose(pc,x,work);
655: MatMultTranspose(pc->mat,work,y);
656: } else if (side == PC_LEFT) {
657: MatMultTranspose(pc->mat,x,work);
658: PCApplyTranspose(pc,work,y);
659: }
660: /* add support for PC_SYMMETRIC */
661: return(0); /* actually will never get here */
662: }
664: /* -------------------------------------------------------------------------------*/
668: /*@
669: PCApplyRichardsonExists - Determines whether a particular preconditioner has a
670: built-in fast application of Richardson's method.
672: Not Collective
674: Input Parameter:
675: . pc - the preconditioner
677: Output Parameter:
678: . exists - PETSC_TRUE or PETSC_FALSE
680: Level: developer
682: .keywords: PC, apply, Richardson, exists
684: .seealso: PCApplyRichardson()
685: @*/
686: PetscErrorCode PETSCKSP_DLLEXPORT PCApplyRichardsonExists(PC pc,PetscTruth *exists)
687: {
691: if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
692: else *exists = PETSC_FALSE;
693: return(0);
694: }
698: /*@
699: PCApplyRichardson - Applies several steps of Richardson iteration with
700: the particular preconditioner. This routine is usually used by the
701: Krylov solvers and not the application code directly.
703: Collective on PC
705: Input Parameters:
706: + pc - the preconditioner context
707: . x - the initial guess
708: . w - one work vector
709: . rtol - relative decrease in residual norm convergence criteria
710: . abstol - absolute residual norm convergence criteria
711: . dtol - divergence residual norm increase criteria
712: - its - the number of iterations to apply.
714: Output Parameter:
715: . y - the solution
717: Notes:
718: Most preconditioners do not support this function. Use the command
719: PCApplyRichardsonExists() to determine if one does.
721: Except for the multigrid PC this routine ignores the convergence tolerances
722: and always runs for the number of iterations
723:
724: Level: developer
726: .keywords: PC, apply, Richardson
728: .seealso: PCApplyRichardsonExists()
729: @*/
730: PetscErrorCode PETSCKSP_DLLEXPORT PCApplyRichardson(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its)
731: {
739: if (!pc->ops->applyrichardson) SETERRQ(PETSC_ERR_SUP," ");
741: if (pc->setupcalled < 2) {
742: PCSetUp(pc);
743: }
745: (*pc->ops->applyrichardson)(pc,x,y,w,rtol,abstol,dtol,its);
746: return(0);
747: }
749: /*
750: a setupcall of 0 indicates never setup,
751: 1 needs to be resetup,
752: 2 does not need any changes.
753: */
756: /*@
757: PCSetUp - Prepares for the use of a preconditioner.
759: Collective on PC
761: Input Parameter:
762: . pc - the preconditioner context
764: Level: developer
766: .keywords: PC, setup
768: .seealso: PCCreate(), PCApply(), PCDestroy()
769: @*/
770: PetscErrorCode PETSCKSP_DLLEXPORT PCSetUp(PC pc)
771: {
773: const char *def;
778: if (pc->setupcalled > 1) {
779: PetscInfo(pc,"Setting PC with identical preconditioner\n");
780: return(0);
781: } else if (!pc->setupcalled) {
782: PetscInfo(pc,"Setting up new PC\n");
783: } else if (pc->flag == SAME_NONZERO_PATTERN) {
784: PetscInfo(pc,"Setting up PC with same nonzero pattern\n");
785: } else {
786: PetscInfo(pc,"Setting up PC with different nonzero pattern\n");
787: }
789: PetscLogEventBegin(PC_SetUp,pc,0,0,0);
790: if (!pc->mat) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");}
792: if (!pc->type_name) {
793: PCGetDefaultType_Private(pc,&def);
794: PCSetType(pc,def);
795: }
797: if (pc->ops->setup) {
798: (*pc->ops->setup)(pc);
799: }
800: pc->setupcalled = 2;
801: PetscLogEventEnd(PC_SetUp,pc,0,0,0);
802: return(0);
803: }
807: /*@
808: PCSetUpOnBlocks - Sets up the preconditioner for each block in
809: the block Jacobi, block Gauss-Seidel, and overlapping Schwarz
810: methods.
812: Collective on PC
814: Input Parameters:
815: . pc - the preconditioner context
817: Level: developer
819: .keywords: PC, setup, blocks
821: .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
822: @*/
823: PetscErrorCode PETSCKSP_DLLEXPORT PCSetUpOnBlocks(PC pc)
824: {
829: if (!pc->ops->setuponblocks) return(0);
830: PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);
831: (*pc->ops->setuponblocks)(pc);
832: PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);
833: return(0);
834: }
838: /*@C
839: PCSetModifySubMatrices - Sets a user-defined routine for modifying the
840: submatrices that arise within certain subdomain-based preconditioners.
841: The basic submatrices are extracted from the preconditioner matrix as
842: usual; the user can then alter these (for example, to set different boundary
843: conditions for each submatrix) before they are used for the local solves.
845: Collective on PC
847: Input Parameters:
848: + pc - the preconditioner context
849: . func - routine for modifying the submatrices
850: - ctx - optional user-defined context (may be null)
852: Calling sequence of func:
853: $ func (PC pc,PetscInt nsub,IS *row,IS *col,Mat *submat,void *ctx);
855: . row - an array of index sets that contain the global row numbers
856: that comprise each local submatrix
857: . col - an array of index sets that contain the global column numbers
858: that comprise each local submatrix
859: . submat - array of local submatrices
860: - ctx - optional user-defined context for private data for the
861: user-defined func routine (may be null)
863: Notes:
864: PCSetModifySubMatrices() MUST be called before KSPSetUp() and
865: KSPSolve().
867: A routine set by PCSetModifySubMatrices() is currently called within
868: the block Jacobi (PCBJACOBI) and additive Schwarz (PCASM)
869: preconditioners. All other preconditioners ignore this routine.
871: Level: advanced
873: .keywords: PC, set, modify, submatrices
875: .seealso: PCModifySubMatrices()
876: @*/
877: PetscErrorCode PETSCKSP_DLLEXPORT PCSetModifySubMatrices(PC pc,PetscErrorCode (*func)(PC,PetscInt,const IS[],const IS[],Mat[],void*),void *ctx)
878: {
881: pc->modifysubmatrices = func;
882: pc->modifysubmatricesP = ctx;
883: return(0);
884: }
888: /*@C
889: PCModifySubMatrices - Calls an optional user-defined routine within
890: certain preconditioners if one has been set with PCSetModifySubMarices().
892: Collective on PC
894: Input Parameters:
895: + pc - the preconditioner context
896: . nsub - the number of local submatrices
897: . row - an array of index sets that contain the global row numbers
898: that comprise each local submatrix
899: . col - an array of index sets that contain the global column numbers
900: that comprise each local submatrix
901: . submat - array of local submatrices
902: - ctx - optional user-defined context for private data for the
903: user-defined routine (may be null)
905: Output Parameter:
906: . submat - array of local submatrices (the entries of which may
907: have been modified)
909: Notes:
910: The user should NOT generally call this routine, as it will
911: automatically be called within certain preconditioners (currently
912: block Jacobi, additive Schwarz) if set.
914: The basic submatrices are extracted from the preconditioner matrix
915: as usual; the user can then alter these (for example, to set different
916: boundary conditions for each submatrix) before they are used for the
917: local solves.
919: Level: developer
921: .keywords: PC, modify, submatrices
923: .seealso: PCSetModifySubMatrices()
924: @*/
925: PetscErrorCode PETSCKSP_DLLEXPORT PCModifySubMatrices(PC pc,PetscInt nsub,const IS row[],const IS col[],Mat submat[],void *ctx)
926: {
930: if (!pc->modifysubmatrices) return(0);
931: PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);
932: (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);
933: PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);
934: return(0);
935: }
939: /*@
940: PCSetOperators - Sets the matrix associated with the linear system and
941: a (possibly) different one associated with the preconditioner.
943: Collective on PC and Mat
945: Input Parameters:
946: + pc - the preconditioner context
947: . Amat - the matrix associated with the linear system
948: . Pmat - the matrix to be used in constructing the preconditioner, usually
949: the same as Amat.
950: - flag - flag indicating information about the preconditioner matrix structure
951: during successive linear solves. This flag is ignored the first time a
952: linear system is solved, and thus is irrelevant when solving just one linear
953: system.
955: Notes:
956: The flag can be used to eliminate unnecessary work in the preconditioner
957: during the repeated solution of linear systems of the same size. The
958: available options are
959: + SAME_PRECONDITIONER -
960: Pmat is identical during successive linear solves.
961: This option is intended for folks who are using
962: different Amat and Pmat matrices and wish to reuse the
963: same preconditioner matrix. For example, this option
964: saves work by not recomputing incomplete factorization
965: for ILU/ICC preconditioners.
966: . SAME_NONZERO_PATTERN -
967: Pmat has the same nonzero structure during
968: successive linear solves.
969: - DIFFERENT_NONZERO_PATTERN -
970: Pmat does not have the same nonzero structure.
972: Caution:
973: If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion
974: and does not check the structure of the matrix. If you erroneously
975: claim that the structure is the same when it actually is not, the new
976: preconditioner will not function correctly. Thus, use this optimization
977: feature carefully!
979: If in doubt about whether your preconditioner matrix has changed
980: structure or not, use the flag DIFFERENT_NONZERO_PATTERN.
982: More Notes about Repeated Solution of Linear Systems:
983: PETSc does NOT reset the matrix entries of either Amat or Pmat
984: to zero after a linear solve; the user is completely responsible for
985: matrix assembly. See the routine MatZeroEntries() if desiring to
986: zero all elements of a matrix.
988: Level: intermediate
990: .keywords: PC, set, operators, matrix, linear system
992: .seealso: PCGetOperators(), MatZeroEntries()
993: @*/
994: PetscErrorCode PETSCKSP_DLLEXPORT PCSetOperators(PC pc,Mat Amat,Mat Pmat,MatStructure flag)
995: {
997: PetscTruth isbjacobi,isrowbs;
1006: /*
1007: BlockSolve95 cannot use default BJacobi preconditioning
1008: */
1009: if (Amat) {
1010: PetscTypeCompare((PetscObject)Amat,MATMPIROWBS,&isrowbs);
1011: if (isrowbs) {
1012: PetscTypeCompare((PetscObject)pc,PCBJACOBI,&isbjacobi);
1013: if (isbjacobi) {
1014: PCSetType(pc,PCILU);
1015: PetscInfo(pc,"Switching default PC to PCILU since BS95 doesn't support PCBJACOBI\n");
1016: }
1017: }
1018: }
1020: pc->mat = Amat;
1021: pc->pmat = Pmat;
1022: if (pc->setupcalled == 2 && flag != SAME_PRECONDITIONER) {
1023: pc->setupcalled = 1;
1024: }
1025: pc->flag = flag;
1026: return(0);
1027: }
1031: /*@C
1032: PCGetOperators - Gets the matrix associated with the linear system and
1033: possibly a different one associated with the preconditioner.
1035: Not collective, though parallel Mats are returned if the PC is parallel
1037: Input Parameter:
1038: . pc - the preconditioner context
1040: Output Parameters:
1041: + mat - the matrix associated with the linear system
1042: . pmat - matrix associated with the preconditioner, usually the same
1043: as mat.
1044: - flag - flag indicating information about the preconditioner
1045: matrix structure. See PCSetOperators() for details.
1047: Level: intermediate
1049: .keywords: PC, get, operators, matrix, linear system
1051: .seealso: PCSetOperators()
1052: @*/
1053: PetscErrorCode PETSCKSP_DLLEXPORT PCGetOperators(PC pc,Mat *mat,Mat *pmat,MatStructure *flag)
1054: {
1057: if (mat) *mat = pc->mat;
1058: if (pmat) *pmat = pc->pmat;
1059: if (flag) *flag = pc->flag;
1060: return(0);
1061: }
1065: /*@
1066: PCGetFactoredMatrix - Gets the factored matrix from the
1067: preconditioner context. This routine is valid only for the LU,
1068: incomplete LU, Cholesky, and incomplete Cholesky methods.
1070: Not Collective on PC though Mat is parallel if PC is parallel
1072: Input Parameters:
1073: . pc - the preconditioner context
1075: Output parameters:
1076: . mat - the factored matrix
1078: Level: advanced
1080: Notes: Does not increase the reference count for the matrix so DO NOT destroy it
1082: .keywords: PC, get, factored, matrix
1083: @*/
1084: PetscErrorCode PETSCKSP_DLLEXPORT PCGetFactoredMatrix(PC pc,Mat *mat)
1085: {
1091: if (pc->ops->getfactoredmatrix) {
1092: (*pc->ops->getfactoredmatrix)(pc,mat);
1093: }
1094: return(0);
1095: }
1099: /*@C
1100: PCSetOptionsPrefix - Sets the prefix used for searching for all
1101: PC options in the database.
1103: Collective on PC
1105: Input Parameters:
1106: + pc - the preconditioner context
1107: - prefix - the prefix string to prepend to all PC option requests
1109: Notes:
1110: A hyphen (-) must NOT be given at the beginning of the prefix name.
1111: The first character of all runtime options is AUTOMATICALLY the
1112: hyphen.
1114: Level: advanced
1116: .keywords: PC, set, options, prefix, database
1118: .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1119: @*/
1120: PetscErrorCode PETSCKSP_DLLEXPORT PCSetOptionsPrefix(PC pc,const char prefix[])
1121: {
1126: PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);
1127: return(0);
1128: }
1132: /*@C
1133: PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1134: PC options in the database.
1136: Collective on PC
1138: Input Parameters:
1139: + pc - the preconditioner context
1140: - prefix - the prefix string to prepend to all PC option requests
1142: Notes:
1143: A hyphen (-) must NOT be given at the beginning of the prefix name.
1144: The first character of all runtime options is AUTOMATICALLY the
1145: hyphen.
1147: Level: advanced
1149: .keywords: PC, append, options, prefix, database
1151: .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1152: @*/
1153: PetscErrorCode PETSCKSP_DLLEXPORT PCAppendOptionsPrefix(PC pc,const char prefix[])
1154: {
1159: PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);
1160: return(0);
1161: }
1165: /*@C
1166: PCGetOptionsPrefix - Gets the prefix used for searching for all
1167: PC options in the database.
1169: Not Collective
1171: Input Parameters:
1172: . pc - the preconditioner context
1174: Output Parameters:
1175: . prefix - pointer to the prefix string used, is returned
1177: Notes: On the fortran side, the user should pass in a string 'prifix' of
1178: sufficient length to hold the prefix.
1180: Level: advanced
1182: .keywords: PC, get, options, prefix, database
1184: .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1185: @*/
1186: PetscErrorCode PETSCKSP_DLLEXPORT PCGetOptionsPrefix(PC pc,const char *prefix[])
1187: {
1193: PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);
1194: return(0);
1195: }
1199: /*@
1200: PCPreSolve - Optional pre-solve phase, intended for any
1201: preconditioner-specific actions that must be performed before
1202: the iterative solve itself.
1204: Collective on PC
1206: Input Parameters:
1207: + pc - the preconditioner context
1208: - ksp - the Krylov subspace context
1210: Level: developer
1212: Sample of Usage:
1213: .vb
1214: PCPreSolve(pc,ksp);
1215: KSPSolve(ksp,b,x);
1216: PCPostSolve(pc,ksp);
1217: .ve
1219: Notes:
1220: The pre-solve phase is distinct from the PCSetUp() phase.
1222: KSPSolve() calls this directly, so is rarely called by the user.
1224: .keywords: PC, pre-solve
1226: .seealso: PCPostSolve()
1227: @*/
1228: PetscErrorCode PETSCKSP_DLLEXPORT PCPreSolve(PC pc,KSP ksp)
1229: {
1231: Vec x,rhs;
1232: Mat A,B;
1237: KSPGetSolution(ksp,&x);
1238: KSPGetRhs(ksp,&rhs);
1239: /*
1240: Scale the system and have the matrices use the scaled form
1241: only if the two matrices are actually the same (and hence
1242: have the same scaling
1243: */
1244: PCGetOperators(pc,&A,&B,PETSC_NULL);
1245: if (A == B) {
1246: MatScaleSystem(pc->mat,rhs,x);
1247: MatUseScaledForm(pc->mat,PETSC_TRUE);
1248: }
1250: if (pc->ops->presolve) {
1251: (*pc->ops->presolve)(pc,ksp,rhs,x);
1252: }
1253: return(0);
1254: }
1258: /*@
1259: PCPostSolve - Optional post-solve phase, intended for any
1260: preconditioner-specific actions that must be performed after
1261: the iterative solve itself.
1263: Collective on PC
1265: Input Parameters:
1266: + pc - the preconditioner context
1267: - ksp - the Krylov subspace context
1269: Sample of Usage:
1270: .vb
1271: PCPreSolve(pc,ksp);
1272: KSPSolve(ksp,b,x);
1273: PCPostSolve(pc,ksp);
1274: .ve
1276: Note:
1277: KSPSolve() calls this routine directly, so it is rarely called by the user.
1279: Level: developer
1281: .keywords: PC, post-solve
1283: .seealso: PCPreSolve(), KSPSolve()
1284: @*/
1285: PetscErrorCode PETSCKSP_DLLEXPORT PCPostSolve(PC pc,KSP ksp)
1286: {
1288: Vec x,rhs;
1289: Mat A,B;
1294: KSPGetSolution(ksp,&x);
1295: KSPGetRhs(ksp,&rhs);
1296: if (pc->ops->postsolve) {
1297: (*pc->ops->postsolve)(pc,ksp,rhs,x);
1298: }
1300: /*
1301: Scale the system and have the matrices use the scaled form
1302: only if the two matrices are actually the same (and hence
1303: have the same scaling
1304: */
1305: PCGetOperators(pc,&A,&B,PETSC_NULL);
1306: if (A == B) {
1307: MatUnScaleSystem(pc->mat,rhs,x);
1308: MatUseScaledForm(pc->mat,PETSC_FALSE);
1309: }
1310: return(0);
1311: }
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: PetscErrorCode PETSCKSP_DLLEXPORT PCView(PC pc,PetscViewer viewer)
1342: {
1343: PCType cstr;
1344: PetscErrorCode ierr;
1345: PetscTruth mat_exists,iascii,isstring;
1346: PetscViewerFormat format;
1350: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pc->comm);
1354: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
1355: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
1356: if (iascii) {
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: %s\n",cstr);
1366: } else {
1367: PetscViewerASCIIPrintf(viewer," type: not yet set\n");
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(PETSC_ERR_SUP,"Viewer type %s not supported by PC",((PetscObject)viewer)->type_name);
1402: }
1403: return(0);
1404: }
1408: /*@C
1409: PCRegister - See PCRegisterDynamic()
1411: Level: advanced
1412: @*/
1413: PetscErrorCode PETSCKSP_DLLEXPORT PCRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PC))
1414: {
1416: char fullname[PETSC_MAX_PATH_LEN];
1420: PetscFListConcat(path,name,fullname);
1421: PetscFListAdd(&PCList,sname,fullname,(void (*)(void))function);
1422: return(0);
1423: }
1427: /*@
1428: PCComputeExplicitOperator - Computes the explicit preconditioned operator.
1430: Collective on PC
1432: Input Parameter:
1433: . pc - the preconditioner object
1435: Output Parameter:
1436: . mat - the explict preconditioned operator
1438: Notes:
1439: This computation is done by applying the operators to columns of the
1440: identity matrix.
1442: Currently, this routine uses a dense matrix format when 1 processor
1443: is used and a sparse format otherwise. This routine is costly in general,
1444: and is recommended for use only with relatively small systems.
1446: Level: advanced
1447:
1448: .keywords: PC, compute, explicit, operator
1450: @*/
1451: PetscErrorCode PETSCKSP_DLLEXPORT PCComputeExplicitOperator(PC pc,Mat *mat)
1452: {
1453: Vec in,out;
1455: PetscInt i,M,m,*rows,start,end;
1456: PetscMPIInt size;
1457: MPI_Comm comm;
1458: PetscScalar *array,one = 1.0;
1459:
1464: comm = pc->comm;
1465: MPI_Comm_size(comm,&size);
1467: if (!pc->pmat) SETERRQ(PETSC_ERR_ORDER,"You must call KSPSetOperators() or PCSetOperators() before this call");
1468: MatGetVecs(pc->pmat,&in,0);
1469: VecDuplicate(in,&out);
1470: VecGetOwnershipRange(in,&start,&end);
1471: VecGetSize(in,&M);
1472: VecGetLocalSize(in,&m);
1473: PetscMalloc((m+1)*sizeof(PetscInt),&rows);
1474: for (i=0; i<m; i++) {rows[i] = start + i;}
1476: MatCreate(comm,mat);
1477: MatSetSizes(*mat,m,m,M,M);
1478: if (size == 1) {
1479: MatSetType(*mat,MATSEQDENSE);
1480: MatSeqDenseSetPreallocation(*mat,PETSC_NULL);
1481: } else {
1482: MatSetType(*mat,MATMPIAIJ);
1483: MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);
1484: }
1486: for (i=0; i<M; i++) {
1488: VecSet(in,0.0);
1489: VecSetValues(in,1,&i,&one,INSERT_VALUES);
1490: VecAssemblyBegin(in);
1491: VecAssemblyEnd(in);
1493: /* should fix, allowing user to choose side */
1494: PCApply(pc,in,out);
1495:
1496: VecGetArray(out,&array);
1497: MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
1498: VecRestoreArray(out,&array);
1500: }
1501: PetscFree(rows);
1502: VecDestroy(out);
1503: MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
1504: MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
1505: return(0);
1506: }