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 PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 30 31 /* Set the reuse flag on children PCs */ 32 while (next) { 33 PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 34 next = next->next; 35 } 36 next = jac->head; 37 38 if (next->next && !jac->work2) { /* allocate second work vector */ 39 PetscCall(VecDuplicate(jac->work1, &jac->work2)); 40 } 41 if (pc->useAmat) mat = pc->mat; 42 PetscCall(PCApply(next->pc, x, y)); /* y <- B x */ 43 while (next->next) { 44 next = next->next; 45 PetscCall(MatMult(mat, y, jac->work1)); /* work1 <- A y */ 46 PetscCall(VecWAXPY(jac->work2, -1.0, jac->work1, x)); /* work2 <- x - work1 */ 47 PetscCall(PCApply(next->pc, jac->work2, jac->work1)); /* work1 <- C work2 */ 48 PetscCall(VecAXPY(y, 1.0, jac->work1)); /* y <- y + work1 = B x + C (x - A B x) = (B + C (1 - A B)) x */ 49 } 50 if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 51 while (next->previous) { 52 next = next->previous; 53 PetscCall(MatMult(mat, y, jac->work1)); 54 PetscCall(VecWAXPY(jac->work2, -1.0, jac->work1, x)); 55 PetscCall(PCApply(next->pc, jac->work2, jac->work1)); 56 PetscCall(VecAXPY(y, 1.0, jac->work1)); 57 } 58 } 59 PetscFunctionReturn(PETSC_SUCCESS); 60 } 61 62 static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc, Vec x, Vec y) 63 { 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(PETSC_SUCCESS); 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 { 104 PC_Composite *jac = (PC_Composite *)pc->data; 105 PC_CompositeLink next = jac->head; 106 107 PetscFunctionBegin; 108 PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 109 PetscCheck(next->next && !next->next->next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Special composite preconditioners requires exactly two PCs"); 110 111 /* Set the reuse flag on children PCs */ 112 PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 113 PetscCall(PCSetReusePreconditioner(next->next->pc, pc->reusepreconditioner)); 114 115 PetscCall(PCApply(next->pc, x, jac->work1)); 116 PetscCall(PCApply(next->next->pc, jac->work1, y)); 117 PetscFunctionReturn(PETSC_SUCCESS); 118 } 119 120 static PetscErrorCode PCApply_Composite_Additive(PC pc, Vec x, Vec y) 121 { 122 PC_Composite *jac = (PC_Composite *)pc->data; 123 PC_CompositeLink next = jac->head; 124 125 PetscFunctionBegin; 126 PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 127 128 /* Set the reuse flag on children PCs */ 129 while (next) { 130 PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 131 next = next->next; 132 } 133 next = jac->head; 134 135 PetscCall(PCApply(next->pc, x, y)); 136 while (next->next) { 137 next = next->next; 138 PetscCall(PCApply(next->pc, x, jac->work1)); 139 PetscCall(VecAXPY(y, 1.0, jac->work1)); 140 } 141 PetscFunctionReturn(PETSC_SUCCESS); 142 } 143 144 static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc, Vec x, Vec y) 145 { 146 PC_Composite *jac = (PC_Composite *)pc->data; 147 PC_CompositeLink next = jac->head; 148 149 PetscFunctionBegin; 150 PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 151 PetscCall(PCApplyTranspose(next->pc, x, y)); 152 while (next->next) { 153 next = next->next; 154 PetscCall(PCApplyTranspose(next->pc, x, jac->work1)); 155 PetscCall(VecAXPY(y, 1.0, jac->work1)); 156 } 157 PetscFunctionReturn(PETSC_SUCCESS); 158 } 159 160 static PetscErrorCode PCSetUp_Composite(PC pc) 161 { 162 PC_Composite *jac = (PC_Composite *)pc->data; 163 PC_CompositeLink next = jac->head; 164 DM dm; 165 166 PetscFunctionBegin; 167 if (!jac->work1) PetscCall(MatCreateVecs(pc->pmat, &jac->work1, NULL)); 168 PetscCall(PCGetDM(pc, &dm)); 169 while (next) { 170 if (!next->pc->dm) PetscCall(PCSetDM(next->pc, dm)); 171 if (!next->pc->mat) PetscCall(PCSetOperators(next->pc, pc->mat, pc->pmat)); 172 next = next->next; 173 } 174 PetscFunctionReturn(PETSC_SUCCESS); 175 } 176 177 static PetscErrorCode PCSetUpOnBlocks_Composite(PC pc) 178 { 179 PC_Composite *jac = (PC_Composite *)pc->data; 180 PC_CompositeLink next = jac->head; 181 PCFailedReason reason; 182 183 PetscFunctionBegin; 184 while (next) { 185 PetscCall(PCSetUp(next->pc)); 186 PetscCall(PCGetFailedReasonRank(next->pc, &reason)); 187 if (reason) pc->failedreason = reason; 188 next = next->next; 189 } 190 PetscFunctionReturn(PETSC_SUCCESS); 191 } 192 193 static PetscErrorCode PCReset_Composite(PC pc) 194 { 195 PC_Composite *jac = (PC_Composite *)pc->data; 196 PC_CompositeLink next = jac->head; 197 198 PetscFunctionBegin; 199 while (next) { 200 PetscCall(PCReset(next->pc)); 201 next = next->next; 202 } 203 PetscCall(VecDestroy(&jac->work1)); 204 PetscCall(VecDestroy(&jac->work2)); 205 PetscFunctionReturn(PETSC_SUCCESS); 206 } 207 208 static PetscErrorCode PCDestroy_Composite(PC pc) 209 { 210 PC_Composite *jac = (PC_Composite *)pc->data; 211 PC_CompositeLink next = jac->head, next_tmp; 212 213 PetscFunctionBegin; 214 PetscCall(PCReset_Composite(pc)); 215 while (next) { 216 PetscCall(PCDestroy(&next->pc)); 217 next_tmp = next; 218 next = next->next; 219 PetscCall(PetscFree(next_tmp)); 220 } 221 PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSetType_C", NULL)); 222 PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetType_C", NULL)); 223 PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPCType_C", NULL)); 224 PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPC_C", NULL)); 225 PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetNumberPC_C", NULL)); 226 PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetPC_C", NULL)); 227 PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSpecialSetAlpha_C", NULL)); 228 PetscCall(PetscFree(pc->data)); 229 PetscFunctionReturn(PETSC_SUCCESS); 230 } 231 232 static PetscErrorCode PCSetFromOptions_Composite(PC pc, PetscOptionItems *PetscOptionsObject) 233 { 234 PC_Composite *jac = (PC_Composite *)pc->data; 235 PetscInt nmax, i; 236 PC_CompositeLink next; 237 char *pcs[1024]; 238 PetscBool flg; 239 240 PetscFunctionBegin; 241 PetscOptionsHeadBegin(PetscOptionsObject, "Composite preconditioner options"); 242 PetscCall(PetscOptionsEnum("-pc_composite_type", "Type of composition", "PCCompositeSetType", PCCompositeTypes, (PetscEnum)jac->type, (PetscEnum *)&jac->type, &flg)); 243 if (flg) PetscCall(PCCompositeSetType(pc, jac->type)); 244 nmax = (PetscInt)PETSC_STATIC_ARRAY_LENGTH(pcs); 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: [](ch_ksp), `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: [](ch_ksp), `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 $\alpha I + 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: [](ch_ksp), `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: [](ch_ksp), `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: [](ch_ksp), `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: [](ch_ksp), `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: [](ch_ksp), `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: [](ch_ksp), `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