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