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