Actual source code: composite.c
1: /*$Id: composite.c,v 1.45 2001/08/07 03:03:39 balay Exp $*/
2: /*
3: Defines a preconditioner that can consist of a collection of PCs
4: */
5: #include src/sles/pc/pcimpl.h
6: #include petscsles.h
8: typedef struct _PC_CompositeLink *PC_CompositeLink;
9: struct _PC_CompositeLink {
10: PC pc;
11: PC_CompositeLink next;
12: };
13:
14: typedef struct {
15: PC_CompositeLink head;
16: PCCompositeType type;
17: Vec work1;
18: Vec work2;
19: PetscScalar alpha;
20: PetscTruth use_true_matrix;
21: } PC_Composite;
23: static int PCApply_Composite_Multiplicative(PC pc,Vec x,Vec y)
24: {
25: int ierr;
26: PC_Composite *jac = (PC_Composite*)pc->data;
27: PC_CompositeLink next = jac->head;
28: PetscScalar one = 1.0,mone = -1.0;
29: Mat mat = pc->pmat;
32: if (!next) {
33: SETERRQ(1,"No composite preconditioners supplied via PCCompositeAddPC()");
34: }
35: if (next->next && !jac->work2) { /* allocate second work vector */
36: VecDuplicate(jac->work1,&jac->work2);
37: }
38: PCApply(next->pc,x,y);
39: if (jac->use_true_matrix) mat = pc->mat;
40: while (next->next) {
41: next = next->next;
42: MatMult(mat,y,jac->work1);
43: VecWAXPY(&mone,jac->work1,x,jac->work2);
44: PCApply(next->pc,jac->work2,jac->work1);
45: VecAXPY(&one,jac->work1,y);
46: }
48: return(0);
49: }
51: /*
52: This is very special for a matrix of the form alpha I + R + S
53: where first preconditioner is built from alpha I + S and second from
54: alpha I + R
55: */
56: static int PCApply_Composite_Special(PC pc,Vec x,Vec y)
57: {
58: int ierr;
59: PC_Composite *jac = (PC_Composite*)pc->data;
60: PC_CompositeLink next = jac->head;
63: if (!next) {
64: SETERRQ(1,"No composite preconditioners supplied via PCCompositeAddPC()");
65: }
66: if (!next->next || next->next->next) {
67: SETERRQ(1,"Special composite preconditioners requires exactly two PCs");
68: }
70: PCApply(next->pc,x,jac->work1);
71: PCApply(next->next->pc,jac->work1,y);
72: return(0);
73: }
75: static int PCApply_Composite_Additive(PC pc,Vec x,Vec y)
76: {
77: int ierr;
78: PC_Composite *jac = (PC_Composite*)pc->data;
79: PC_CompositeLink next = jac->head;
80: PetscScalar one = 1.0;
83: if (!next) {
84: SETERRQ(1,"No composite preconditioners supplied via PCCompositeAddPC()");
85: }
86: PCApply(next->pc,x,y);
87: while (next->next) {
88: next = next->next;
89: PCApply(next->pc,x,jac->work1);
90: VecAXPY(&one,jac->work1,y);
91: }
92: return(0);
93: }
95: static int PCSetUp_Composite(PC pc)
96: {
97: int ierr;
98: PC_Composite *jac = (PC_Composite*)pc->data;
99: PC_CompositeLink next = jac->head;
102: if (!jac->work1) {
103: VecDuplicate(pc->vec,&jac->work1);
104: }
105: while (next) {
106: PCSetOperators(next->pc,pc->mat,pc->pmat,pc->flag);
107: PCSetVector(next->pc,jac->work1);
108: next = next->next;
109: }
111: return(0);
112: }
114: static int PCDestroy_Composite(PC pc)
115: {
116: PC_Composite *jac = (PC_Composite*)pc->data;
117: int ierr;
118: PC_CompositeLink next = jac->head;
121: while (next) {
122: PCDestroy(next->pc);
123: next = next->next;
124: }
126: if (jac->work1) {VecDestroy(jac->work1);}
127: if (jac->work2) {VecDestroy(jac->work2);}
128: PetscFree(jac);
129: return(0);
130: }
132: static int PCSetFromOptions_Composite(PC pc)
133: {
134: PC_Composite *jac = (PC_Composite*)pc->data;
135: int ierr,nmax = 8,i;
136: PCCompositeType type=PC_COMPOSITE_ADDITIVE;
137: PC_CompositeLink next;
138: char *pcs[8],stype[16],*types[] = {"multiplicative","additive","special"};
139: PetscTruth flg;
142: PetscOptionsHead("Composite preconditioner options");
143: PetscOptionsEList("-pc_composite_type","Type of composition","PCCompositeSetType",types,3,"multiplicative",stype,16,&flg);
144: if (flg) {
145: PetscTruth ismult,isadd,isspecial;
147: PetscStrcmp(stype,types[0],&ismult);
148: PetscStrcmp(stype,types[1],&isadd);
149: PetscStrcmp(stype,types[2],&isspecial);
151: if (ismult) type = PC_COMPOSITE_MULTIPLICATIVE;
152: else if (isadd) type = PC_COMPOSITE_ADDITIVE;
153: else if (isspecial) type = PC_COMPOSITE_SPECIAL;
154: else SETERRQ(1,"Unknown composite type given");
156: PCCompositeSetType(pc,type);
157: }
158: PetscOptionsName("-pc_composite_true","Use true matrix for inner solves","PCCompositeSetUseTrue",&flg);
159: if (flg) {
160: PCCompositeSetUseTrue(pc);
161: }
162: PetscOptionsStringArray("-pc_composite_pcs","List of composite solvers","PCCompositeAddPC",pcs,&nmax,&flg);
163: if (flg) {
164: for (i=0; i<nmax; i++) {
165: PCCompositeAddPC(pc,pcs[i]);
166: }
167: }
168: PetscOptionsTail();
170: next = jac->head;
171: while (next) {
172: PCSetFromOptions(next->pc);
173: next = next->next;
174: }
175: return(0);
176: }
178: static int PCView_Composite(PC pc,PetscViewer viewer)
179: {
180: PC_Composite *jac = (PC_Composite*)pc->data;
181: int ierr;
182: PC_CompositeLink next = jac->head;
183: PetscTruth isascii;
186: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
187: if (isascii) {
188: PetscViewerASCIIPrintf(viewer,"PCs on composite preconditioner follown");
189: PetscViewerASCIIPrintf(viewer,"---------------------------------n");
190: } else {
191: SETERRQ1(1,"Viewer type %s not supported for PCComposite",((PetscObject)viewer)->type_name);
192: }
193: if (isascii) {
194: PetscViewerASCIIPushTab(viewer);
195: }
196: while (next) {
197: PCView(next->pc,viewer);
198: next = next->next;
199: }
200: if (isascii) {
201: PetscViewerASCIIPopTab(viewer);
202: PetscViewerASCIIPrintf(viewer,"---------------------------------n");
203: }
204: return(0);
205: }
207: /* ------------------------------------------------------------------------------*/
209: EXTERN_C_BEGIN
210: int PCCompositeSpecialSetAlpha_Composite(PC pc,PetscScalar alpha)
211: {
212: PC_Composite *jac = (PC_Composite*)pc->data;
214: jac->alpha = alpha;
215: return(0);
216: }
217: EXTERN_C_END
219: EXTERN_C_BEGIN
220: int PCCompositeSetType_Composite(PC pc,PCCompositeType type)
221: {
223: if (type == PC_COMPOSITE_ADDITIVE) {
224: pc->ops->apply = PCApply_Composite_Additive;
225: } else if (type == PC_COMPOSITE_MULTIPLICATIVE) {
226: pc->ops->apply = PCApply_Composite_Multiplicative;
227: } else if (type == PC_COMPOSITE_SPECIAL) {
228: pc->ops->apply = PCApply_Composite_Special;
229: } else {
230: SETERRQ(1,"Unkown composite preconditioner type");
231: }
232: return(0);
233: }
234: EXTERN_C_END
236: EXTERN_C_BEGIN
237: int PCCompositeAddPC_Composite(PC pc,PCType type)
238: {
239: PC_Composite *jac;
240: PC_CompositeLink next,link;
241: int ierr,cnt = 0;
242: char *prefix,newprefix[8];
245: ierr = PetscNew(struct _PC_CompositeLink,&link);
246: link->next = 0;
247: PCCreate(pc->comm,&link->pc);
249: jac = (PC_Composite*)pc->data;
250: next = jac->head;
251: if (!next) {
252: jac->head = link;
253: } else {
254: cnt++;
255: while (next->next) {
256: next = next->next;
257: cnt++;
258: }
259: next->next = link;
260: }
261: PCGetOptionsPrefix(pc,&prefix);
262: PCSetOptionsPrefix(link->pc,prefix);
263: sprintf(newprefix,"sub_%d_",cnt);
264: PCAppendOptionsPrefix(link->pc,newprefix);
265: /* type is set after prefix, because some methods may modify prefix, e.g. pcsles */
266: PCSetType(link->pc,type);
268: return(0);
269: }
270: EXTERN_C_END
272: EXTERN_C_BEGIN
273: int PCCompositeGetPC_Composite(PC pc,int n,PC *subpc)
274: {
275: PC_Composite *jac;
276: PC_CompositeLink next;
277: int i;
280: jac = (PC_Composite*)pc->data;
281: next = jac->head;
282: for (i=0; i<n; i++) {
283: if (!next->next) {
284: SETERRQ(1,"Not enough PCs in composite preconditioner");
285: }
286: next = next->next;
287: }
288: *subpc = next->pc;
289: return(0);
290: }
291: EXTERN_C_END
293: EXTERN_C_BEGIN
294: int PCCompositeSetUseTrue_Composite(PC pc)
295: {
296: PC_Composite *jac;
299: jac = (PC_Composite*)pc->data;
300: jac->use_true_matrix = PETSC_TRUE;
301: return(0);
302: }
303: EXTERN_C_END
305: /* -------------------------------------------------------------------------------- */
306: /*@C
307: PCCompositeSetType - Sets the type of composite preconditioner.
308:
309: Collective on PC
311: Input Parameter:
312: . pc - the preconditioner context
313: . type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL
315: Options Database Key:
316: . -pc_composite_type <type> - Sets composite preconditioner type
318: Level: Developer
320: .keywords: PC, set, type, composite preconditioner, additive, multiplicative
321: @*/
322: int PCCompositeSetType(PC pc,PCCompositeType type)
323: {
324: int ierr,(*f)(PC,PCCompositeType);
328: PetscObjectQueryFunction((PetscObject)pc,"PCCompositeSetType_C",(void (**)(void))&f);
329: if (f) {
330: (*f)(pc,type);
331: }
332: return(0);
333: }
335: /*@C
336: PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner
337: for alphaI + R + S
338:
339: Collective on PC
341: Input Parameter:
342: + pc - the preconditioner context
343: - alpha - scale on identity
345: Level: Developer
347: .keywords: PC, set, type, composite preconditioner, additive, multiplicative
348: @*/
349: int PCCompositeSpecialSetAlpha(PC pc,PetscScalar alpha)
350: {
351: int ierr,(*f)(PC,PetscScalar);
355: PetscObjectQueryFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",(void (**)(void))&f);
356: if (f) {
357: (*f)(pc,alpha);
358: }
359: return(0);
360: }
362: /*@C
363: PCCompositeAddPC - Adds another PC to the composite PC.
364:
365: Collective on PC
367: Input Parameters:
368: . pc - the preconditioner context
369: . type - the type of the new preconditioner
371: Level: Developer
373: .keywords: PC, composite preconditioner, add
374: @*/
375: int PCCompositeAddPC(PC pc,PCType type)
376: {
377: int ierr,(*f)(PC,PCType);
381: PetscObjectQueryFunction((PetscObject)pc,"PCCompositeAddPC_C",(void (**)(void))&f);
382: if (f) {
383: (*f)(pc,type);
384: }
385: return(0);
386: }
388: /*@C
389: PCCompositeGetPC - Gets one of the PC objects in the composite PC.
390:
391: Not Collective
393: Input Parameter:
394: . pc - the preconditioner context
395: . n - the number of the pc requested
397: Output Parameters:
398: . subpc - the PC requested
400: Level: Developer
402: .keywords: PC, get, composite preconditioner, sub preconditioner
404: .seealso: PCCompositeAddPC()
405: @*/
406: int PCCompositeGetPC(PC pc,int n,PC *subpc)
407: {
408: int ierr,(*f)(PC,int,PC *);
412: PetscObjectQueryFunction((PetscObject)pc,"PCCompositeGetPC_C",(void (**)(void))&f);
413: if (f) {
414: (*f)(pc,n,subpc);
415: } else {
416: SETERRQ(1,"Cannot get pc, not composite type");
417: }
418: return(0);
419: }
421: /*@
422: PCCompositeSetUseTrue - Sets a flag to indicate that the true matrix (rather than
423: the matrix used to define the preconditioner) is used to compute
424: the residual when the multiplicative scheme is used.
426: Collective on PC
428: Input Parameters:
429: . pc - the preconditioner context
431: Options Database Key:
432: . -pc_composite_true - Activates PCCompositeSetUseTrue()
434: Note:
435: For the common case in which the preconditioning and linear
436: system matrices are identical, this routine is unnecessary.
438: Level: Developer
440: .keywords: PC, composite preconditioner, set, true, flag
442: .seealso: PCSetOperators(), PCBJacobiSetUseTrueLocal(), PCSLESSetUseTrue()
443: @*/
444: int PCCompositeSetUseTrue(PC pc)
445: {
446: int ierr,(*f)(PC);
450: PetscObjectQueryFunction((PetscObject)pc,"PCCompositeSetUseTrue_C",(void (**)(void))&f);
451: if (f) {
452: (*f)(pc);
453: }
454: return(0);
455: }
457: /* -------------------------------------------------------------------------------------------*/
459: EXTERN_C_BEGIN
460: int PCCreate_Composite(PC pc)
461: {
462: int ierr;
463: PC_Composite *jac;
466: PetscNew(PC_Composite,&jac);
467: PetscLogObjectMemory(pc,sizeof(PC_Composite));
468: pc->ops->apply = PCApply_Composite_Additive;
469: pc->ops->setup = PCSetUp_Composite;
470: pc->ops->destroy = PCDestroy_Composite;
471: pc->ops->setfromoptions = PCSetFromOptions_Composite;
472: pc->ops->view = PCView_Composite;
473: pc->ops->applyrichardson = 0;
475: pc->data = (void*)jac;
476: jac->type = PC_COMPOSITE_ADDITIVE;
477: jac->work1 = 0;
478: jac->work2 = 0;
479: jac->head = 0;
481: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCompositeSetType_C","PCCompositeSetType_Composite",
482: PCCompositeSetType_Composite);
483: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCompositeAddPC_C","PCCompositeAddPC_Composite",
484: PCCompositeAddPC_Composite);
485: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCompositeGetPC_C","PCCompositeGetPC_Composite",
486: PCCompositeGetPC_Composite);
487: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCompositeSetUseTrue_C","PCCompositeSetUseTrue_Composite",
488: PCCompositeSetUseTrue_Composite);
489: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCompositeSpecialSetAlpha_C","PCCompositeSpecialSetAlpha_Composite",
490: PCCompositeSpecialSetAlpha_Composite);
492: return(0);
493: }
494: EXTERN_C_END