1 2 /* 3 Defines a preconditioner that can consist of a collection of PCs 4 */ 5 #include <petsc/private/pcimpl.h> 6 #include <petscksp.h> /*I "petscksp.h" I*/ 7 8 typedef struct _PC_CompositeLink *PC_CompositeLink; 9 struct _PC_CompositeLink { 10 PC pc; 11 PC_CompositeLink next; 12 PC_CompositeLink previous; 13 }; 14 15 typedef struct { 16 PC_CompositeLink head; 17 PCCompositeType type; 18 Vec work1; 19 Vec work2; 20 PetscScalar alpha; 21 } PC_Composite; 22 23 static PetscErrorCode PCApply_Composite_Multiplicative(PC pc,Vec x,Vec y) 24 { 25 PC_Composite *jac = (PC_Composite*)pc->data; 26 PC_CompositeLink next = jac->head; 27 Mat mat = pc->pmat; 28 29 PetscFunctionBegin; 30 31 PetscCheck(next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 32 33 /* Set the reuse flag on children PCs */ 34 while (next) { 35 PetscCall(PCSetReusePreconditioner(next->pc,pc->reusepreconditioner)); 36 next = next->next; 37 } 38 next = jac->head; 39 40 if (next->next && !jac->work2) { /* allocate second work vector */ 41 PetscCall(VecDuplicate(jac->work1,&jac->work2)); 42 } 43 if (pc->useAmat) mat = pc->mat; 44 PetscCall(PCApply(next->pc,x,y)); /* y <- B x */ 45 while (next->next) { 46 next = next->next; 47 PetscCall(MatMult(mat,y,jac->work1)); /* work1 <- A y */ 48 PetscCall(VecWAXPY(jac->work2,-1.0,jac->work1,x)); /* work2 <- x - work1 */ 49 PetscCall(PCApply(next->pc,jac->work2,jac->work1)); /* work1 <- C work2 */ 50 PetscCall(VecAXPY(y,1.0,jac->work1)); /* y <- y + work1 = B x + C (x - A B x) = (B + C (1 - A B)) x */ 51 } 52 if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 53 while (next->previous) { 54 next = next->previous; 55 PetscCall(MatMult(mat,y,jac->work1)); 56 PetscCall(VecWAXPY(jac->work2,-1.0,jac->work1,x)); 57 PetscCall(PCApply(next->pc,jac->work2,jac->work1)); 58 PetscCall(VecAXPY(y,1.0,jac->work1)); 59 } 60 } 61 PetscFunctionReturn(0); 62 } 63 64 static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc,Vec x,Vec y) 65 { 66 PC_Composite *jac = (PC_Composite*)pc->data; 67 PC_CompositeLink next = jac->head; 68 Mat mat = pc->pmat; 69 70 PetscFunctionBegin; 71 PetscCheck(next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 72 if (next->next && !jac->work2) { /* allocate second work vector */ 73 PetscCall(VecDuplicate(jac->work1,&jac->work2)); 74 } 75 if (pc->useAmat) mat = pc->mat; 76 /* locate last PC */ 77 while (next->next) { 78 next = next->next; 79 } 80 PetscCall(PCApplyTranspose(next->pc,x,y)); 81 while (next->previous) { 82 next = next->previous; 83 PetscCall(MatMultTranspose(mat,y,jac->work1)); 84 PetscCall(VecWAXPY(jac->work2,-1.0,jac->work1,x)); 85 PetscCall(PCApplyTranspose(next->pc,jac->work2,jac->work1)); 86 PetscCall(VecAXPY(y,1.0,jac->work1)); 87 } 88 if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 89 next = jac->head; 90 while (next->next) { 91 next = next->next; 92 PetscCall(MatMultTranspose(mat,y,jac->work1)); 93 PetscCall(VecWAXPY(jac->work2,-1.0,jac->work1,x)); 94 PetscCall(PCApplyTranspose(next->pc,jac->work2,jac->work1)); 95 PetscCall(VecAXPY(y,1.0,jac->work1)); 96 } 97 } 98 PetscFunctionReturn(0); 99 } 100 101 /* 102 This is very special for a matrix of the form alpha I + R + S 103 where first preconditioner is built from alpha I + S and second from 104 alpha I + R 105 */ 106 static PetscErrorCode PCApply_Composite_Special(PC pc,Vec x,Vec y) 107 { 108 PC_Composite *jac = (PC_Composite*)pc->data; 109 PC_CompositeLink next = jac->head; 110 111 PetscFunctionBegin; 112 PetscCheck(next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 113 PetscCheck(next->next && !next->next->next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Special composite preconditioners requires exactly two PCs"); 114 115 /* Set the reuse flag on children PCs */ 116 PetscCall(PCSetReusePreconditioner(next->pc,pc->reusepreconditioner)); 117 PetscCall(PCSetReusePreconditioner(next->next->pc,pc->reusepreconditioner)); 118 119 PetscCall(PCApply(next->pc,x,jac->work1)); 120 PetscCall(PCApply(next->next->pc,jac->work1,y)); 121 PetscFunctionReturn(0); 122 } 123 124 static PetscErrorCode PCApply_Composite_Additive(PC pc,Vec x,Vec y) 125 { 126 PC_Composite *jac = (PC_Composite*)pc->data; 127 PC_CompositeLink next = jac->head; 128 129 PetscFunctionBegin; 130 PetscCheck(next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 131 132 /* Set the reuse flag on children PCs */ 133 while (next) { 134 PetscCall(PCSetReusePreconditioner(next->pc,pc->reusepreconditioner)); 135 next = next->next; 136 } 137 next = jac->head; 138 139 PetscCall(PCApply(next->pc,x,y)); 140 while (next->next) { 141 next = next->next; 142 PetscCall(PCApply(next->pc,x,jac->work1)); 143 PetscCall(VecAXPY(y,1.0,jac->work1)); 144 } 145 PetscFunctionReturn(0); 146 } 147 148 static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc,Vec x,Vec y) 149 { 150 PC_Composite *jac = (PC_Composite*)pc->data; 151 PC_CompositeLink next = jac->head; 152 153 PetscFunctionBegin; 154 PetscCheck(next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 155 PetscCall(PCApplyTranspose(next->pc,x,y)); 156 while (next->next) { 157 next = next->next; 158 PetscCall(PCApplyTranspose(next->pc,x,jac->work1)); 159 PetscCall(VecAXPY(y,1.0,jac->work1)); 160 } 161 PetscFunctionReturn(0); 162 } 163 164 static PetscErrorCode PCSetUp_Composite(PC pc) 165 { 166 PC_Composite *jac = (PC_Composite*)pc->data; 167 PC_CompositeLink next = jac->head; 168 DM dm; 169 170 PetscFunctionBegin; 171 if (!jac->work1) { 172 PetscCall(MatCreateVecs(pc->pmat,&jac->work1,NULL)); 173 } 174 PetscCall(PCGetDM(pc,&dm)); 175 while (next) { 176 if (!next->pc->dm) { 177 PetscCall(PCSetDM(next->pc,dm)); 178 } 179 if (!next->pc->mat) { 180 PetscCall(PCSetOperators(next->pc,pc->mat,pc->pmat)); 181 } 182 next = next->next; 183 } 184 PetscFunctionReturn(0); 185 } 186 187 static PetscErrorCode PCReset_Composite(PC pc) 188 { 189 PC_Composite *jac = (PC_Composite*)pc->data; 190 PC_CompositeLink next = jac->head; 191 192 PetscFunctionBegin; 193 while (next) { 194 PetscCall(PCReset(next->pc)); 195 next = next->next; 196 } 197 PetscCall(VecDestroy(&jac->work1)); 198 PetscCall(VecDestroy(&jac->work2)); 199 PetscFunctionReturn(0); 200 } 201 202 static PetscErrorCode PCDestroy_Composite(PC pc) 203 { 204 PC_Composite *jac = (PC_Composite*)pc->data; 205 PC_CompositeLink next = jac->head,next_tmp; 206 207 PetscFunctionBegin; 208 PetscCall(PCReset_Composite(pc)); 209 while (next) { 210 PetscCall(PCDestroy(&next->pc)); 211 next_tmp = next; 212 next = next->next; 213 PetscCall(PetscFree(next_tmp)); 214 } 215 PetscCall(PetscFree(pc->data)); 216 PetscFunctionReturn(0); 217 } 218 219 static PetscErrorCode PCSetFromOptions_Composite(PetscOptionItems *PetscOptionsObject,PC pc) 220 { 221 PC_Composite *jac = (PC_Composite*)pc->data; 222 PetscInt nmax = 8,i; 223 PC_CompositeLink next; 224 char *pcs[8]; 225 PetscBool flg; 226 227 PetscFunctionBegin; 228 PetscCall(PetscOptionsHead(PetscOptionsObject,"Composite preconditioner options")); 229 PetscCall(PetscOptionsEnum("-pc_composite_type","Type of composition","PCCompositeSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg)); 230 if (flg) { 231 PetscCall(PCCompositeSetType(pc,jac->type)); 232 } 233 PetscCall(PetscOptionsStringArray("-pc_composite_pcs","List of composite solvers","PCCompositeAddPCType",pcs,&nmax,&flg)); 234 if (flg) { 235 for (i=0; i<nmax; i++) { 236 PetscCall(PCCompositeAddPCType(pc,pcs[i])); 237 PetscCall(PetscFree(pcs[i])); /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */ 238 } 239 } 240 PetscCall(PetscOptionsTail()); 241 242 next = jac->head; 243 while (next) { 244 PetscCall(PCSetFromOptions(next->pc)); 245 next = next->next; 246 } 247 PetscFunctionReturn(0); 248 } 249 250 static PetscErrorCode PCView_Composite(PC pc,PetscViewer viewer) 251 { 252 PC_Composite *jac = (PC_Composite*)pc->data; 253 PC_CompositeLink next = jac->head; 254 PetscBool iascii; 255 256 PetscFunctionBegin; 257 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 258 if (iascii) { 259 PetscCall(PetscViewerASCIIPrintf(viewer,"Composite PC type - %s\n",PCCompositeTypes[jac->type])); 260 PetscCall(PetscViewerASCIIPrintf(viewer,"PCs on composite preconditioner follow\n")); 261 PetscCall(PetscViewerASCIIPrintf(viewer,"---------------------------------\n")); 262 } 263 if (iascii) { 264 PetscCall(PetscViewerASCIIPushTab(viewer)); 265 } 266 while (next) { 267 PetscCall(PCView(next->pc,viewer)); 268 next = next->next; 269 } 270 if (iascii) { 271 PetscCall(PetscViewerASCIIPopTab(viewer)); 272 PetscCall(PetscViewerASCIIPrintf(viewer,"---------------------------------\n")); 273 } 274 PetscFunctionReturn(0); 275 } 276 277 /* ------------------------------------------------------------------------------*/ 278 279 static PetscErrorCode PCCompositeSpecialSetAlpha_Composite(PC pc,PetscScalar alpha) 280 { 281 PC_Composite *jac = (PC_Composite*)pc->data; 282 283 PetscFunctionBegin; 284 jac->alpha = alpha; 285 PetscFunctionReturn(0); 286 } 287 288 static PetscErrorCode PCCompositeSetType_Composite(PC pc,PCCompositeType type) 289 { 290 PC_Composite *jac = (PC_Composite*)pc->data; 291 292 PetscFunctionBegin; 293 if (type == PC_COMPOSITE_ADDITIVE) { 294 pc->ops->apply = PCApply_Composite_Additive; 295 pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 296 } else if (type == PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 297 pc->ops->apply = PCApply_Composite_Multiplicative; 298 pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative; 299 } else if (type == PC_COMPOSITE_SPECIAL) { 300 pc->ops->apply = PCApply_Composite_Special; 301 pc->ops->applytranspose = NULL; 302 } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unknown composite preconditioner type"); 303 jac->type = type; 304 PetscFunctionReturn(0); 305 } 306 307 static PetscErrorCode PCCompositeGetType_Composite(PC pc,PCCompositeType *type) 308 { 309 PC_Composite *jac = (PC_Composite*)pc->data; 310 311 PetscFunctionBegin; 312 *type = jac->type; 313 PetscFunctionReturn(0); 314 } 315 316 static PetscErrorCode PCCompositeAddPC_Composite(PC pc, PC subpc) 317 { 318 PC_Composite *jac; 319 PC_CompositeLink next, ilink; 320 PetscInt cnt = 0; 321 const char *prefix; 322 char newprefix[20]; 323 324 PetscFunctionBegin; 325 PetscCall(PetscNewLog(pc, &ilink)); 326 ilink->next = NULL; 327 ilink->pc = subpc; 328 329 jac = (PC_Composite *) pc->data; 330 next = jac->head; 331 if (!next) { 332 jac->head = ilink; 333 ilink->previous = NULL; 334 } else { 335 cnt++; 336 while (next->next) { 337 next = next->next; 338 cnt++; 339 } 340 next->next = ilink; 341 ilink->previous = next; 342 } 343 PetscCall(PCGetOptionsPrefix(pc, &prefix)); 344 PetscCall(PCSetOptionsPrefix(subpc, prefix)); 345 PetscCall(PetscSNPrintf(newprefix, 20, "sub_%d_", (int) cnt)); 346 PetscCall(PCAppendOptionsPrefix(subpc, newprefix)); 347 PetscCall(PetscObjectReference((PetscObject) subpc)); 348 PetscFunctionReturn(0); 349 } 350 351 static PetscErrorCode PCCompositeAddPCType_Composite(PC pc, PCType type) 352 { 353 PC subpc; 354 355 PetscFunctionBegin; 356 PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &subpc)); 357 PetscCall(PetscObjectIncrementTabLevel((PetscObject) subpc, (PetscObject) pc, 1)); 358 PetscCall(PetscLogObjectParent((PetscObject) pc, (PetscObject) subpc)); 359 PetscCall(PCCompositeAddPC_Composite(pc, subpc)); 360 /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */ 361 PetscCall(PCSetType(subpc, type)); 362 PetscCall(PCDestroy(&subpc)); 363 PetscFunctionReturn(0); 364 } 365 366 static PetscErrorCode PCCompositeGetNumberPC_Composite(PC pc,PetscInt *n) 367 { 368 PC_Composite *jac; 369 PC_CompositeLink next; 370 371 PetscFunctionBegin; 372 jac = (PC_Composite*)pc->data; 373 next = jac->head; 374 *n = 0; 375 while (next) { 376 next = next->next; 377 (*n) ++; 378 } 379 PetscFunctionReturn(0); 380 } 381 382 static PetscErrorCode PCCompositeGetPC_Composite(PC pc,PetscInt n,PC *subpc) 383 { 384 PC_Composite *jac; 385 PC_CompositeLink next; 386 PetscInt i; 387 388 PetscFunctionBegin; 389 jac = (PC_Composite*)pc->data; 390 next = jac->head; 391 for (i=0; i<n; i++) { 392 PetscCheck(next->next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Not enough PCs in composite preconditioner"); 393 next = next->next; 394 } 395 *subpc = next->pc; 396 PetscFunctionReturn(0); 397 } 398 399 /* -------------------------------------------------------------------------------- */ 400 /*@ 401 PCCompositeSetType - Sets the type of composite preconditioner. 402 403 Logically Collective on PC 404 405 Input Parameters: 406 + pc - the preconditioner context 407 - type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 408 409 Options Database Key: 410 . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 411 412 Level: Developer 413 414 @*/ 415 PetscErrorCode PCCompositeSetType(PC pc,PCCompositeType type) 416 { 417 PetscFunctionBegin; 418 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 419 PetscValidLogicalCollectiveEnum(pc,type,2); 420 PetscTryMethod(pc,"PCCompositeSetType_C",(PC,PCCompositeType),(pc,type)); 421 PetscFunctionReturn(0); 422 } 423 424 /*@ 425 PCCompositeGetType - Gets the type of composite preconditioner. 426 427 Logically Collective on PC 428 429 Input Parameter: 430 . pc - the preconditioner context 431 432 Output Parameter: 433 . type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 434 435 Options Database Key: 436 . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 437 438 Level: Developer 439 440 @*/ 441 PetscErrorCode PCCompositeGetType(PC pc,PCCompositeType *type) 442 { 443 PetscFunctionBegin; 444 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 445 PetscUseMethod(pc,"PCCompositeGetType_C",(PC,PCCompositeType*),(pc,type)); 446 PetscFunctionReturn(0); 447 } 448 449 /*@ 450 PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner 451 for alphaI + R + S 452 453 Logically Collective on PC 454 455 Input Parameters: 456 + pc - the preconditioner context 457 - alpha - scale on identity 458 459 Level: Developer 460 461 @*/ 462 PetscErrorCode PCCompositeSpecialSetAlpha(PC pc,PetscScalar alpha) 463 { 464 PetscFunctionBegin; 465 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 466 PetscValidLogicalCollectiveScalar(pc,alpha,2); 467 PetscTryMethod(pc,"PCCompositeSpecialSetAlpha_C",(PC,PetscScalar),(pc,alpha)); 468 PetscFunctionReturn(0); 469 } 470 471 /*@C 472 PCCompositeAddPCType - Adds another PC of the given type to the composite PC. 473 474 Collective on PC 475 476 Input Parameters: 477 + pc - the preconditioner context 478 - type - the type of the new preconditioner 479 480 Level: Developer 481 482 .seealso: PCCompositeAddPC() 483 @*/ 484 PetscErrorCode PCCompositeAddPCType(PC pc,PCType type) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 488 PetscTryMethod(pc,"PCCompositeAddPCType_C",(PC,PCType),(pc,type)); 489 PetscFunctionReturn(0); 490 } 491 492 /*@ 493 PCCompositeAddPC - Adds another PC to the composite PC. 494 495 Collective on PC 496 497 Input Parameters: 498 + pc - the preconditioner context 499 - subpc - the new preconditioner 500 501 Level: Developer 502 503 .seealso: PCCompositeAddPCType() 504 @*/ 505 PetscErrorCode PCCompositeAddPC(PC pc, PC subpc) 506 { 507 PetscFunctionBegin; 508 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 509 PetscValidHeaderSpecific(subpc,PC_CLASSID,2); 510 PetscTryMethod(pc,"PCCompositeAddPC_C",(PC,PC),(pc,subpc)); 511 PetscFunctionReturn(0); 512 } 513 514 /*@ 515 PCCompositeGetNumberPC - Gets the number of PC objects in the composite PC. 516 517 Not Collective 518 519 Input Parameter: 520 . pc - the preconditioner context 521 522 Output Parameter: 523 . num - the number of sub pcs 524 525 Level: Developer 526 527 .seealso: PCCompositeGetPC() 528 @*/ 529 PetscErrorCode PCCompositeGetNumberPC(PC pc,PetscInt *num) 530 { 531 PetscFunctionBegin; 532 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 533 PetscValidIntPointer(num,2); 534 PetscUseMethod(pc,"PCCompositeGetNumberPC_C",(PC,PetscInt*),(pc,num)); 535 PetscFunctionReturn(0); 536 } 537 538 /*@ 539 PCCompositeGetPC - Gets one of the PC objects in the composite PC. 540 541 Not Collective 542 543 Input Parameters: 544 + pc - the preconditioner context 545 - n - the number of the pc requested 546 547 Output Parameters: 548 . subpc - the PC requested 549 550 Level: Developer 551 552 Notes: 553 To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then 554 call PCSetOperators() on that PC. 555 556 .seealso: PCCompositeAddPCType(), PCCompositeGetNumberPC(), PCSetOperators() 557 @*/ 558 PetscErrorCode PCCompositeGetPC(PC pc,PetscInt n,PC *subpc) 559 { 560 PetscFunctionBegin; 561 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 562 PetscValidPointer(subpc,3); 563 PetscUseMethod(pc,"PCCompositeGetPC_C",(PC,PetscInt,PC*),(pc,n,subpc)); 564 PetscFunctionReturn(0); 565 } 566 567 /* -------------------------------------------------------------------------------------------*/ 568 569 /*MC 570 PCCOMPOSITE - Build a preconditioner by composing together several preconditioners 571 572 Options Database Keys: 573 + -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 574 . -pc_use_amat - activates PCSetUseAmat() 575 - -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose 576 577 Level: intermediate 578 579 Notes: 580 To use a Krylov method inside the composite preconditioner, set the PCType of one or more 581 inner PCs to be PCKSP. 582 Using a Krylov method inside another Krylov method can be dangerous (you get divergence or 583 the incorrect answer) unless you use KSPFGMRES as the outer Krylov method 584 To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then 585 call PCSetOperators() on that PC. 586 587 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 588 PCSHELL, PCKSP, PCCompositeSetType(), PCCompositeSpecialSetAlpha(), PCCompositeAddPCType(), 589 PCCompositeGetPC(), PCSetUseAmat() 590 591 M*/ 592 593 PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc) 594 { 595 PC_Composite *jac; 596 597 PetscFunctionBegin; 598 PetscCall(PetscNewLog(pc,&jac)); 599 600 pc->ops->apply = PCApply_Composite_Additive; 601 pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 602 pc->ops->setup = PCSetUp_Composite; 603 pc->ops->reset = PCReset_Composite; 604 pc->ops->destroy = PCDestroy_Composite; 605 pc->ops->setfromoptions = PCSetFromOptions_Composite; 606 pc->ops->view = PCView_Composite; 607 pc->ops->applyrichardson = NULL; 608 609 pc->data = (void*)jac; 610 jac->type = PC_COMPOSITE_ADDITIVE; 611 jac->work1 = NULL; 612 jac->work2 = NULL; 613 jac->head = NULL; 614 615 PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSetType_C",PCCompositeSetType_Composite)); 616 PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetType_C",PCCompositeGetType_Composite)); 617 PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPCType_C",PCCompositeAddPCType_Composite)); 618 PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPC_C",PCCompositeAddPC_Composite)); 619 PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetNumberPC_C",PCCompositeGetNumberPC_Composite)); 620 PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetPC_C",PCCompositeGetPC_Composite)); 621 PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",PCCompositeSpecialSetAlpha_Composite)); 622 PetscFunctionReturn(0); 623 } 624