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