1 /*$Id: precon.c,v 1.216 2001/08/21 21:03:13 bsmith Exp $*/ 2 /* 3 The PC (preconditioner) interface routines, callable by users. 4 */ 5 #include "src/ksp/pc/pcimpl.h" /*I "petscksp.h" I*/ 6 7 /* Logging support */ 8 int PC_COOKIE = 0; 9 int PC_SetUp = 0, PC_SetUpOnBlocks = 0, PC_Apply = 0, PC_ApplyCoarse = 0, PC_ApplyMultiple = 0, PC_ApplySymmetricLeft = 0; 10 int PC_ApplySymmetricRight = 0, PC_ModifySubMatrices = 0; 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "PCGetDefaultType_Private" 14 int PCGetDefaultType_Private(PC pc,const char* type[]) 15 { 16 int ierr,size; 17 PetscTruth flg1,flg2,set,flg3; 18 19 PetscFunctionBegin; 20 ierr = MPI_Comm_size(pc->comm,&size);CHKERRQ(ierr); 21 if (pc->pmat) { 22 int (*f)(Mat,PetscTruth*,MatReuse,Mat*); 23 ierr = PetscObjectQueryFunction((PetscObject)pc->pmat,"MatGetDiagonalBlock_C",(void (**)(void))&f);CHKERRQ(ierr); 24 if (size == 1) { 25 ierr = MatHasOperation(pc->pmat,MATOP_ICCFACTOR_SYMBOLIC,&flg1);CHKERRQ(ierr); 26 ierr = MatHasOperation(pc->pmat,MATOP_ILUFACTOR_SYMBOLIC,&flg2);CHKERRQ(ierr); 27 ierr = MatIsSymmetricKnown(pc->pmat,&set,&flg3);CHKERRQ(ierr); 28 if (flg1 && (!flg2 || (set && flg3))) { 29 *type = PCICC; 30 } else if (flg2) { 31 *type = PCILU; 32 } else if (f) { /* likely is a parallel matrix run on one processor */ 33 *type = PCBJACOBI; 34 } else { 35 *type = PCNONE; 36 } 37 } else { 38 if (f) { 39 *type = PCBJACOBI; 40 } else { 41 *type = PCNONE; 42 } 43 } 44 } else { 45 if (size == 1) { 46 *type = PCILU; 47 } else { 48 *type = PCBJACOBI; 49 } 50 } 51 PetscFunctionReturn(0); 52 } 53 54 #undef __FUNCT__ 55 #define __FUNCT__ "PCNullSpaceAttach" 56 /*@C 57 PCNullSpaceAttach - attaches a null space to a preconditioner object. 58 This null space will be removed from the resulting vector whenever 59 the preconditioner is applied. 60 61 Collective on PC 62 63 Input Parameters: 64 + pc - the preconditioner context 65 - nullsp - the null space object 66 67 Level: developer 68 69 Notes: 70 Overwrites any previous null space that may have been attached 71 72 Users manual sections: 73 . sec_singular 74 75 .keywords: PC, destroy, null space 76 77 .seealso: PCCreate(), PCSetUp(), MatNullSpaceCreate(), MatNullSpace 78 79 @*/ 80 int PCNullSpaceAttach(PC pc,MatNullSpace nullsp) 81 { 82 int ierr; 83 84 PetscFunctionBegin; 85 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 86 PetscValidHeaderSpecific(nullsp,MAT_NULLSPACE_COOKIE,2); 87 88 if (pc->nullsp) { 89 ierr = MatNullSpaceDestroy(pc->nullsp);CHKERRQ(ierr); 90 } 91 pc->nullsp = nullsp; 92 ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr); 93 PetscFunctionReturn(0); 94 } 95 96 #undef __FUNCT__ 97 #define __FUNCT__ "PCDestroy" 98 /*@C 99 PCDestroy - Destroys PC context that was created with PCCreate(). 100 101 Collective on PC 102 103 Input Parameter: 104 . pc - the preconditioner context 105 106 Level: developer 107 108 .keywords: PC, destroy 109 110 .seealso: PCCreate(), PCSetUp() 111 @*/ 112 int PCDestroy(PC pc) 113 { 114 int ierr; 115 116 PetscFunctionBegin; 117 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 118 if (--pc->refct > 0) PetscFunctionReturn(0); 119 120 /* if memory was published with AMS then destroy it */ 121 ierr = PetscObjectDepublish(pc);CHKERRQ(ierr); 122 123 if (pc->ops->destroy) {ierr = (*pc->ops->destroy)(pc);CHKERRQ(ierr);} 124 if (pc->nullsp) {ierr = MatNullSpaceDestroy(pc->nullsp);CHKERRQ(ierr);} 125 if (pc->diagonalscaleright) {ierr = VecDestroy(pc->diagonalscaleright);CHKERRQ(ierr);} 126 if (pc->diagonalscaleleft) {ierr = VecDestroy(pc->diagonalscaleleft);CHKERRQ(ierr);} 127 128 PetscLogObjectDestroy(pc); 129 PetscHeaderDestroy(pc); 130 PetscFunctionReturn(0); 131 } 132 133 #undef __FUNCT__ 134 #define __FUNCT__ "PCDiagonalScale" 135 /*@C 136 PCDiagonalScale - Indicates if the preconditioner applies an additional left and right 137 scaling as needed by certain time-stepping codes. 138 139 Collective on PC 140 141 Input Parameter: 142 . pc - the preconditioner context 143 144 Output Parameter: 145 . flag - PETSC_TRUE if it applies the scaling 146 147 Level: developer 148 149 Notes: If this returns PETSC_TRUE then the system solved via the Krylov method is 150 $ D M A D^{-1} y = D M b for left preconditioning or 151 $ D A M D^{-1} z = D b for right preconditioning 152 153 .keywords: PC 154 155 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScaleSet() 156 @*/ 157 int PCDiagonalScale(PC pc,PetscTruth *flag) 158 { 159 PetscFunctionBegin; 160 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 161 PetscValidPointer(flag,2); 162 *flag = pc->diagonalscale; 163 PetscFunctionReturn(0); 164 } 165 166 #undef __FUNCT__ 167 #define __FUNCT__ "PCDiagonalScaleSet" 168 /*@ 169 PCDiagonalScaleSet - Indicates the left scaling to use to apply an additional left and right 170 scaling as needed by certain time-stepping codes. 171 172 Collective on PC 173 174 Input Parameters: 175 + pc - the preconditioner context 176 - s - scaling vector 177 178 Level: intermediate 179 180 Notes: The system solved via the Krylov method is 181 $ D M A D^{-1} y = D M b for left preconditioning or 182 $ D A M D^{-1} z = D b for right preconditioning 183 184 PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}. 185 186 .keywords: PC 187 188 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScale() 189 @*/ 190 int PCDiagonalScaleSet(PC pc,Vec s) 191 { 192 int ierr; 193 194 PetscFunctionBegin; 195 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 196 PetscValidHeaderSpecific(s,VEC_COOKIE,2); 197 pc->diagonalscale = PETSC_TRUE; 198 if (pc->diagonalscaleleft) { 199 ierr = VecDestroy(pc->diagonalscaleleft);CHKERRQ(ierr); 200 } 201 pc->diagonalscaleleft = s; 202 ierr = PetscObjectReference((PetscObject)s);CHKERRQ(ierr); 203 if (!pc->diagonalscaleright) { 204 ierr = VecDuplicate(s,&pc->diagonalscaleright);CHKERRQ(ierr); 205 } 206 ierr = VecCopy(s,pc->diagonalscaleright);CHKERRQ(ierr); 207 ierr = VecReciprocal(pc->diagonalscaleright);CHKERRQ(ierr); 208 PetscFunctionReturn(0); 209 } 210 211 #undef __FUNCT__ 212 #define __FUNCT__ "PCDiagonalScaleLeft" 213 /*@C 214 PCDiagonalScaleLeft - Indicates the left scaling to use to apply an additional left and right 215 scaling as needed by certain time-stepping codes. 216 217 Collective on PC 218 219 Input Parameters: 220 + pc - the preconditioner context 221 . in - input vector 222 + out - scaled vector (maybe the same as in) 223 224 Level: intermediate 225 226 Notes: The system solved via the Krylov method is 227 $ D M A D^{-1} y = D M b for left preconditioning or 228 $ D A M D^{-1} z = D b for right preconditioning 229 230 PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}. 231 232 If diagonal scaling is turned off and in is not out then in is copied to out 233 234 .keywords: PC 235 236 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale() 237 @*/ 238 int PCDiagonalScaleLeft(PC pc,Vec in,Vec out) 239 { 240 int ierr; 241 242 PetscFunctionBegin; 243 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 244 PetscValidHeaderSpecific(in,VEC_COOKIE,2); 245 PetscValidHeaderSpecific(out,VEC_COOKIE,3); 246 if (pc->diagonalscale) { 247 ierr = VecPointwiseMult(pc->diagonalscaleleft,in,out);CHKERRQ(ierr); 248 } else if (in != out) { 249 ierr = VecCopy(in,out);CHKERRQ(ierr); 250 } 251 PetscFunctionReturn(0); 252 } 253 254 #undef __FUNCT__ 255 #define __FUNCT__ "PCDiagonalScaleRight" 256 /*@C 257 PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes. 258 259 Collective on PC 260 261 Input Parameters: 262 + pc - the preconditioner context 263 . in - input vector 264 + out - scaled vector (maybe the same as in) 265 266 Level: intermediate 267 268 Notes: The system solved via the Krylov method is 269 $ D M A D^{-1} y = D M b for left preconditioning or 270 $ D A M D^{-1} z = D b for right preconditioning 271 272 PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}. 273 274 If diagonal scaling is turned off and in is not out then in is copied to out 275 276 .keywords: PC 277 278 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale() 279 @*/ 280 int PCDiagonalScaleRight(PC pc,Vec in,Vec out) 281 { 282 int ierr; 283 284 PetscFunctionBegin; 285 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 286 PetscValidHeaderSpecific(in,VEC_COOKIE,2); 287 PetscValidHeaderSpecific(out,VEC_COOKIE,3); 288 if (pc->diagonalscale) { 289 ierr = VecPointwiseMult(pc->diagonalscaleright,in,out);CHKERRQ(ierr); 290 } else if (in != out) { 291 ierr = VecCopy(in,out);CHKERRQ(ierr); 292 } 293 PetscFunctionReturn(0); 294 } 295 296 #undef __FUNCT__ 297 #define __FUNCT__ "PCPublish_Petsc" 298 static int PCPublish_Petsc(PetscObject obj) 299 { 300 #if defined(PETSC_HAVE_AMS) 301 PC v = (PC) obj; 302 int ierr; 303 #endif 304 305 PetscFunctionBegin; 306 307 #if defined(PETSC_HAVE_AMS) 308 /* if it is already published then return */ 309 if (v->amem >=0) PetscFunctionReturn(0); 310 311 ierr = PetscObjectPublishBaseBegin(obj);CHKERRQ(ierr); 312 ierr = PetscObjectPublishBaseEnd(obj);CHKERRQ(ierr); 313 #endif 314 315 PetscFunctionReturn(0); 316 } 317 318 #undef __FUNCT__ 319 #define __FUNCT__ "PCCreate" 320 /*@C 321 PCCreate - Creates a preconditioner context. 322 323 Collective on MPI_Comm 324 325 Input Parameter: 326 . comm - MPI communicator 327 328 Output Parameter: 329 . pc - location to put the preconditioner context 330 331 Notes: 332 The default preconditioner on one processor is PCILU with 0 fill on more 333 then one it is PCBJACOBI with ILU() on each processor. 334 335 Level: developer 336 337 .keywords: PC, create, context 338 339 .seealso: PCSetUp(), PCApply(), PCDestroy() 340 @*/ 341 int PCCreate(MPI_Comm comm,PC *newpc) 342 { 343 PC pc; 344 int ierr; 345 346 PetscFunctionBegin; 347 PetscValidPointer(newpc,1) 348 *newpc = 0; 349 #ifndef PETSC_USE_DYNAMIC_LIBRARIES 350 ierr = PCInitializePackage(PETSC_NULL); CHKERRQ(ierr); 351 #endif 352 353 PetscHeaderCreate(pc,_p_PC,struct _PCOps,PC_COOKIE,-1,"PC",comm,PCDestroy,PCView); 354 PetscLogObjectCreate(pc); 355 pc->bops->publish = PCPublish_Petsc; 356 pc->vec = 0; 357 pc->mat = 0; 358 pc->setupcalled = 0; 359 pc->nullsp = 0; 360 pc->data = 0; 361 pc->diagonalscale = PETSC_FALSE; 362 pc->diagonalscaleleft = 0; 363 pc->diagonalscaleright = 0; 364 365 pc->ops->destroy = 0; 366 pc->ops->apply = 0; 367 pc->ops->applytranspose = 0; 368 pc->ops->applyBA = 0; 369 pc->ops->applyBAtranspose = 0; 370 pc->ops->applyrichardson = 0; 371 pc->ops->view = 0; 372 pc->ops->getfactoredmatrix = 0; 373 pc->ops->applysymmetricright = 0; 374 pc->ops->applysymmetricleft = 0; 375 pc->ops->setuponblocks = 0; 376 377 pc->modifysubmatrices = 0; 378 pc->modifysubmatricesP = 0; 379 *newpc = pc; 380 ierr = PetscPublishAll(pc);CHKERRQ(ierr); 381 PetscFunctionReturn(0); 382 383 } 384 385 /* -------------------------------------------------------------------------------*/ 386 387 #undef __FUNCT__ 388 #define __FUNCT__ "PCApply" 389 /*@ 390 PCApply - Applies the preconditioner to a vector. 391 392 Collective on PC and Vec 393 394 Input Parameters: 395 + pc - the preconditioner context 396 - x - input vector 397 398 Output Parameter: 399 . y - output vector 400 401 Level: developer 402 403 .keywords: PC, apply 404 405 .seealso: PCApplyTranspose(), PCApplyBAorAB() 406 @*/ 407 int PCApply(PC pc,Vec x,Vec y,PCSide side) 408 { 409 int ierr; 410 411 PetscFunctionBegin; 412 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 413 PetscValidHeaderSpecific(x,VEC_COOKIE,2); 414 PetscValidHeaderSpecific(y,VEC_COOKIE,3); 415 if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 416 417 if (pc->setupcalled < 2) { 418 ierr = PCSetUp(pc);CHKERRQ(ierr); 419 } 420 421 /* Remove null space from input vector y */ 422 if (side == PC_RIGHT && pc->nullsp) { 423 Vec tmp; 424 ierr = MatNullSpaceRemove(pc->nullsp,x,&tmp);CHKERRQ(ierr); 425 x = tmp; 426 SETERRQ(1,"Cannot deflate out null space if using right preconditioner!"); 427 } 428 429 ierr = PetscLogEventBegin(PC_Apply,pc,x,y,0);CHKERRQ(ierr); 430 ierr = (*pc->ops->apply)(pc,x,y);CHKERRQ(ierr); 431 ierr = PetscLogEventEnd(PC_Apply,pc,x,y,0);CHKERRQ(ierr); 432 433 /* Remove null space from preconditioned vector y */ 434 if (side == PC_LEFT && pc->nullsp) { 435 ierr = MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);CHKERRQ(ierr); 436 } 437 PetscFunctionReturn(0); 438 } 439 440 #undef __FUNCT__ 441 #define __FUNCT__ "PCApplySymmetricLeft" 442 /*@ 443 PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector. 444 445 Collective on PC and Vec 446 447 Input Parameters: 448 + pc - the preconditioner context 449 - x - input vector 450 451 Output Parameter: 452 . y - output vector 453 454 Notes: 455 Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners. 456 457 Level: developer 458 459 .keywords: PC, apply, symmetric, left 460 461 .seealso: PCApply(), PCApplySymmetricRight() 462 @*/ 463 int PCApplySymmetricLeft(PC pc,Vec x,Vec y) 464 { 465 int ierr; 466 467 PetscFunctionBegin; 468 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 469 PetscValidHeaderSpecific(x,VEC_COOKIE,2); 470 PetscValidHeaderSpecific(y,VEC_COOKIE,3); 471 if (!pc->ops->applysymmetricleft) SETERRQ(1,"PC does not have left symmetric apply"); 472 473 if (pc->setupcalled < 2) { 474 ierr = PCSetUp(pc);CHKERRQ(ierr); 475 } 476 477 ierr = PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);CHKERRQ(ierr); 478 ierr = (*pc->ops->applysymmetricleft)(pc,x,y);CHKERRQ(ierr); 479 ierr = PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);CHKERRQ(ierr); 480 PetscFunctionReturn(0); 481 } 482 483 #undef __FUNCT__ 484 #define __FUNCT__ "PCApplySymmetricRight" 485 /*@ 486 PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector. 487 488 Collective on PC and Vec 489 490 Input Parameters: 491 + pc - the preconditioner context 492 - x - input vector 493 494 Output Parameter: 495 . y - output vector 496 497 Level: developer 498 499 Notes: 500 Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners. 501 502 .keywords: PC, apply, symmetric, right 503 504 .seealso: PCApply(), PCApplySymmetricLeft() 505 @*/ 506 int PCApplySymmetricRight(PC pc,Vec x,Vec y) 507 { 508 int ierr; 509 510 PetscFunctionBegin; 511 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 512 PetscValidHeaderSpecific(x,VEC_COOKIE,2); 513 PetscValidHeaderSpecific(y,VEC_COOKIE,3); 514 if (!pc->ops->applysymmetricright) SETERRQ(1,"PC does not have left symmetric apply"); 515 516 if (pc->setupcalled < 2) { 517 ierr = PCSetUp(pc);CHKERRQ(ierr); 518 } 519 520 ierr = PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);CHKERRQ(ierr); 521 ierr = (*pc->ops->applysymmetricright)(pc,x,y);CHKERRQ(ierr); 522 ierr = PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);CHKERRQ(ierr); 523 PetscFunctionReturn(0); 524 } 525 526 #undef __FUNCT__ 527 #define __FUNCT__ "PCApplyTranspose" 528 /*@ 529 PCApplyTranspose - Applies the transpose of preconditioner to a vector. 530 531 Collective on PC and Vec 532 533 Input Parameters: 534 + pc - the preconditioner context 535 - x - input vector 536 537 Output Parameter: 538 . y - output vector 539 540 Level: developer 541 542 .keywords: PC, apply, transpose 543 544 .seealso: PCApply(), PCApplyBAorAB(), PCApplyBAorABTranspose(), PCHasApplyTranspose() 545 @*/ 546 int PCApplyTranspose(PC pc,Vec x,Vec y) 547 { 548 int ierr; 549 550 PetscFunctionBegin; 551 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 552 PetscValidHeaderSpecific(x,VEC_COOKIE,2); 553 PetscValidHeaderSpecific(y,VEC_COOKIE,3); 554 if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 555 if (!pc->ops->applytranspose) SETERRQ(PETSC_ERR_SUP," "); 556 557 if (pc->setupcalled < 2) { 558 ierr = PCSetUp(pc);CHKERRQ(ierr); 559 } 560 561 ierr = PetscLogEventBegin(PC_Apply,pc,x,y,0);CHKERRQ(ierr); 562 ierr = (*pc->ops->applytranspose)(pc,x,y);CHKERRQ(ierr); 563 ierr = PetscLogEventEnd(PC_Apply,pc,x,y,0);CHKERRQ(ierr); 564 PetscFunctionReturn(0); 565 } 566 567 #undef __FUNCT__ 568 #define __FUNCT__ "PCHasApplyTranspose" 569 /*@ 570 PCHasApplyTranspose - Test whether the preconditioner has a transpose apply operation 571 572 Collective on PC and Vec 573 574 Input Parameters: 575 . pc - the preconditioner context 576 577 Output Parameter: 578 . flg - PETSC_TRUE if a transpose operation is defined 579 580 Level: developer 581 582 .keywords: PC, apply, transpose 583 584 .seealso: PCApplyTranspose() 585 @*/ 586 int PCHasApplyTranspose(PC pc,PetscTruth *flg) 587 { 588 PetscFunctionBegin; 589 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 590 PetscValidPointer(flg,2); 591 *flg = (PetscTruth) (pc->ops->applytranspose == 0); 592 PetscFunctionReturn(0); 593 } 594 595 #undef __FUNCT__ 596 #define __FUNCT__ "PCApplyBAorAB" 597 /*@ 598 PCApplyBAorAB - Applies the preconditioner and operator to a vector. 599 600 Collective on PC and Vec 601 602 Input Parameters: 603 + pc - the preconditioner context 604 . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC 605 . x - input vector 606 - work - work vector 607 608 Output Parameter: 609 . y - output vector 610 611 Level: developer 612 613 .keywords: PC, apply, operator 614 615 .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose() 616 @*/ 617 int PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work) 618 { 619 int ierr; 620 621 PetscFunctionBegin; 622 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 623 PetscValidHeaderSpecific(x,VEC_COOKIE,3); 624 PetscValidHeaderSpecific(y,VEC_COOKIE,4); 625 PetscValidHeaderSpecific(work,VEC_COOKIE,5); 626 if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 627 if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) { 628 SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric"); 629 } 630 if (pc->diagonalscale && side == PC_SYMMETRIC) { 631 SETERRQ(1,"Cannot include diagonal scaling with symmetric preconditioner application"); 632 } 633 634 if (pc->setupcalled < 2) { 635 ierr = PCSetUp(pc);CHKERRQ(ierr); 636 } 637 638 if (pc->diagonalscale) { 639 if (pc->ops->applyBA) { 640 Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */ 641 ierr = VecDuplicate(x,&work2);CHKERRQ(ierr); 642 ierr = PCDiagonalScaleRight(pc,x,work2);CHKERRQ(ierr); 643 ierr = (*pc->ops->applyBA)(pc,side,work2,y,work);CHKERRQ(ierr); 644 /* Remove null space from preconditioned vector y */ 645 if (pc->nullsp) { 646 ierr = MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);CHKERRQ(ierr); 647 } 648 ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr); 649 ierr = VecDestroy(work2);CHKERRQ(ierr); 650 } else if (side == PC_RIGHT) { 651 ierr = PCDiagonalScaleRight(pc,x,y);CHKERRQ(ierr); 652 ierr = PCApply(pc,y,work,side);CHKERRQ(ierr); 653 ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr); 654 ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr); 655 } else if (side == PC_LEFT) { 656 ierr = PCDiagonalScaleRight(pc,x,y);CHKERRQ(ierr); 657 ierr = MatMult(pc->mat,y,work);CHKERRQ(ierr); 658 ierr = PCApply(pc,work,y,side);CHKERRQ(ierr); 659 ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr); 660 } else if (side == PC_SYMMETRIC) { 661 SETERRQ(1,"Cannot provide diagonal scaling with symmetric application of preconditioner"); 662 } 663 } else { 664 if (pc->ops->applyBA) { 665 ierr = (*pc->ops->applyBA)(pc,side,x,y,work);CHKERRQ(ierr); 666 /* Remove null space from preconditioned vector y */ 667 if (pc->nullsp) { 668 ierr = MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);CHKERRQ(ierr); 669 } 670 } else if (side == PC_RIGHT) { 671 ierr = PCApply(pc,x,work,side);CHKERRQ(ierr); 672 ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr); 673 } else if (side == PC_LEFT) { 674 ierr = MatMult(pc->mat,x,work);CHKERRQ(ierr); 675 ierr = PCApply(pc,work,y,side);CHKERRQ(ierr); 676 } else if (side == PC_SYMMETRIC) { 677 /* There's an extra copy here; maybe should provide 2 work vectors instead? */ 678 ierr = PCApplySymmetricRight(pc,x,work);CHKERRQ(ierr); 679 ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr); 680 ierr = VecCopy(y,work);CHKERRQ(ierr); 681 ierr = PCApplySymmetricLeft(pc,work,y);CHKERRQ(ierr); 682 } 683 } 684 PetscFunctionReturn(0); 685 } 686 687 #undef __FUNCT__ 688 #define __FUNCT__ "PCApplyBAorABTranspose" 689 /*@ 690 PCApplyBAorABTranspose - Applies the transpose of the preconditioner 691 and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning, 692 not tr(B*A) = tr(A)*tr(B). 693 694 Collective on PC and Vec 695 696 Input Parameters: 697 + pc - the preconditioner context 698 . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC 699 . x - input vector 700 - work - work vector 701 702 Output Parameter: 703 . y - output vector 704 705 Level: developer 706 707 .keywords: PC, apply, operator, transpose 708 709 .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB() 710 @*/ 711 int PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work) 712 { 713 int ierr; 714 715 PetscFunctionBegin; 716 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 717 PetscValidHeaderSpecific(x,VEC_COOKIE,3); 718 PetscValidHeaderSpecific(y,VEC_COOKIE,4); 719 PetscValidHeaderSpecific(work,VEC_COOKIE,5); 720 if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 721 if (pc->ops->applyBAtranspose) { 722 ierr = (*pc->ops->applyBAtranspose)(pc,side,x,y,work);CHKERRQ(ierr); 723 PetscFunctionReturn(0); 724 } 725 if (side != PC_LEFT && side != PC_RIGHT) { 726 SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left"); 727 } 728 729 if (pc->setupcalled < 2) { 730 ierr = PCSetUp(pc);CHKERRQ(ierr); 731 } 732 733 if (side == PC_RIGHT) { 734 ierr = PCApplyTranspose(pc,x,work);CHKERRQ(ierr); 735 ierr = MatMultTranspose(pc->mat,work,y);CHKERRQ(ierr); 736 } else if (side == PC_LEFT) { 737 ierr = MatMultTranspose(pc->mat,x,work);CHKERRQ(ierr); 738 ierr = PCApplyTranspose(pc,work,y);CHKERRQ(ierr); 739 } 740 /* add support for PC_SYMMETRIC */ 741 PetscFunctionReturn(0); /* actually will never get here */ 742 } 743 744 /* -------------------------------------------------------------------------------*/ 745 746 #undef __FUNCT__ 747 #define __FUNCT__ "PCApplyRichardsonExists" 748 /*@ 749 PCApplyRichardsonExists - Determines whether a particular preconditioner has a 750 built-in fast application of Richardson's method. 751 752 Not Collective 753 754 Input Parameter: 755 . pc - the preconditioner 756 757 Output Parameter: 758 . exists - PETSC_TRUE or PETSC_FALSE 759 760 Level: developer 761 762 .keywords: PC, apply, Richardson, exists 763 764 .seealso: PCApplyRichardson() 765 @*/ 766 int PCApplyRichardsonExists(PC pc,PetscTruth *exists) 767 { 768 PetscFunctionBegin; 769 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 770 PetscValidIntPointer(exists,2); 771 if (pc->ops->applyrichardson) *exists = PETSC_TRUE; 772 else *exists = PETSC_FALSE; 773 PetscFunctionReturn(0); 774 } 775 776 #undef __FUNCT__ 777 #define __FUNCT__ "PCApplyRichardson" 778 /*@ 779 PCApplyRichardson - Applies several steps of Richardson iteration with 780 the particular preconditioner. This routine is usually used by the 781 Krylov solvers and not the application code directly. 782 783 Collective on PC 784 785 Input Parameters: 786 + pc - the preconditioner context 787 . x - the initial guess 788 . w - one work vector 789 . rtol - relative decrease in residual norm convergence criteria 790 . atol - absolute residual norm convergence criteria 791 . dtol - divergence residual norm increase criteria 792 - its - the number of iterations to apply. 793 794 Output Parameter: 795 . y - the solution 796 797 Notes: 798 Most preconditioners do not support this function. Use the command 799 PCApplyRichardsonExists() to determine if one does. 800 801 Except for the multigrid PC this routine ignores the convergence tolerances 802 and always runs for the number of iterations 803 804 Level: developer 805 806 .keywords: PC, apply, Richardson 807 808 .seealso: PCApplyRichardsonExists() 809 @*/ 810 int PCApplyRichardson(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int its) 811 { 812 int ierr; 813 814 PetscFunctionBegin; 815 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 816 PetscValidHeaderSpecific(x,VEC_COOKIE,2); 817 PetscValidHeaderSpecific(y,VEC_COOKIE,3); 818 PetscValidHeaderSpecific(w,VEC_COOKIE,4); 819 if (!pc->ops->applyrichardson) SETERRQ(PETSC_ERR_SUP," "); 820 821 if (pc->setupcalled < 2) { 822 ierr = PCSetUp(pc);CHKERRQ(ierr); 823 } 824 825 ierr = (*pc->ops->applyrichardson)(pc,x,y,w,rtol,atol,dtol,its);CHKERRQ(ierr); 826 PetscFunctionReturn(0); 827 } 828 829 /* 830 a setupcall of 0 indicates never setup, 831 1 needs to be resetup, 832 2 does not need any changes. 833 */ 834 #undef __FUNCT__ 835 #define __FUNCT__ "PCSetUp" 836 /*@ 837 PCSetUp - Prepares for the use of a preconditioner. 838 839 Collective on PC 840 841 Input Parameter: 842 . pc - the preconditioner context 843 844 Level: developer 845 846 .keywords: PC, setup 847 848 .seealso: PCCreate(), PCApply(), PCDestroy() 849 @*/ 850 int PCSetUp(PC pc) 851 { 852 int ierr; 853 const char *def; 854 855 PetscFunctionBegin; 856 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 857 858 if (pc->setupcalled > 1) { 859 PetscLogInfo(pc,"PCSetUp:Setting PC with identical preconditioner\n"); 860 PetscFunctionReturn(0); 861 } else if (pc->setupcalled == 0) { 862 PetscLogInfo(pc,"PCSetUp:Setting up new PC\n"); 863 } else if (pc->flag == SAME_NONZERO_PATTERN) { 864 PetscLogInfo(pc,"PCSetUp:Setting up PC with same nonzero pattern\n"); 865 } else { 866 PetscLogInfo(pc,"PCSetUp:Setting up PC with different nonzero pattern\n"); 867 } 868 869 ierr = PetscLogEventBegin(PC_SetUp,pc,0,0,0);CHKERRQ(ierr); 870 if (!pc->vec) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Vector must be set first");} 871 if (!pc->mat) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");} 872 873 if (!pc->type_name) { 874 ierr = PCGetDefaultType_Private(pc,&def);CHKERRQ(ierr); 875 ierr = PCSetType(pc,def);CHKERRQ(ierr); 876 } 877 878 if (pc->ops->setup) { 879 ierr = (*pc->ops->setup)(pc);CHKERRQ(ierr); 880 } 881 pc->setupcalled = 2; 882 if (pc->nullsp) { 883 PetscTruth test; 884 ierr = PetscOptionsHasName(pc->prefix,"-pc_test_null_space",&test);CHKERRQ(ierr); 885 if (test) { 886 ierr = MatNullSpaceTest(pc->nullsp,pc->mat);CHKERRQ(ierr); 887 } 888 } 889 ierr = PetscLogEventEnd(PC_SetUp,pc,0,0,0);CHKERRQ(ierr); 890 PetscFunctionReturn(0); 891 } 892 893 #undef __FUNCT__ 894 #define __FUNCT__ "PCSetUpOnBlocks" 895 /*@ 896 PCSetUpOnBlocks - Sets up the preconditioner for each block in 897 the block Jacobi, block Gauss-Seidel, and overlapping Schwarz 898 methods. 899 900 Collective on PC 901 902 Input Parameters: 903 . pc - the preconditioner context 904 905 Level: developer 906 907 .keywords: PC, setup, blocks 908 909 .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp() 910 @*/ 911 int PCSetUpOnBlocks(PC pc) 912 { 913 int ierr; 914 915 PetscFunctionBegin; 916 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 917 if (!pc->ops->setuponblocks) PetscFunctionReturn(0); 918 ierr = PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);CHKERRQ(ierr); 919 ierr = (*pc->ops->setuponblocks)(pc);CHKERRQ(ierr); 920 ierr = PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);CHKERRQ(ierr); 921 PetscFunctionReturn(0); 922 } 923 924 #undef __FUNCT__ 925 #define __FUNCT__ "PCSetModifySubMatrices" 926 /*@C 927 PCSetModifySubMatrices - Sets a user-defined routine for modifying the 928 submatrices that arise within certain subdomain-based preconditioners. 929 The basic submatrices are extracted from the preconditioner matrix as 930 usual; the user can then alter these (for example, to set different boundary 931 conditions for each submatrix) before they are used for the local solves. 932 933 Collective on PC 934 935 Input Parameters: 936 + pc - the preconditioner context 937 . func - routine for modifying the submatrices 938 - ctx - optional user-defined context (may be null) 939 940 Calling sequence of func: 941 $ func (PC pc,int nsub,IS *row,IS *col,Mat *submat,void *ctx); 942 943 . row - an array of index sets that contain the global row numbers 944 that comprise each local submatrix 945 . col - an array of index sets that contain the global column numbers 946 that comprise each local submatrix 947 . submat - array of local submatrices 948 - ctx - optional user-defined context for private data for the 949 user-defined func routine (may be null) 950 951 Notes: 952 PCSetModifySubMatrices() MUST be called before KSPSetUp() and 953 KSPSolve(). 954 955 A routine set by PCSetModifySubMatrices() is currently called within 956 the block Jacobi (PCBJACOBI) and additive Schwarz (PCASM) 957 preconditioners. All other preconditioners ignore this routine. 958 959 Level: advanced 960 961 .keywords: PC, set, modify, submatrices 962 963 .seealso: PCModifySubMatrices() 964 @*/ 965 int PCSetModifySubMatrices(PC pc,int(*func)(PC,int,const IS[],const IS[],Mat[],void*),void *ctx) 966 { 967 PetscFunctionBegin; 968 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 969 pc->modifysubmatrices = func; 970 pc->modifysubmatricesP = ctx; 971 PetscFunctionReturn(0); 972 } 973 974 #undef __FUNCT__ 975 #define __FUNCT__ "PCModifySubMatrices" 976 /*@C 977 PCModifySubMatrices - Calls an optional user-defined routine within 978 certain preconditioners if one has been set with PCSetModifySubMarices(). 979 980 Collective on PC 981 982 Input Parameters: 983 + pc - the preconditioner context 984 . nsub - the number of local submatrices 985 . row - an array of index sets that contain the global row numbers 986 that comprise each local submatrix 987 . col - an array of index sets that contain the global column numbers 988 that comprise each local submatrix 989 . submat - array of local submatrices 990 - ctx - optional user-defined context for private data for the 991 user-defined routine (may be null) 992 993 Output Parameter: 994 . submat - array of local submatrices (the entries of which may 995 have been modified) 996 997 Notes: 998 The user should NOT generally call this routine, as it will 999 automatically be called within certain preconditioners (currently 1000 block Jacobi, additive Schwarz) if set. 1001 1002 The basic submatrices are extracted from the preconditioner matrix 1003 as usual; the user can then alter these (for example, to set different 1004 boundary conditions for each submatrix) before they are used for the 1005 local solves. 1006 1007 Level: developer 1008 1009 .keywords: PC, modify, submatrices 1010 1011 .seealso: PCSetModifySubMatrices() 1012 @*/ 1013 int PCModifySubMatrices(PC pc,int nsub,const IS row[],const IS col[],Mat submat[],void *ctx) 1014 { 1015 int ierr; 1016 1017 PetscFunctionBegin; 1018 if (!pc->modifysubmatrices) PetscFunctionReturn(0); 1019 ierr = PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);CHKERRQ(ierr); 1020 ierr = (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);CHKERRQ(ierr); 1021 ierr = PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);CHKERRQ(ierr); 1022 PetscFunctionReturn(0); 1023 } 1024 1025 #undef __FUNCT__ 1026 #define __FUNCT__ "PCSetOperators" 1027 /*@ 1028 PCSetOperators - Sets the matrix associated with the linear system and 1029 a (possibly) different one associated with the preconditioner. 1030 1031 Collective on PC and Mat 1032 1033 Input Parameters: 1034 + pc - the preconditioner context 1035 . Amat - the matrix associated with the linear system 1036 . Pmat - the matrix to be used in constructing the preconditioner, usually 1037 the same as Amat. 1038 - flag - flag indicating information about the preconditioner matrix structure 1039 during successive linear solves. This flag is ignored the first time a 1040 linear system is solved, and thus is irrelevant when solving just one linear 1041 system. 1042 1043 Notes: 1044 The flag can be used to eliminate unnecessary work in the preconditioner 1045 during the repeated solution of linear systems of the same size. The 1046 available options are 1047 + SAME_PRECONDITIONER - 1048 Pmat is identical during successive linear solves. 1049 This option is intended for folks who are using 1050 different Amat and Pmat matrices and wish to reuse the 1051 same preconditioner matrix. For example, this option 1052 saves work by not recomputing incomplete factorization 1053 for ILU/ICC preconditioners. 1054 . SAME_NONZERO_PATTERN - 1055 Pmat has the same nonzero structure during 1056 successive linear solves. 1057 - DIFFERENT_NONZERO_PATTERN - 1058 Pmat does not have the same nonzero structure. 1059 1060 Caution: 1061 If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion 1062 and does not check the structure of the matrix. If you erroneously 1063 claim that the structure is the same when it actually is not, the new 1064 preconditioner will not function correctly. Thus, use this optimization 1065 feature carefully! 1066 1067 If in doubt about whether your preconditioner matrix has changed 1068 structure or not, use the flag DIFFERENT_NONZERO_PATTERN. 1069 1070 More Notes about Repeated Solution of Linear Systems: 1071 PETSc does NOT reset the matrix entries of either Amat or Pmat 1072 to zero after a linear solve; the user is completely responsible for 1073 matrix assembly. See the routine MatZeroEntries() if desiring to 1074 zero all elements of a matrix. 1075 1076 Level: intermediate 1077 1078 .keywords: PC, set, operators, matrix, linear system 1079 1080 .seealso: PCGetOperators(), MatZeroEntries() 1081 @*/ 1082 int PCSetOperators(PC pc,Mat Amat,Mat Pmat,MatStructure flag) 1083 { 1084 int ierr; 1085 PetscTruth isbjacobi,isrowbs; 1086 1087 PetscFunctionBegin; 1088 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1089 PetscValidHeaderSpecific(Amat,MAT_COOKIE,2); 1090 PetscValidHeaderSpecific(Pmat,MAT_COOKIE,3); 1091 1092 /* 1093 BlockSolve95 cannot use default BJacobi preconditioning 1094 */ 1095 ierr = PetscTypeCompare((PetscObject)Amat,MATMPIROWBS,&isrowbs);CHKERRQ(ierr); 1096 if (isrowbs) { 1097 ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&isbjacobi);CHKERRQ(ierr); 1098 if (isbjacobi) { 1099 ierr = PCSetType(pc,PCILU);CHKERRQ(ierr); 1100 PetscLogInfo(pc,"PCSetOperators:Switching default PC to PCILU since BS95 doesn't support PCBJACOBI\n"); 1101 } 1102 } 1103 1104 pc->mat = Amat; 1105 pc->pmat = Pmat; 1106 if (pc->setupcalled == 2 && flag != SAME_PRECONDITIONER) { 1107 pc->setupcalled = 1; 1108 } 1109 pc->flag = flag; 1110 PetscFunctionReturn(0); 1111 } 1112 1113 #undef __FUNCT__ 1114 #define __FUNCT__ "PCGetOperators" 1115 /*@C 1116 PCGetOperators - Gets the matrix associated with the linear system and 1117 possibly a different one associated with the preconditioner. 1118 1119 Not collective, though parallel Mats are returned if the PC is parallel 1120 1121 Input Parameter: 1122 . pc - the preconditioner context 1123 1124 Output Parameters: 1125 + mat - the matrix associated with the linear system 1126 . pmat - matrix associated with the preconditioner, usually the same 1127 as mat. 1128 - flag - flag indicating information about the preconditioner 1129 matrix structure. See PCSetOperators() for details. 1130 1131 Level: intermediate 1132 1133 .keywords: PC, get, operators, matrix, linear system 1134 1135 .seealso: PCSetOperators() 1136 @*/ 1137 int PCGetOperators(PC pc,Mat *mat,Mat *pmat,MatStructure *flag) 1138 { 1139 PetscFunctionBegin; 1140 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1141 if (mat) *mat = pc->mat; 1142 if (pmat) *pmat = pc->pmat; 1143 if (flag) *flag = pc->flag; 1144 PetscFunctionReturn(0); 1145 } 1146 1147 #undef __FUNCT__ 1148 #define __FUNCT__ "PCSetVector" 1149 /*@ 1150 PCSetVector - Sets a vector associated with the preconditioner. 1151 1152 Collective on PC and Vec 1153 1154 Input Parameters: 1155 + pc - the preconditioner context 1156 - vec - the vector 1157 1158 Notes: 1159 The vector must be set so that the preconditioner knows what type 1160 of vector to allocate if necessary. 1161 1162 Level: intermediate 1163 1164 .keywords: PC, set, vector 1165 1166 .seealso: PCGetVector() 1167 1168 @*/ 1169 int PCSetVector(PC pc,Vec vec) 1170 { 1171 PetscFunctionBegin; 1172 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1173 PetscValidHeaderSpecific(vec,VEC_COOKIE,2); 1174 PetscCheckSameComm(pc,1,vec,2); 1175 pc->vec = vec; 1176 PetscFunctionReturn(0); 1177 } 1178 1179 #undef __FUNCT__ 1180 #define __FUNCT__ "PCGetVector" 1181 /*@ 1182 PCGetVector - Gets a vector associated with the preconditioner; if the 1183 vector was not get set it will return a 0 pointer. 1184 1185 Not collective, but vector is shared by all processors that share the PC 1186 1187 Input Parameter: 1188 . pc - the preconditioner context 1189 1190 Output Parameter: 1191 . vec - the vector 1192 1193 Level: intermediate 1194 1195 .keywords: PC, get, vector 1196 1197 .seealso: PCSetVector() 1198 1199 @*/ 1200 int PCGetVector(PC pc,Vec *vec) 1201 { 1202 PetscFunctionBegin; 1203 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1204 *vec = pc->vec; 1205 PetscFunctionReturn(0); 1206 } 1207 1208 #undef __FUNCT__ 1209 #define __FUNCT__ "PCGetFactoredMatrix" 1210 /*@C 1211 PCGetFactoredMatrix - Gets the factored matrix from the 1212 preconditioner context. This routine is valid only for the LU, 1213 incomplete LU, Cholesky, and incomplete Cholesky methods. 1214 1215 Not Collective on PC though Mat is parallel if PC is parallel 1216 1217 Input Parameters: 1218 . pc - the preconditioner context 1219 1220 Output parameters: 1221 . mat - the factored matrix 1222 1223 Level: advanced 1224 1225 .keywords: PC, get, factored, matrix 1226 @*/ 1227 int PCGetFactoredMatrix(PC pc,Mat *mat) 1228 { 1229 int ierr; 1230 1231 PetscFunctionBegin; 1232 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1233 PetscValidPointer(mat,2); 1234 if (pc->ops->getfactoredmatrix) { 1235 ierr = (*pc->ops->getfactoredmatrix)(pc,mat);CHKERRQ(ierr); 1236 } 1237 PetscFunctionReturn(0); 1238 } 1239 1240 #undef __FUNCT__ 1241 #define __FUNCT__ "PCSetOptionsPrefix" 1242 /*@C 1243 PCSetOptionsPrefix - Sets the prefix used for searching for all 1244 PC options in the database. 1245 1246 Collective on PC 1247 1248 Input Parameters: 1249 + pc - the preconditioner context 1250 - prefix - the prefix string to prepend to all PC option requests 1251 1252 Notes: 1253 A hyphen (-) must NOT be given at the beginning of the prefix name. 1254 The first character of all runtime options is AUTOMATICALLY the 1255 hyphen. 1256 1257 Level: advanced 1258 1259 .keywords: PC, set, options, prefix, database 1260 1261 .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix() 1262 @*/ 1263 int PCSetOptionsPrefix(PC pc,const char prefix[]) 1264 { 1265 int ierr; 1266 1267 PetscFunctionBegin; 1268 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1269 ierr = PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr); 1270 PetscFunctionReturn(0); 1271 } 1272 1273 #undef __FUNCT__ 1274 #define __FUNCT__ "PCAppendOptionsPrefix" 1275 /*@C 1276 PCAppendOptionsPrefix - Appends to the prefix used for searching for all 1277 PC options in the database. 1278 1279 Collective on PC 1280 1281 Input Parameters: 1282 + pc - the preconditioner context 1283 - prefix - the prefix string to prepend to all PC option requests 1284 1285 Notes: 1286 A hyphen (-) must NOT be given at the beginning of the prefix name. 1287 The first character of all runtime options is AUTOMATICALLY the 1288 hyphen. 1289 1290 Level: advanced 1291 1292 .keywords: PC, append, options, prefix, database 1293 1294 .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix() 1295 @*/ 1296 int PCAppendOptionsPrefix(PC pc,const char prefix[]) 1297 { 1298 int ierr; 1299 1300 PetscFunctionBegin; 1301 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1302 ierr = PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr); 1303 PetscFunctionReturn(0); 1304 } 1305 1306 #undef __FUNCT__ 1307 #define __FUNCT__ "PCGetOptionsPrefix" 1308 /*@C 1309 PCGetOptionsPrefix - Gets the prefix used for searching for all 1310 PC options in the database. 1311 1312 Not Collective 1313 1314 Input Parameters: 1315 . pc - the preconditioner context 1316 1317 Output Parameters: 1318 . prefix - pointer to the prefix string used, is returned 1319 1320 Notes: On the fortran side, the user should pass in a string 'prifix' of 1321 sufficient length to hold the prefix. 1322 1323 Level: advanced 1324 1325 .keywords: PC, get, options, prefix, database 1326 1327 .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix() 1328 @*/ 1329 int PCGetOptionsPrefix(PC pc,char *prefix[]) 1330 { 1331 int ierr; 1332 1333 PetscFunctionBegin; 1334 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1335 PetscValidPointer(prefix,2); 1336 ierr = PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr); 1337 PetscFunctionReturn(0); 1338 } 1339 1340 #undef __FUNCT__ 1341 #define __FUNCT__ "PCPreSolve" 1342 /*@ 1343 PCPreSolve - Optional pre-solve phase, intended for any 1344 preconditioner-specific actions that must be performed before 1345 the iterative solve itself. 1346 1347 Collective on PC 1348 1349 Input Parameters: 1350 + pc - the preconditioner context 1351 - ksp - the Krylov subspace context 1352 1353 Level: developer 1354 1355 Sample of Usage: 1356 .vb 1357 PCPreSolve(pc,ksp); 1358 KSPSolve(ksp,its); 1359 PCPostSolve(pc,ksp); 1360 .ve 1361 1362 Notes: 1363 The pre-solve phase is distinct from the PCSetUp() phase. 1364 1365 KSPSolve() calls this directly, so is rarely called by the user. 1366 1367 .keywords: PC, pre-solve 1368 1369 .seealso: PCPostSolve() 1370 @*/ 1371 int PCPreSolve(PC pc,KSP ksp) 1372 { 1373 int ierr; 1374 Vec x,rhs; 1375 Mat A,B; 1376 1377 PetscFunctionBegin; 1378 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1379 PetscValidHeaderSpecific(ksp,KSP_COOKIE,2); 1380 ierr = KSPGetSolution(ksp,&x);CHKERRQ(ierr); 1381 ierr = KSPGetRhs(ksp,&rhs);CHKERRQ(ierr); 1382 /* 1383 Scale the system and have the matrices use the scaled form 1384 only if the two matrices are actually the same (and hence 1385 have the same scaling 1386 */ 1387 ierr = PCGetOperators(pc,&A,&B,PETSC_NULL);CHKERRQ(ierr); 1388 if (A == B) { 1389 ierr = MatScaleSystem(pc->mat,x,rhs);CHKERRQ(ierr); 1390 ierr = MatUseScaledForm(pc->mat,PETSC_TRUE);CHKERRQ(ierr); 1391 } 1392 1393 if (pc->ops->presolve) { 1394 ierr = (*pc->ops->presolve)(pc,ksp,x,rhs);CHKERRQ(ierr); 1395 } 1396 PetscFunctionReturn(0); 1397 } 1398 1399 #undef __FUNCT__ 1400 #define __FUNCT__ "PCPostSolve" 1401 /*@ 1402 PCPostSolve - Optional post-solve phase, intended for any 1403 preconditioner-specific actions that must be performed after 1404 the iterative solve itself. 1405 1406 Collective on PC 1407 1408 Input Parameters: 1409 + pc - the preconditioner context 1410 - ksp - the Krylov subspace context 1411 1412 Sample of Usage: 1413 .vb 1414 PCPreSolve(pc,ksp); 1415 KSPSolve(ksp,its); 1416 PCPostSolve(pc,ksp); 1417 .ve 1418 1419 Note: 1420 KSPSolve() calls this routine directly, so it is rarely called by the user. 1421 1422 Level: developer 1423 1424 .keywords: PC, post-solve 1425 1426 .seealso: PCPreSolve(), KSPSolve() 1427 @*/ 1428 int PCPostSolve(PC pc,KSP ksp) 1429 { 1430 int ierr; 1431 Vec x,rhs; 1432 Mat A,B; 1433 1434 PetscFunctionBegin; 1435 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1436 PetscValidHeaderSpecific(ksp,KSP_COOKIE,2); 1437 ierr = KSPGetSolution(ksp,&x);CHKERRQ(ierr); 1438 ierr = KSPGetRhs(ksp,&rhs);CHKERRQ(ierr); 1439 if (pc->ops->postsolve) { 1440 ierr = (*pc->ops->postsolve)(pc,ksp,x,rhs);CHKERRQ(ierr); 1441 } 1442 1443 /* 1444 Scale the system and have the matrices use the scaled form 1445 only if the two matrices are actually the same (and hence 1446 have the same scaling 1447 */ 1448 ierr = PCGetOperators(pc,&A,&B,PETSC_NULL);CHKERRQ(ierr); 1449 if (A == B) { 1450 ierr = MatUnScaleSystem(pc->mat,x,rhs);CHKERRQ(ierr); 1451 ierr = MatUseScaledForm(pc->mat,PETSC_FALSE);CHKERRQ(ierr); 1452 } 1453 PetscFunctionReturn(0); 1454 } 1455 1456 #undef __FUNCT__ 1457 #define __FUNCT__ "PCView" 1458 /*@C 1459 PCView - Prints the PC data structure. 1460 1461 Collective on PC 1462 1463 Input Parameters: 1464 + PC - the PC context 1465 - viewer - optional visualization context 1466 1467 Note: 1468 The available visualization contexts include 1469 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 1470 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 1471 output where only the first processor opens 1472 the file. All other processors send their 1473 data to the first processor to print. 1474 1475 The user can open an alternative visualization contexts with 1476 PetscViewerASCIIOpen() (output to a specified file). 1477 1478 Level: developer 1479 1480 .keywords: PC, view 1481 1482 .seealso: KSPView(), PetscViewerASCIIOpen() 1483 @*/ 1484 int PCView(PC pc,PetscViewer viewer) 1485 { 1486 PCType cstr; 1487 int ierr; 1488 PetscTruth mat_exists,isascii,isstring; 1489 PetscViewerFormat format; 1490 1491 PetscFunctionBegin; 1492 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1493 if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pc->comm); 1494 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2); 1495 PetscCheckSameComm(pc,1,viewer,2); 1496 1497 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr); 1498 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr); 1499 if (isascii) { 1500 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1501 if (pc->prefix) { 1502 ierr = PetscViewerASCIIPrintf(viewer,"PC Object:(%s)\n",pc->prefix);CHKERRQ(ierr); 1503 } else { 1504 ierr = PetscViewerASCIIPrintf(viewer,"PC Object:\n");CHKERRQ(ierr); 1505 } 1506 ierr = PCGetType(pc,&cstr);CHKERRQ(ierr); 1507 if (cstr) { 1508 ierr = PetscViewerASCIIPrintf(viewer," type: %s\n",cstr);CHKERRQ(ierr); 1509 } else { 1510 ierr = PetscViewerASCIIPrintf(viewer," type: not yet set\n");CHKERRQ(ierr); 1511 } 1512 if (pc->ops->view) { 1513 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1514 ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr); 1515 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1516 } 1517 ierr = PetscObjectExists((PetscObject)pc->mat,&mat_exists);CHKERRQ(ierr); 1518 if (mat_exists) { 1519 ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr); 1520 if (pc->pmat == pc->mat) { 1521 ierr = PetscViewerASCIIPrintf(viewer," linear system matrix = precond matrix:\n");CHKERRQ(ierr); 1522 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1523 ierr = MatView(pc->mat,viewer);CHKERRQ(ierr); 1524 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1525 } else { 1526 ierr = PetscObjectExists((PetscObject)pc->pmat,&mat_exists);CHKERRQ(ierr); 1527 if (mat_exists) { 1528 ierr = PetscViewerASCIIPrintf(viewer," linear system matrix followed by preconditioner matrix:\n");CHKERRQ(ierr); 1529 } else { 1530 ierr = PetscViewerASCIIPrintf(viewer," linear system matrix:\n");CHKERRQ(ierr); 1531 } 1532 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1533 ierr = MatView(pc->mat,viewer);CHKERRQ(ierr); 1534 if (mat_exists) {ierr = MatView(pc->pmat,viewer);CHKERRQ(ierr);} 1535 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1536 } 1537 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1538 } 1539 } else if (isstring) { 1540 ierr = PCGetType(pc,&cstr);CHKERRQ(ierr); 1541 ierr = PetscViewerStringSPrintf(viewer," %-7.7s",cstr);CHKERRQ(ierr); 1542 if (pc->ops->view) {ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr);} 1543 } else { 1544 SETERRQ1(1,"Viewer type %s not supported by PC",((PetscObject)viewer)->type_name); 1545 } 1546 PetscFunctionReturn(0); 1547 } 1548 1549 #undef __FUNCT__ 1550 #define __FUNCT__ "PCRegister" 1551 /*@C 1552 PCRegister - See PCRegisterDynamic() 1553 1554 Level: advanced 1555 @*/ 1556 int PCRegister(const char sname[],const char path[],const char name[],int (*function)(PC)) 1557 { 1558 int ierr; 1559 char fullname[256]; 1560 1561 PetscFunctionBegin; 1562 1563 ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr); 1564 ierr = PetscFListAdd(&PCList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr); 1565 PetscFunctionReturn(0); 1566 } 1567 1568 #undef __FUNCT__ 1569 #define __FUNCT__ "PCComputeExplicitOperator" 1570 /*@ 1571 PCComputeExplicitOperator - Computes the explicit preconditioned operator. 1572 1573 Collective on PC 1574 1575 Input Parameter: 1576 . pc - the preconditioner object 1577 1578 Output Parameter: 1579 . mat - the explict preconditioned operator 1580 1581 Notes: 1582 This computation is done by applying the operators to columns of the 1583 identity matrix. 1584 1585 Currently, this routine uses a dense matrix format when 1 processor 1586 is used and a sparse format otherwise. This routine is costly in general, 1587 and is recommended for use only with relatively small systems. 1588 1589 Level: advanced 1590 1591 .keywords: PC, compute, explicit, operator 1592 1593 @*/ 1594 int PCComputeExplicitOperator(PC pc,Mat *mat) 1595 { 1596 Vec in,out; 1597 int ierr,i,M,m,size,*rows,start,end; 1598 MPI_Comm comm; 1599 PetscScalar *array,zero = 0.0,one = 1.0; 1600 1601 PetscFunctionBegin; 1602 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1603 PetscValidPointer(mat,2); 1604 1605 comm = pc->comm; 1606 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1607 1608 ierr = PCGetVector(pc,&in);CHKERRQ(ierr); 1609 ierr = VecDuplicate(in,&out);CHKERRQ(ierr); 1610 ierr = VecGetOwnershipRange(in,&start,&end);CHKERRQ(ierr); 1611 ierr = VecGetSize(in,&M);CHKERRQ(ierr); 1612 ierr = VecGetLocalSize(in,&m);CHKERRQ(ierr); 1613 ierr = PetscMalloc((m+1)*sizeof(int),&rows);CHKERRQ(ierr); 1614 for (i=0; i<m; i++) {rows[i] = start + i;} 1615 1616 ierr = MatCreate(comm,m,m,M,M,mat);CHKERRQ(ierr); 1617 if (size == 1) { 1618 ierr = MatSetType(*mat,MATSEQDENSE);CHKERRQ(ierr); 1619 ierr = MatSeqDenseSetPreallocation(*mat,PETSC_NULL);CHKERRQ(ierr); 1620 } else { 1621 ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr); 1622 ierr = MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); 1623 } 1624 1625 for (i=0; i<M; i++) { 1626 1627 ierr = VecSet(&zero,in);CHKERRQ(ierr); 1628 ierr = VecSetValues(in,1,&i,&one,INSERT_VALUES);CHKERRQ(ierr); 1629 ierr = VecAssemblyBegin(in);CHKERRQ(ierr); 1630 ierr = VecAssemblyEnd(in);CHKERRQ(ierr); 1631 1632 /* should fix, allowing user to choose side */ 1633 ierr = PCApply(pc,in,out,PC_LEFT);CHKERRQ(ierr); 1634 1635 ierr = VecGetArray(out,&array);CHKERRQ(ierr); 1636 ierr = MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);CHKERRQ(ierr); 1637 ierr = VecRestoreArray(out,&array);CHKERRQ(ierr); 1638 1639 } 1640 ierr = PetscFree(rows);CHKERRQ(ierr); 1641 ierr = VecDestroy(out);CHKERRQ(ierr); 1642 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1643 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1644 PetscFunctionReturn(0); 1645 } 1646 1647