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