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(PetscOptions *PetscOptionsObject,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(PetscOptionsObject,"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__ "PCCompositeGetType_Composite" 321 static PetscErrorCode PCCompositeGetType_Composite(PC pc,PCCompositeType *type) 322 { 323 PC_Composite *jac = (PC_Composite*)pc->data; 324 325 PetscFunctionBegin; 326 *type = jac->type; 327 PetscFunctionReturn(0); 328 } 329 330 #undef __FUNCT__ 331 #define __FUNCT__ "PCCompositeAddPC_Composite" 332 static PetscErrorCode PCCompositeAddPC_Composite(PC pc,PCType type) 333 { 334 PC_Composite *jac; 335 PC_CompositeLink next,ilink; 336 PetscErrorCode ierr; 337 PetscInt cnt = 0; 338 const char *prefix; 339 char newprefix[8]; 340 341 PetscFunctionBegin; 342 ierr = PetscNewLog(pc,&ilink);CHKERRQ(ierr); 343 ilink->next = 0; 344 ierr = PCCreate(PetscObjectComm((PetscObject)pc),&ilink->pc);CHKERRQ(ierr); 345 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->pc);CHKERRQ(ierr); 346 347 jac = (PC_Composite*)pc->data; 348 next = jac->head; 349 if (!next) { 350 jac->head = ilink; 351 ilink->previous = NULL; 352 } else { 353 cnt++; 354 while (next->next) { 355 next = next->next; 356 cnt++; 357 } 358 next->next = ilink; 359 ilink->previous = next; 360 } 361 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 362 ierr = PCSetOptionsPrefix(ilink->pc,prefix);CHKERRQ(ierr); 363 sprintf(newprefix,"sub_%d_",(int)cnt); 364 ierr = PCAppendOptionsPrefix(ilink->pc,newprefix);CHKERRQ(ierr); 365 /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */ 366 ierr = PCSetType(ilink->pc,type);CHKERRQ(ierr); 367 PetscFunctionReturn(0); 368 } 369 370 #undef __FUNCT__ 371 #define __FUNCT__ "PCCompositeGetNumberPC_Composite" 372 static PetscErrorCode PCCompositeGetNumberPC_Composite(PC pc,PetscInt *n) 373 { 374 PC_Composite *jac; 375 PC_CompositeLink next; 376 377 PetscFunctionBegin; 378 jac = (PC_Composite*)pc->data; 379 next = jac->head; 380 *n = 0; 381 while (next) { 382 next = next->next; 383 (*n) ++; 384 } 385 PetscFunctionReturn(0); 386 } 387 388 #undef __FUNCT__ 389 #define __FUNCT__ "PCCompositeGetPC_Composite" 390 static PetscErrorCode PCCompositeGetPC_Composite(PC pc,PetscInt n,PC *subpc) 391 { 392 PC_Composite *jac; 393 PC_CompositeLink next; 394 PetscInt i; 395 396 PetscFunctionBegin; 397 jac = (PC_Composite*)pc->data; 398 next = jac->head; 399 for (i=0; i<n; i++) { 400 if (!next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Not enough PCs in composite preconditioner"); 401 next = next->next; 402 } 403 *subpc = next->pc; 404 PetscFunctionReturn(0); 405 } 406 407 /* -------------------------------------------------------------------------------- */ 408 #undef __FUNCT__ 409 #define __FUNCT__ "PCCompositeSetType" 410 /*@ 411 PCCompositeSetType - Sets the type of composite preconditioner. 412 413 Logically Collective on PC 414 415 Input Parameters: 416 + pc - the preconditioner context 417 - type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 418 419 Options Database Key: 420 . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 421 422 Level: Developer 423 424 .keywords: PC, set, type, composite preconditioner, additive, multiplicative 425 @*/ 426 PetscErrorCode PCCompositeSetType(PC pc,PCCompositeType type) 427 { 428 PetscErrorCode ierr; 429 430 PetscFunctionBegin; 431 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 432 PetscValidLogicalCollectiveEnum(pc,type,2); 433 ierr = PetscTryMethod(pc,"PCCompositeSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr); 434 PetscFunctionReturn(0); 435 } 436 437 #undef __FUNCT__ 438 #define __FUNCT__ "PCCompositeGetType" 439 /*@ 440 PCCompositeGetType - Gets the type of composite preconditioner. 441 442 Logically Collective on PC 443 444 Input Parameter: 445 . pc - the preconditioner context 446 447 Output Parameter: 448 . type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 449 450 Options Database Key: 451 . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 452 453 Level: Developer 454 455 .keywords: PC, set, type, composite preconditioner, additive, multiplicative 456 @*/ 457 PetscErrorCode PCCompositeGetType(PC pc,PCCompositeType *type) 458 { 459 PetscErrorCode ierr; 460 461 PetscFunctionBegin; 462 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 463 ierr = PetscUseMethod(pc,"PCCompositeGetType_C",(PC,PCCompositeType*),(pc,type));CHKERRQ(ierr); 464 PetscFunctionReturn(0); 465 } 466 467 #undef __FUNCT__ 468 #define __FUNCT__ "PCCompositeSpecialSetAlpha" 469 /*@ 470 PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner 471 for alphaI + R + S 472 473 Logically Collective on PC 474 475 Input Parameter: 476 + pc - the preconditioner context 477 - alpha - scale on identity 478 479 Level: Developer 480 481 .keywords: PC, set, type, composite preconditioner, additive, multiplicative 482 @*/ 483 PetscErrorCode PCCompositeSpecialSetAlpha(PC pc,PetscScalar alpha) 484 { 485 PetscErrorCode ierr; 486 487 PetscFunctionBegin; 488 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 489 PetscValidLogicalCollectiveScalar(pc,alpha,2); 490 ierr = PetscTryMethod(pc,"PCCompositeSpecialSetAlpha_C",(PC,PetscScalar),(pc,alpha));CHKERRQ(ierr); 491 PetscFunctionReturn(0); 492 } 493 494 #undef __FUNCT__ 495 #define __FUNCT__ "PCCompositeAddPC" 496 /*@C 497 PCCompositeAddPC - Adds another PC to the composite PC. 498 499 Collective on PC 500 501 Input Parameters: 502 + pc - the preconditioner context 503 - type - the type of the new preconditioner 504 505 Level: Developer 506 507 .keywords: PC, composite preconditioner, add 508 @*/ 509 PetscErrorCode PCCompositeAddPC(PC pc,PCType type) 510 { 511 PetscErrorCode ierr; 512 513 PetscFunctionBegin; 514 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 515 ierr = PetscTryMethod(pc,"PCCompositeAddPC_C",(PC,PCType),(pc,type));CHKERRQ(ierr); 516 PetscFunctionReturn(0); 517 } 518 519 #undef __FUNCT__ 520 #define __FUNCT__ "PCCompositeGetNumberPC" 521 /*@ 522 PCCompositeGetNumberPC - Gets the number of PC objects in the composite PC. 523 524 Not Collective 525 526 Input Parameter: 527 . pc - the preconditioner context 528 529 Output Parameter: 530 . num - the number of sub pcs 531 532 Level: Developer 533 534 .keywords: PC, get, composite preconditioner, sub preconditioner 535 536 .seealso: PCCompositeGetPC() 537 @*/ 538 PetscErrorCode PCCompositeGetNumberPC(PC pc,PetscInt *num) 539 { 540 PetscErrorCode ierr; 541 542 PetscFunctionBegin; 543 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 544 PetscValidIntPointer(num,2); 545 ierr = PetscUseMethod(pc,"PCCompositeGetNumberPC_C",(PC,PetscInt*),(pc,num));CHKERRQ(ierr); 546 PetscFunctionReturn(0); 547 } 548 549 #undef __FUNCT__ 550 #define __FUNCT__ "PCCompositeGetPC" 551 /*@ 552 PCCompositeGetPC - Gets one of the PC objects in the composite PC. 553 554 Not Collective 555 556 Input Parameter: 557 + pc - the preconditioner context 558 - n - the number of the pc requested 559 560 Output Parameters: 561 . subpc - the PC requested 562 563 Level: Developer 564 565 .keywords: PC, get, composite preconditioner, sub preconditioner 566 567 .seealso: PCCompositeAddPC(), PCCompositeGetNumberPC() 568 @*/ 569 PetscErrorCode PCCompositeGetPC(PC pc,PetscInt n,PC *subpc) 570 { 571 PetscErrorCode ierr; 572 573 PetscFunctionBegin; 574 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 575 PetscValidPointer(subpc,3); 576 ierr = PetscUseMethod(pc,"PCCompositeGetPC_C",(PC,PetscInt,PC*),(pc,n,subpc));CHKERRQ(ierr); 577 PetscFunctionReturn(0); 578 } 579 580 /* -------------------------------------------------------------------------------------------*/ 581 582 /*MC 583 PCCOMPOSITE - Build a preconditioner by composing together several preconditioners 584 585 Options Database Keys: 586 + -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 587 . -pc_use_amat - Activates PCSetUseAmat() 588 - -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose 589 590 Level: intermediate 591 592 Concepts: composing solvers 593 594 Notes: To use a Krylov method inside the composite preconditioner, set the PCType of one or more 595 inner PCs to be PCKSP. 596 Using a Krylov method inside another Krylov method can be dangerous (you get divergence or 597 the incorrect answer) unless you use KSPFGMRES as the outer Krylov method 598 599 600 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 601 PCSHELL, PCKSP, PCCompositeSetType(), PCCompositeSpecialSetAlpha(), PCCompositeAddPC(), 602 PCCompositeGetPC(), PCSetUseAmat() 603 604 M*/ 605 606 #undef __FUNCT__ 607 #define __FUNCT__ "PCCreate_Composite" 608 PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc) 609 { 610 PetscErrorCode ierr; 611 PC_Composite *jac; 612 613 PetscFunctionBegin; 614 ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr); 615 616 pc->ops->apply = PCApply_Composite_Additive; 617 pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 618 pc->ops->setup = PCSetUp_Composite; 619 pc->ops->reset = PCReset_Composite; 620 pc->ops->destroy = PCDestroy_Composite; 621 pc->ops->setfromoptions = PCSetFromOptions_Composite; 622 pc->ops->view = PCView_Composite; 623 pc->ops->applyrichardson = 0; 624 625 pc->data = (void*)jac; 626 jac->type = PC_COMPOSITE_ADDITIVE; 627 jac->work1 = 0; 628 jac->work2 = 0; 629 jac->head = 0; 630 631 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSetType_C",PCCompositeSetType_Composite);CHKERRQ(ierr); 632 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetType_C",PCCompositeGetType_Composite);CHKERRQ(ierr); 633 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPC_C",PCCompositeAddPC_Composite);CHKERRQ(ierr); 634 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetNumberPC_C",PCCompositeGetNumberPC_Composite);CHKERRQ(ierr); 635 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetPC_C",PCCompositeGetPC_Composite);CHKERRQ(ierr); 636 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",PCCompositeSpecialSetAlpha_Composite);CHKERRQ(ierr); 637 PetscFunctionReturn(0); 638 } 639 640