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