Actual source code: composite.c
petsc-3.15.0 2021-03-30
Report Typos and Errors

      2: /*
      3:       Defines a preconditioner that can consist of a collection of PCs
      4: */
      5: #include <petsc/private/pcimpl.h>
      6: #include <petscksp.h>

      8: typedef struct _PC_CompositeLink *PC_CompositeLink;
      9: struct _PC_CompositeLink {
     10:   PC               pc;
     11:   PC_CompositeLink next;
     12:   PC_CompositeLink previous;
     13: };

     15: typedef struct {
     16:   PC_CompositeLink head;
     17:   PCCompositeType  type;
     18:   Vec              work1;
     19:   Vec              work2;
     20:   PetscScalar      alpha;
     21: } PC_Composite;

     23: static PetscErrorCode PCApply_Composite_Multiplicative(PC pc,Vec x,Vec y)
     24: {
     25:   PetscErrorCode   ierr;
     26:   PC_Composite     *jac = (PC_Composite*)pc->data;
     27:   PC_CompositeLink next = jac->head;
     28:   Mat              mat  = pc->pmat;

     32:   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs");

     34:   /* Set the reuse flag on children PCs */
     35:   while (next) {
     36:     PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);
     37:     next = next->next;
     38:   }
     39:   next = jac->head;

     41:   if (next->next && !jac->work2) { /* allocate second work vector */
     42:     VecDuplicate(jac->work1,&jac->work2);
     43:   }
     44:   if (pc->useAmat) mat = pc->mat;
     45:   PCApply(next->pc,x,y);                      /* y <- B x */
     46:   while (next->next) {
     47:     next = next->next;
     48:     MatMult(mat,y,jac->work1);                /* work1 <- A y */
     49:     VecWAXPY(jac->work2,-1.0,jac->work1,x);   /* work2 <- x - work1 */
     50:     PCApply(next->pc,jac->work2,jac->work1);  /* work1 <- C work2 */
     51:     VecAXPY(y,1.0,jac->work1);                /* y <- y + work1 = B x + C (x - A B x) = (B + C (1 - A B)) x */
     52:   }
     53:   if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
     54:     while (next->previous) {
     55:       next = next->previous;
     56:       MatMult(mat,y,jac->work1);
     57:       VecWAXPY(jac->work2,-1.0,jac->work1,x);
     58:       PCApply(next->pc,jac->work2,jac->work1);
     59:       VecAXPY(y,1.0,jac->work1);
     60:     }
     61:   }
     62:   return(0);
     63: }

     65: static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc,Vec x,Vec y)
     66: {
     67:   PetscErrorCode   ierr;
     68:   PC_Composite     *jac = (PC_Composite*)pc->data;
     69:   PC_CompositeLink next = jac->head;
     70:   Mat              mat  = pc->pmat;

     73:   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs");
     74:   if (next->next && !jac->work2) { /* allocate second work vector */
     75:     VecDuplicate(jac->work1,&jac->work2);
     76:   }
     77:   if (pc->useAmat) mat = pc->mat;
     78:   /* locate last PC */
     79:   while (next->next) {
     80:     next = next->next;
     81:   }
     82:   PCApplyTranspose(next->pc,x,y);
     83:   while (next->previous) {
     84:     next = next->previous;
     85:     MatMultTranspose(mat,y,jac->work1);
     86:     VecWAXPY(jac->work2,-1.0,jac->work1,x);
     87:     PCApplyTranspose(next->pc,jac->work2,jac->work1);
     88:     VecAXPY(y,1.0,jac->work1);
     89:   }
     90:   if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
     91:     next = jac->head;
     92:     while (next->next) {
     93:       next = next->next;
     94:       MatMultTranspose(mat,y,jac->work1);
     95:       VecWAXPY(jac->work2,-1.0,jac->work1,x);
     96:       PCApplyTranspose(next->pc,jac->work2,jac->work1);
     97:       VecAXPY(y,1.0,jac->work1);
     98:     }
     99:   }
    100:   return(0);
    101: }

    103: /*
    104:     This is very special for a matrix of the form alpha I + R + S
    105: where first preconditioner is built from alpha I + S and second from
    106: alpha I + R
    107: */
    108: static PetscErrorCode PCApply_Composite_Special(PC pc,Vec x,Vec y)
    109: {
    110:   PetscErrorCode   ierr;
    111:   PC_Composite     *jac = (PC_Composite*)pc->data;
    112:   PC_CompositeLink next = jac->head;

    115:   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs");
    116:   if (!next->next || next->next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Special composite preconditioners requires exactly two PCs");

    118:   /* Set the reuse flag on children PCs */
    119:   PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);
    120:   PCSetReusePreconditioner(next->next->pc,pc->reusepreconditioner);

    122:   PCApply(next->pc,x,jac->work1);
    123:   PCApply(next->next->pc,jac->work1,y);
    124:   return(0);
    125: }

    127: static PetscErrorCode PCApply_Composite_Additive(PC pc,Vec x,Vec y)
    128: {
    129:   PetscErrorCode   ierr;
    130:   PC_Composite     *jac = (PC_Composite*)pc->data;
    131:   PC_CompositeLink next = jac->head;

    134:   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs");

    136:   /* Set the reuse flag on children PCs */
    137:   while (next) {
    138:     PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);
    139:     next = next->next;
    140:   }
    141:   next = jac->head;

    143:   PCApply(next->pc,x,y);
    144:   while (next->next) {
    145:     next = next->next;
    146:     PCApply(next->pc,x,jac->work1);
    147:     VecAXPY(y,1.0,jac->work1);
    148:   }
    149:   return(0);
    150: }

    152: static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc,Vec x,Vec y)
    153: {
    154:   PetscErrorCode   ierr;
    155:   PC_Composite     *jac = (PC_Composite*)pc->data;
    156:   PC_CompositeLink next = jac->head;

    159:   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs");
    160:   PCApplyTranspose(next->pc,x,y);
    161:   while (next->next) {
    162:     next = next->next;
    163:     PCApplyTranspose(next->pc,x,jac->work1);
    164:     VecAXPY(y,1.0,jac->work1);
    165:   }
    166:   return(0);
    167: }

    169: static PetscErrorCode PCSetUp_Composite(PC pc)
    170: {
    171:   PetscErrorCode   ierr;
    172:   PC_Composite     *jac = (PC_Composite*)pc->data;
    173:   PC_CompositeLink next = jac->head;
    174:   DM               dm;

    177:   if (!jac->work1) {
    178:     MatCreateVecs(pc->pmat,&jac->work1,NULL);
    179:   }
    180:   PCGetDM(pc,&dm);
    181:   while (next) {
    182:     if (!next->pc->dm) {
    183:       PCSetDM(next->pc,dm);
    184:     }
    185:     if (!next->pc->mat) {
    186:       PCSetOperators(next->pc,pc->mat,pc->pmat);
    187:     }
    188:     next = next->next;
    189:   }
    190:   return(0);
    191: }

    193: static PetscErrorCode PCReset_Composite(PC pc)
    194: {
    195:   PC_Composite     *jac = (PC_Composite*)pc->data;
    196:   PetscErrorCode   ierr;
    197:   PC_CompositeLink next = jac->head;

    200:   while (next) {
    201:     PCReset(next->pc);
    202:     next = next->next;
    203:   }
    204:   VecDestroy(&jac->work1);
    205:   VecDestroy(&jac->work2);
    206:   return(0);
    207: }

    209: static PetscErrorCode PCDestroy_Composite(PC pc)
    210: {
    211:   PC_Composite     *jac = (PC_Composite*)pc->data;
    212:   PetscErrorCode   ierr;
    213:   PC_CompositeLink next = jac->head,next_tmp;

    216:   PCReset_Composite(pc);
    217:   while (next) {
    218:     PCDestroy(&next->pc);
    219:     next_tmp = next;
    220:     next     = next->next;
    221:     PetscFree(next_tmp);
    222:   }
    223:   PetscFree(pc->data);
    224:   return(0);
    225: }

    227: static PetscErrorCode PCSetFromOptions_Composite(PetscOptionItems *PetscOptionsObject,PC pc)
    228: {
    229:   PC_Composite     *jac = (PC_Composite*)pc->data;
    230:   PetscErrorCode   ierr;
    231:   PetscInt         nmax = 8,i;
    232:   PC_CompositeLink next;
    233:   char             *pcs[8];
    234:   PetscBool        flg;

    237:   PetscOptionsHead(PetscOptionsObject,"Composite preconditioner options");
    238:   PetscOptionsEnum("-pc_composite_type","Type of composition","PCCompositeSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg);
    239:   if (flg) {
    240:     PCCompositeSetType(pc,jac->type);
    241:   }
    242:   PetscOptionsStringArray("-pc_composite_pcs","List of composite solvers","PCCompositeAddPCType",pcs,&nmax,&flg);
    243:   if (flg) {
    244:     for (i=0; i<nmax; i++) {
    245:       PCCompositeAddPCType(pc,pcs[i]);
    246:       PetscFree(pcs[i]);   /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */
    247:     }
    248:   }
    249:   PetscOptionsTail();

    251:   next = jac->head;
    252:   while (next) {
    253:     PCSetFromOptions(next->pc);
    254:     next = next->next;
    255:   }
    256:   return(0);
    257: }

    259: static PetscErrorCode PCView_Composite(PC pc,PetscViewer viewer)
    260: {
    261:   PC_Composite     *jac = (PC_Composite*)pc->data;
    262:   PetscErrorCode   ierr;
    263:   PC_CompositeLink next = jac->head;
    264:   PetscBool        iascii;

    267:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    268:   if (iascii) {
    269:     PetscViewerASCIIPrintf(viewer,"Composite PC type - %s\n",PCCompositeTypes[jac->type]);
    270:     PetscViewerASCIIPrintf(viewer,"PCs on composite preconditioner follow\n");
    271:     PetscViewerASCIIPrintf(viewer,"---------------------------------\n");
    272:   }
    273:   if (iascii) {
    274:     PetscViewerASCIIPushTab(viewer);
    275:   }
    276:   while (next) {
    277:     PCView(next->pc,viewer);
    278:     next = next->next;
    279:   }
    280:   if (iascii) {
    281:     PetscViewerASCIIPopTab(viewer);
    282:     PetscViewerASCIIPrintf(viewer,"---------------------------------\n");
    283:   }
    284:   return(0);
    285: }

    287: /* ------------------------------------------------------------------------------*/

    289: static PetscErrorCode  PCCompositeSpecialSetAlpha_Composite(PC pc,PetscScalar alpha)
    290: {
    291:   PC_Composite *jac = (PC_Composite*)pc->data;

    294:   jac->alpha = alpha;
    295:   return(0);
    296: }

    298: static PetscErrorCode  PCCompositeSetType_Composite(PC pc,PCCompositeType type)
    299: {
    300:   PC_Composite *jac = (PC_Composite*)pc->data;

    303:   if (type == PC_COMPOSITE_ADDITIVE) {
    304:     pc->ops->apply          = PCApply_Composite_Additive;
    305:     pc->ops->applytranspose = PCApplyTranspose_Composite_Additive;
    306:   } else if (type ==  PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
    307:     pc->ops->apply          = PCApply_Composite_Multiplicative;
    308:     pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative;
    309:   } else if (type ==  PC_COMPOSITE_SPECIAL) {
    310:     pc->ops->apply          = PCApply_Composite_Special;
    311:     pc->ops->applytranspose = NULL;
    312:   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unknown composite preconditioner type");
    313:   jac->type = type;
    314:   return(0);
    315: }

    317: static PetscErrorCode  PCCompositeGetType_Composite(PC pc,PCCompositeType *type)
    318: {
    319:   PC_Composite *jac = (PC_Composite*)pc->data;

    322:   *type = jac->type;
    323:   return(0);
    324: }

    326: static PetscErrorCode PCCompositeAddPC_Composite(PC pc, PC subpc)
    327: {
    328:   PC_Composite    *jac;
    329:   PC_CompositeLink next, ilink;
    330:   PetscInt         cnt = 0;
    331:   const char      *prefix;
    332:   char             newprefix[20];
    333:   PetscErrorCode   ierr;

    336:   PetscNewLog(pc, &ilink);
    337:   ilink->next = NULL;
    338:   ilink->pc   = subpc;

    340:   jac  = (PC_Composite *) pc->data;
    341:   next = jac->head;
    342:   if (!next) {
    343:     jac->head       = ilink;
    344:     ilink->previous = NULL;
    345:   } else {
    346:     cnt++;
    347:     while (next->next) {
    348:       next = next->next;
    349:       cnt++;
    350:     }
    351:     next->next      = ilink;
    352:     ilink->previous = next;
    353:   }
    354:   PCGetOptionsPrefix(pc, &prefix);
    355:   PCSetOptionsPrefix(subpc, prefix);
    356:   PetscSNPrintf(newprefix, 20, "sub_%d_", (int) cnt);
    357:   PCAppendOptionsPrefix(subpc, newprefix);
    358:   PetscObjectReference((PetscObject) subpc);
    359:   return(0);
    360: }

    362: static PetscErrorCode PCCompositeAddPCType_Composite(PC pc, PCType type)
    363: {
    364:   PC             subpc;

    368:   PCCreate(PetscObjectComm((PetscObject)pc), &subpc);
    369:   PetscObjectIncrementTabLevel((PetscObject) subpc, (PetscObject) pc, 1);
    370:   PetscLogObjectParent((PetscObject) pc, (PetscObject) subpc);
    371:   PCCompositeAddPC_Composite(pc, subpc);
    372:   /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */
    373:   PCSetType(subpc, type);
    374:   PCDestroy(&subpc);
    375:   return(0);
    376: }

    378: static PetscErrorCode  PCCompositeGetNumberPC_Composite(PC pc,PetscInt *n)
    379: {
    380:   PC_Composite     *jac;
    381:   PC_CompositeLink next;

    384:   jac  = (PC_Composite*)pc->data;
    385:   next = jac->head;
    386:   *n = 0;
    387:   while (next) {
    388:     next = next->next;
    389:     (*n) ++;
    390:   }
    391:   return(0);
    392: }

    394: static PetscErrorCode  PCCompositeGetPC_Composite(PC pc,PetscInt n,PC *subpc)
    395: {
    396:   PC_Composite     *jac;
    397:   PC_CompositeLink next;
    398:   PetscInt         i;

    401:   jac  = (PC_Composite*)pc->data;
    402:   next = jac->head;
    403:   for (i=0; i<n; i++) {
    404:     if (!next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Not enough PCs in composite preconditioner");
    405:     next = next->next;
    406:   }
    407:   *subpc = next->pc;
    408:   return(0);
    409: }

    411: /* -------------------------------------------------------------------------------- */
    412: /*@
    413:    PCCompositeSetType - Sets the type of composite preconditioner.

    415:    Logically Collective on PC

    417:    Input Parameters:
    418: +  pc - the preconditioner context
    419: -  type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL

    421:    Options Database Key:
    422: .  -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type

    424:    Level: Developer

    426: @*/
    427: PetscErrorCode  PCCompositeSetType(PC pc,PCCompositeType type)
    428: {

    434:   PetscTryMethod(pc,"PCCompositeSetType_C",(PC,PCCompositeType),(pc,type));
    435:   return(0);
    436: }

    438: /*@
    439:    PCCompositeGetType - Gets the type of composite preconditioner.

    441:    Logically Collective on PC

    443:    Input Parameter:
    444: .  pc - the preconditioner context

    446:    Output Parameter:
    447: .  type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL

    449:    Options Database Key:
    450: .  -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type

    452:    Level: Developer

    454: @*/
    455: PetscErrorCode  PCCompositeGetType(PC pc,PCCompositeType *type)
    456: {

    461:   PetscUseMethod(pc,"PCCompositeGetType_C",(PC,PCCompositeType*),(pc,type));
    462:   return(0);
    463: }

    465: /*@
    466:    PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner
    467:      for alphaI + R + S

    469:    Logically Collective on PC

    471:    Input Parameter:
    472: +  pc - the preconditioner context
    473: -  alpha - scale on identity

    475:    Level: Developer

    477: @*/
    478: PetscErrorCode  PCCompositeSpecialSetAlpha(PC pc,PetscScalar alpha)
    479: {

    485:   PetscTryMethod(pc,"PCCompositeSpecialSetAlpha_C",(PC,PetscScalar),(pc,alpha));
    486:   return(0);
    487: }

    489: /*@C
    490:   PCCompositeAddPCType - Adds another PC of the given type to the composite PC.

    492:   Collective on PC

    494:   Input Parameters:
    495: + pc - the preconditioner context
    496: - type - the type of the new preconditioner

    498:   Level: Developer

    500: .seealso: PCCompositeAddPC()
    501: @*/
    502: PetscErrorCode  PCCompositeAddPCType(PC pc,PCType type)
    503: {

    508:   PetscTryMethod(pc,"PCCompositeAddPCType_C",(PC,PCType),(pc,type));
    509:   return(0);
    510: }

    512: /*@
    513:   PCCompositeAddPC - Adds another PC to the composite PC.

    515:   Collective on PC

    517:   Input Parameters:
    518: + pc    - the preconditioner context
    519: - subpc - the new preconditioner

    521:    Level: Developer

    523: .seealso: PCCompositeAddPCType()
    524: @*/
    525: PetscErrorCode PCCompositeAddPC(PC pc, PC subpc)
    526: {

    532:   PetscTryMethod(pc,"PCCompositeAddPC_C",(PC,PC),(pc,subpc));
    533:   return(0);
    534: }

    536: /*@
    537:    PCCompositeGetNumberPC - Gets the number of PC objects in the composite PC.

    539:    Not Collective

    541:    Input Parameter:
    542: .  pc - the preconditioner context

    544:    Output Parameter:
    545: .  num - the number of sub pcs

    547:    Level: Developer

    549: .seealso: PCCompositeGetPC()
    550: @*/
    551: PetscErrorCode  PCCompositeGetNumberPC(PC pc,PetscInt *num)
    552: {

    558:   PetscUseMethod(pc,"PCCompositeGetNumberPC_C",(PC,PetscInt*),(pc,num));
    559:   return(0);
    560: }

    562: /*@
    563:    PCCompositeGetPC - Gets one of the PC objects in the composite PC.

    565:    Not Collective

    567:    Input Parameter:
    568: +  pc - the preconditioner context
    569: -  n - the number of the pc requested

    571:    Output Parameters:
    572: .  subpc - the PC requested

    574:    Level: Developer

    576:     Notes:
    577:     To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then
    578:             call PCSetOperators() on that PC.

    580: .seealso: PCCompositeAddPCType(), PCCompositeGetNumberPC(), PCSetOperators()
    581: @*/
    582: PetscErrorCode PCCompositeGetPC(PC pc,PetscInt n,PC *subpc)
    583: {

    589:   PetscUseMethod(pc,"PCCompositeGetPC_C",(PC,PetscInt,PC*),(pc,n,subpc));
    590:   return(0);
    591: }

    593: /* -------------------------------------------------------------------------------------------*/

    595: /*MC
    596:      PCCOMPOSITE - Build a preconditioner by composing together several preconditioners

    598:    Options Database Keys:
    599: +  -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type
    600: .  -pc_use_amat - activates PCSetUseAmat()
    601: -  -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose

    603:    Level: intermediate

    605:    Notes:
    606:     To use a Krylov method inside the composite preconditioner, set the PCType of one or more
    607:           inner PCs to be PCKSP.
    608:           Using a Krylov method inside another Krylov method can be dangerous (you get divergence or
    609:           the incorrect answer) unless you use KSPFGMRES as the outer Krylov method
    610:           To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then
    611:           call PCSetOperators() on that PC.

    614: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
    615:            PCSHELL, PCKSP, PCCompositeSetType(), PCCompositeSpecialSetAlpha(), PCCompositeAddPCType(),
    616:            PCCompositeGetPC(), PCSetUseAmat()

    618: M*/

    620: PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc)
    621: {
    623:   PC_Composite   *jac;

    626:   PetscNewLog(pc,&jac);

    628:   pc->ops->apply           = PCApply_Composite_Additive;
    629:   pc->ops->applytranspose  = PCApplyTranspose_Composite_Additive;
    630:   pc->ops->setup           = PCSetUp_Composite;
    631:   pc->ops->reset           = PCReset_Composite;
    632:   pc->ops->destroy         = PCDestroy_Composite;
    633:   pc->ops->setfromoptions  = PCSetFromOptions_Composite;
    634:   pc->ops->view            = PCView_Composite;
    635:   pc->ops->applyrichardson = NULL;

    637:   pc->data   = (void*)jac;
    638:   jac->type  = PC_COMPOSITE_ADDITIVE;
    639:   jac->work1 = NULL;
    640:   jac->work2 = NULL;
    641:   jac->head  = NULL;

    643:   PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSetType_C",PCCompositeSetType_Composite);
    644:   PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetType_C",PCCompositeGetType_Composite);
    645:   PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPCType_C",PCCompositeAddPCType_Composite);
    646:   PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPC_C",PCCompositeAddPC_Composite);
    647:   PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetNumberPC_C",PCCompositeGetNumberPC_Composite);
    648:   PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetPC_C",PCCompositeGetPC_Composite);
    649:   PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",PCCompositeSpecialSetAlpha_Composite);
    650:   return(0);
    651: }