1 2 /* 3 The PC (preconditioner) interface routines, callable by users. 4 */ 5 #include <petsc/private/pcimpl.h> /*I "petscksp.h" I*/ 6 #include <petscdm.h> 7 8 /* Logging support */ 9 PetscClassId PC_CLASSID; 10 PetscLogEvent PC_SetUp, PC_SetUpOnBlocks, PC_Apply, PC_ApplyCoarse, PC_ApplyMultiple, PC_ApplySymmetricLeft; 11 PetscLogEvent PC_ApplySymmetricRight, PC_ModifySubMatrices, PC_ApplyOnBlocks, PC_ApplyTransposeOnBlocks, PC_ApplyOnMproc; 12 PetscInt PetscMGLevelId; 13 14 #undef __FUNCT__ 15 #define __FUNCT__ "PCGetDefaultType_Private" 16 PetscErrorCode PCGetDefaultType_Private(PC pc,const char *type[]) 17 { 18 PetscErrorCode ierr; 19 PetscMPIInt size; 20 PetscBool flg1,flg2,set,flg3; 21 22 PetscFunctionBegin; 23 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr); 24 if (pc->pmat) { 25 void (*f)(void); 26 ierr = MatShellGetOperation(pc->pmat,MATOP_GET_DIAGONAL_BLOCK,&f);CHKERRQ(ierr); 27 if (size == 1) { 28 ierr = MatGetFactorAvailable(pc->pmat,"petsc",MAT_FACTOR_ICC,&flg1);CHKERRQ(ierr); 29 ierr = MatGetFactorAvailable(pc->pmat,"petsc",MAT_FACTOR_ILU,&flg2);CHKERRQ(ierr); 30 ierr = MatIsSymmetricKnown(pc->pmat,&set,&flg3);CHKERRQ(ierr); 31 if (flg1 && (!flg2 || (set && flg3))) { 32 *type = PCICC; 33 } else if (flg2) { 34 *type = PCILU; 35 } else if (f) { /* likely is a parallel matrix run on one processor */ 36 *type = PCBJACOBI; 37 } else { 38 *type = PCNONE; 39 } 40 } else { 41 if (f) { 42 *type = PCBJACOBI; 43 } else { 44 *type = PCNONE; 45 } 46 } 47 } else { 48 if (size == 1) { 49 *type = PCILU; 50 } else { 51 *type = PCBJACOBI; 52 } 53 } 54 PetscFunctionReturn(0); 55 } 56 57 #undef __FUNCT__ 58 #define __FUNCT__ "PCReset" 59 /*@ 60 PCReset - Resets a PC context to the pcsetupcalled = 0 state and removes any allocated Vecs and Mats 61 62 Collective on PC 63 64 Input Parameter: 65 . pc - the preconditioner context 66 67 Level: developer 68 69 Notes: This allows a PC to be reused for a different sized linear system but using the same options that have been previously set in the PC 70 71 .keywords: PC, destroy 72 73 .seealso: PCCreate(), PCSetUp() 74 @*/ 75 PetscErrorCode PCReset(PC pc) 76 { 77 PetscErrorCode ierr; 78 79 PetscFunctionBegin; 80 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 81 if (pc->ops->reset) { 82 ierr = (*pc->ops->reset)(pc);CHKERRQ(ierr); 83 } 84 ierr = VecDestroy(&pc->diagonalscaleright);CHKERRQ(ierr); 85 ierr = VecDestroy(&pc->diagonalscaleleft);CHKERRQ(ierr); 86 ierr = MatDestroy(&pc->pmat);CHKERRQ(ierr); 87 ierr = MatDestroy(&pc->mat);CHKERRQ(ierr); 88 89 pc->setupcalled = 0; 90 PetscFunctionReturn(0); 91 } 92 93 #undef __FUNCT__ 94 #define __FUNCT__ "PCDestroy" 95 /*@ 96 PCDestroy - Destroys PC context that was created with PCCreate(). 97 98 Collective on PC 99 100 Input Parameter: 101 . pc - the preconditioner context 102 103 Level: developer 104 105 .keywords: PC, destroy 106 107 .seealso: PCCreate(), PCSetUp() 108 @*/ 109 PetscErrorCode PCDestroy(PC *pc) 110 { 111 PetscErrorCode ierr; 112 113 PetscFunctionBegin; 114 if (!*pc) PetscFunctionReturn(0); 115 PetscValidHeaderSpecific((*pc),PC_CLASSID,1); 116 if (--((PetscObject)(*pc))->refct > 0) {*pc = 0; PetscFunctionReturn(0);} 117 118 ierr = PCReset(*pc);CHKERRQ(ierr); 119 120 /* if memory was published with SAWs then destroy it */ 121 ierr = PetscObjectSAWsViewOff((PetscObject)*pc);CHKERRQ(ierr); 122 if ((*pc)->ops->destroy) {ierr = (*(*pc)->ops->destroy)((*pc));CHKERRQ(ierr);} 123 ierr = DMDestroy(&(*pc)->dm);CHKERRQ(ierr); 124 ierr = PetscHeaderDestroy(pc);CHKERRQ(ierr); 125 PetscFunctionReturn(0); 126 } 127 128 #undef __FUNCT__ 129 #define __FUNCT__ "PCGetDiagonalScale" 130 /*@C 131 PCGetDiagonalScale - Indicates if the preconditioner applies an additional left and right 132 scaling as needed by certain time-stepping codes. 133 134 Logically Collective on PC 135 136 Input Parameter: 137 . pc - the preconditioner context 138 139 Output Parameter: 140 . flag - PETSC_TRUE if it applies the scaling 141 142 Level: developer 143 144 Notes: If this returns PETSC_TRUE then the system solved via the Krylov method is 145 $ D M A D^{-1} y = D M b for left preconditioning or 146 $ D A M D^{-1} z = D b for right preconditioning 147 148 .keywords: PC 149 150 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCSetDiagonalScale() 151 @*/ 152 PetscErrorCode PCGetDiagonalScale(PC pc,PetscBool *flag) 153 { 154 PetscFunctionBegin; 155 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 156 PetscValidPointer(flag,2); 157 *flag = pc->diagonalscale; 158 PetscFunctionReturn(0); 159 } 160 161 #undef __FUNCT__ 162 #define __FUNCT__ "PCSetDiagonalScale" 163 /*@ 164 PCSetDiagonalScale - Indicates the left scaling to use to apply an additional left and right 165 scaling as needed by certain time-stepping codes. 166 167 Logically Collective on PC 168 169 Input Parameters: 170 + pc - the preconditioner context 171 - s - scaling vector 172 173 Level: intermediate 174 175 Notes: The system solved via the Krylov method is 176 $ D M A D^{-1} y = D M b for left preconditioning or 177 $ D A M D^{-1} z = D b for right preconditioning 178 179 PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}. 180 181 .keywords: PC 182 183 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCGetDiagonalScale() 184 @*/ 185 PetscErrorCode PCSetDiagonalScale(PC pc,Vec s) 186 { 187 PetscErrorCode ierr; 188 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 191 PetscValidHeaderSpecific(s,VEC_CLASSID,2); 192 pc->diagonalscale = PETSC_TRUE; 193 194 ierr = PetscObjectReference((PetscObject)s);CHKERRQ(ierr); 195 ierr = VecDestroy(&pc->diagonalscaleleft);CHKERRQ(ierr); 196 197 pc->diagonalscaleleft = s; 198 199 ierr = VecDuplicate(s,&pc->diagonalscaleright);CHKERRQ(ierr); 200 ierr = VecCopy(s,pc->diagonalscaleright);CHKERRQ(ierr); 201 ierr = VecReciprocal(pc->diagonalscaleright);CHKERRQ(ierr); 202 PetscFunctionReturn(0); 203 } 204 205 #undef __FUNCT__ 206 #define __FUNCT__ "PCDiagonalScaleLeft" 207 /*@ 208 PCDiagonalScaleLeft - Scales a vector by the left scaling as needed by certain time-stepping codes. 209 210 Logically Collective on PC 211 212 Input Parameters: 213 + pc - the preconditioner context 214 . in - input vector 215 + out - scaled vector (maybe the same as in) 216 217 Level: intermediate 218 219 Notes: The system solved via the Krylov method is 220 $ D M A D^{-1} y = D M b for left preconditioning or 221 $ D A M D^{-1} z = D b for right preconditioning 222 223 PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}. 224 225 If diagonal scaling is turned off and in is not out then in is copied to out 226 227 .keywords: PC 228 229 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale() 230 @*/ 231 PetscErrorCode PCDiagonalScaleLeft(PC pc,Vec in,Vec out) 232 { 233 PetscErrorCode ierr; 234 235 PetscFunctionBegin; 236 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 237 PetscValidHeaderSpecific(in,VEC_CLASSID,2); 238 PetscValidHeaderSpecific(out,VEC_CLASSID,3); 239 if (pc->diagonalscale) { 240 ierr = VecPointwiseMult(out,pc->diagonalscaleleft,in);CHKERRQ(ierr); 241 } else if (in != out) { 242 ierr = VecCopy(in,out);CHKERRQ(ierr); 243 } 244 PetscFunctionReturn(0); 245 } 246 247 #undef __FUNCT__ 248 #define __FUNCT__ "PCDiagonalScaleRight" 249 /*@ 250 PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes. 251 252 Logically Collective on PC 253 254 Input Parameters: 255 + pc - the preconditioner context 256 . in - input vector 257 + out - scaled vector (maybe the same as in) 258 259 Level: intermediate 260 261 Notes: The system solved via the Krylov method is 262 $ D M A D^{-1} y = D M b for left preconditioning or 263 $ D A M D^{-1} z = D b for right preconditioning 264 265 PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}. 266 267 If diagonal scaling is turned off and in is not out then in is copied to out 268 269 .keywords: PC 270 271 .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale() 272 @*/ 273 PetscErrorCode PCDiagonalScaleRight(PC pc,Vec in,Vec out) 274 { 275 PetscErrorCode ierr; 276 277 PetscFunctionBegin; 278 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 279 PetscValidHeaderSpecific(in,VEC_CLASSID,2); 280 PetscValidHeaderSpecific(out,VEC_CLASSID,3); 281 if (pc->diagonalscale) { 282 ierr = VecPointwiseMult(out,pc->diagonalscaleright,in);CHKERRQ(ierr); 283 } else if (in != out) { 284 ierr = VecCopy(in,out);CHKERRQ(ierr); 285 } 286 PetscFunctionReturn(0); 287 } 288 289 #undef __FUNCT__ 290 #define __FUNCT__ "PCSetUseAmat" 291 /*@ 292 PCSetUseAmat - Sets a flag to indicate that when the preconditioner needs to apply (part of) the 293 operator during the preconditioning process it applies the Amat provided to TSSetRHSJacobian(), 294 TSSetIJacobian(), SNESSetJacobian(), KSPSetOperator() or PCSetOperator() not the Pmat. 295 296 Logically Collective on PC 297 298 Input Parameters: 299 + pc - the preconditioner context 300 - flg - PETSC_TRUE to use the Amat, PETSC_FALSE to use the Pmat (default is false) 301 302 Options Database Key: 303 . -pc_use_amat <true,false> 304 305 Notes: 306 For the common case in which the linear system matrix and the matrix used to construct the 307 preconditioner are identical, this routine is does nothing. 308 309 Level: intermediate 310 311 .seealso: PCGetUseAmat(), PCBJACOBI, PGMG, PCFIELDSPLIT, PCCOMPOSITE 312 @*/ 313 PetscErrorCode PCSetUseAmat(PC pc,PetscBool flg) 314 { 315 PetscFunctionBegin; 316 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 317 pc->useAmat = flg; 318 PetscFunctionReturn(0); 319 } 320 321 #undef __FUNCT__ 322 #define __FUNCT__ "PCSetErrorIfFailure" 323 /*@ 324 PCSetErrorIfFailure - Causes PC to generate an error if a FPE, for example a zero pivot, is detected. 325 326 Logically Collective on PC 327 328 Input Parameters: 329 + pc - iterative context obtained from PCCreate() 330 - flg - PETSC_TRUE indicates you want the error generated 331 332 Level: advanced 333 334 Notes: 335 Normally PETSc continues if a linear solver fails due to a failed setup of a preconditioner, you can call KSPGetConvergedReason() after a KSPSolve() 336 to determine if it has converged or failed. Or use -ksp_error_if_not_converged to cause the program to terminate as soon as lack of convergence is 337 detected. 338 339 This is propagated into KSPs used by this PC, which then propagate it into PCs used by those KSPs 340 341 .keywords: PC, set, initial guess, nonzero 342 343 .seealso: PCGetInitialGuessNonzero(), PCSetInitialGuessKnoll(), PCGetInitialGuessKnoll() 344 @*/ 345 PetscErrorCode PCSetErrorIfFailure(PC pc,PetscBool flg) 346 { 347 PetscFunctionBegin; 348 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 349 PetscValidLogicalCollectiveBool(pc,flg,2); 350 pc->erroriffailure = flg; 351 PetscFunctionReturn(0); 352 } 353 354 #undef __FUNCT__ 355 #define __FUNCT__ "PCGetUseAmat" 356 /*@ 357 PCGetUseAmat - Gets a flag to indicate that when the preconditioner needs to apply (part of) the 358 operator during the preconditioning process it applies the Amat provided to TSSetRHSJacobian(), 359 TSSetIJacobian(), SNESSetJacobian(), KSPSetOperator() or PCSetOperator() not the Pmat. 360 361 Logically Collective on PC 362 363 Input Parameter: 364 . pc - the preconditioner context 365 366 Output Parameter: 367 . flg - PETSC_TRUE to use the Amat, PETSC_FALSE to use the Pmat (default is false) 368 369 Notes: 370 For the common case in which the linear system matrix and the matrix used to construct the 371 preconditioner are identical, this routine is does nothing. 372 373 Level: intermediate 374 375 .seealso: PCSetUseAmat(), PCBJACOBI, PGMG, PCFIELDSPLIT, PCCOMPOSITE 376 @*/ 377 PetscErrorCode PCGetUseAmat(PC pc,PetscBool *flg) 378 { 379 PetscFunctionBegin; 380 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 381 *flg = pc->useAmat; 382 PetscFunctionReturn(0); 383 } 384 385 #undef __FUNCT__ 386 #define __FUNCT__ "PCCreate" 387 /*@ 388 PCCreate - Creates a preconditioner context. 389 390 Collective on MPI_Comm 391 392 Input Parameter: 393 . comm - MPI communicator 394 395 Output Parameter: 396 . pc - location to put the preconditioner context 397 398 Notes: 399 The default preconditioner for sparse matrices is PCILU or PCICC with 0 fill on one process and block Jacobi with PCILU or ICC 400 in parallel. For dense matrices it is always PCNONE. 401 402 Level: developer 403 404 .keywords: PC, create, context 405 406 .seealso: PCSetUp(), PCApply(), PCDestroy() 407 @*/ 408 PetscErrorCode PCCreate(MPI_Comm comm,PC *newpc) 409 { 410 PC pc; 411 PetscErrorCode ierr; 412 413 PetscFunctionBegin; 414 PetscValidPointer(newpc,1); 415 *newpc = 0; 416 ierr = PCInitializePackage();CHKERRQ(ierr); 417 418 ierr = PetscHeaderCreate(pc,PC_CLASSID,"PC","Preconditioner","PC",comm,PCDestroy,PCView);CHKERRQ(ierr); 419 420 pc->mat = 0; 421 pc->pmat = 0; 422 pc->setupcalled = 0; 423 pc->setfromoptionscalled = 0; 424 pc->data = 0; 425 pc->diagonalscale = PETSC_FALSE; 426 pc->diagonalscaleleft = 0; 427 pc->diagonalscaleright = 0; 428 429 pc->modifysubmatrices = 0; 430 pc->modifysubmatricesP = 0; 431 432 *newpc = pc; 433 PetscFunctionReturn(0); 434 435 } 436 437 /* -------------------------------------------------------------------------------*/ 438 439 #undef __FUNCT__ 440 #define __FUNCT__ "PCApply" 441 /*@ 442 PCApply - Applies the preconditioner to a vector. 443 444 Collective on PC and Vec 445 446 Input Parameters: 447 + pc - the preconditioner context 448 - x - input vector 449 450 Output Parameter: 451 . y - output vector 452 453 Level: developer 454 455 .keywords: PC, apply 456 457 .seealso: PCApplyTranspose(), PCApplyBAorAB() 458 @*/ 459 PetscErrorCode PCApply(PC pc,Vec x,Vec y) 460 { 461 PetscErrorCode ierr; 462 PetscInt m,n,mv,nv; 463 464 PetscFunctionBegin; 465 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 466 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 467 PetscValidHeaderSpecific(y,VEC_CLASSID,3); 468 if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 469 if (pc->erroriffailure) {ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr);} 470 /* use pmat to check vector sizes since for KSPLQR the pmat may be of a different size than mat */ 471 ierr = MatGetLocalSize(pc->pmat,&m,&n);CHKERRQ(ierr); 472 ierr = VecGetLocalSize(x,&nv);CHKERRQ(ierr); 473 ierr = VecGetLocalSize(y,&mv);CHKERRQ(ierr); 474 if (mv != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Preconditioner number of local rows %D does not equal resulting vector number of rows %D",m,mv);CHKERRQ(ierr); 475 if (nv != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Preconditioner number of local columns %D does not equal resulting vector number of rows %D",n,nv);CHKERRQ(ierr); 476 VecLocked(y,3); 477 478 ierr = PCSetUp(pc);CHKERRQ(ierr); 479 if (!pc->ops->apply) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply"); 480 ierr = VecLockPush(x);CHKERRQ(ierr); 481 ierr = PetscLogEventBegin(PC_Apply,pc,x,y,0);CHKERRQ(ierr); 482 ierr = (*pc->ops->apply)(pc,x,y);CHKERRQ(ierr); 483 ierr = PetscLogEventEnd(PC_Apply,pc,x,y,0);CHKERRQ(ierr); 484 if (pc->erroriffailure) {ierr = VecValidValues(y,3,PETSC_FALSE);CHKERRQ(ierr);} 485 ierr = VecLockPop(x);CHKERRQ(ierr); 486 PetscFunctionReturn(0); 487 } 488 489 #undef __FUNCT__ 490 #define __FUNCT__ "PCApplySymmetricLeft" 491 /*@ 492 PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector. 493 494 Collective on PC and Vec 495 496 Input Parameters: 497 + pc - the preconditioner context 498 - x - input vector 499 500 Output Parameter: 501 . y - output vector 502 503 Notes: 504 Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners. 505 506 Level: developer 507 508 .keywords: PC, apply, symmetric, left 509 510 .seealso: PCApply(), PCApplySymmetricRight() 511 @*/ 512 PetscErrorCode PCApplySymmetricLeft(PC pc,Vec x,Vec y) 513 { 514 PetscErrorCode ierr; 515 516 PetscFunctionBegin; 517 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 518 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 519 PetscValidHeaderSpecific(y,VEC_CLASSID,3); 520 if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 521 if (pc->erroriffailure) {ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr);} 522 ierr = PCSetUp(pc);CHKERRQ(ierr); 523 if (!pc->ops->applysymmetricleft) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have left symmetric apply"); 524 ierr = VecLockPush(x);CHKERRQ(ierr); 525 ierr = PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);CHKERRQ(ierr); 526 ierr = (*pc->ops->applysymmetricleft)(pc,x,y);CHKERRQ(ierr); 527 ierr = PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);CHKERRQ(ierr); 528 ierr = VecLockPop(x);CHKERRQ(ierr); 529 if (pc->erroriffailure) {ierr = VecValidValues(y,3,PETSC_FALSE);CHKERRQ(ierr);} 530 PetscFunctionReturn(0); 531 } 532 533 #undef __FUNCT__ 534 #define __FUNCT__ "PCApplySymmetricRight" 535 /*@ 536 PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector. 537 538 Collective on PC and Vec 539 540 Input Parameters: 541 + pc - the preconditioner context 542 - x - input vector 543 544 Output Parameter: 545 . y - output vector 546 547 Level: developer 548 549 Notes: 550 Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners. 551 552 .keywords: PC, apply, symmetric, right 553 554 .seealso: PCApply(), PCApplySymmetricLeft() 555 @*/ 556 PetscErrorCode PCApplySymmetricRight(PC pc,Vec x,Vec y) 557 { 558 PetscErrorCode ierr; 559 560 PetscFunctionBegin; 561 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 562 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 563 PetscValidHeaderSpecific(y,VEC_CLASSID,3); 564 if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 565 if (pc->erroriffailure) {ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr);} 566 ierr = PCSetUp(pc);CHKERRQ(ierr); 567 if (!pc->ops->applysymmetricright) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have left symmetric apply"); 568 ierr = VecLockPush(x);CHKERRQ(ierr); 569 ierr = PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);CHKERRQ(ierr); 570 ierr = (*pc->ops->applysymmetricright)(pc,x,y);CHKERRQ(ierr); 571 ierr = PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);CHKERRQ(ierr); 572 ierr = VecLockPop(x);CHKERRQ(ierr); 573 if (pc->erroriffailure) {ierr = VecValidValues(y,3,PETSC_FALSE);CHKERRQ(ierr);} 574 PetscFunctionReturn(0); 575 } 576 577 #undef __FUNCT__ 578 #define __FUNCT__ "PCApplyTranspose" 579 /*@ 580 PCApplyTranspose - Applies the transpose of preconditioner to a vector. 581 582 Collective on PC and Vec 583 584 Input Parameters: 585 + pc - the preconditioner context 586 - x - input vector 587 588 Output Parameter: 589 . y - output vector 590 591 Notes: For complex numbers this applies the non-Hermitian transpose. 592 593 Developer Notes: We need to implement a PCApplyHermitianTranspose() 594 595 Level: developer 596 597 .keywords: PC, apply, transpose 598 599 .seealso: PCApply(), PCApplyBAorAB(), PCApplyBAorABTranspose(), PCApplyTransposeExists() 600 @*/ 601 PetscErrorCode PCApplyTranspose(PC pc,Vec x,Vec y) 602 { 603 PetscErrorCode ierr; 604 605 PetscFunctionBegin; 606 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 607 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 608 PetscValidHeaderSpecific(y,VEC_CLASSID,3); 609 if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 610 if (pc->erroriffailure) {ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr);} 611 ierr = PCSetUp(pc);CHKERRQ(ierr); 612 if (!pc->ops->applytranspose) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply transpose"); 613 ierr = VecLockPush(x);CHKERRQ(ierr); 614 ierr = PetscLogEventBegin(PC_Apply,pc,x,y,0);CHKERRQ(ierr); 615 ierr = (*pc->ops->applytranspose)(pc,x,y);CHKERRQ(ierr); 616 ierr = PetscLogEventEnd(PC_Apply,pc,x,y,0);CHKERRQ(ierr); 617 ierr = VecLockPop(x);CHKERRQ(ierr); 618 if (pc->erroriffailure) {ierr = VecValidValues(y,3,PETSC_FALSE);CHKERRQ(ierr);} 619 PetscFunctionReturn(0); 620 } 621 622 #undef __FUNCT__ 623 #define __FUNCT__ "PCApplyTransposeExists" 624 /*@ 625 PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation 626 627 Collective on PC and Vec 628 629 Input Parameters: 630 . pc - the preconditioner context 631 632 Output Parameter: 633 . flg - PETSC_TRUE if a transpose operation is defined 634 635 Level: developer 636 637 .keywords: PC, apply, transpose 638 639 .seealso: PCApplyTranspose() 640 @*/ 641 PetscErrorCode PCApplyTransposeExists(PC pc,PetscBool *flg) 642 { 643 PetscFunctionBegin; 644 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 645 PetscValidPointer(flg,2); 646 if (pc->ops->applytranspose) *flg = PETSC_TRUE; 647 else *flg = PETSC_FALSE; 648 PetscFunctionReturn(0); 649 } 650 651 #undef __FUNCT__ 652 #define __FUNCT__ "PCApplyBAorAB" 653 /*@ 654 PCApplyBAorAB - Applies the preconditioner and operator to a vector. y = B*A*x or y = A*B*x. 655 656 Collective on PC and Vec 657 658 Input Parameters: 659 + pc - the preconditioner context 660 . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC 661 . x - input vector 662 - work - work vector 663 664 Output Parameter: 665 . y - output vector 666 667 Level: developer 668 669 Notes: If the PC has had PCSetDiagonalScale() set then D M A D^{-1} for left preconditioning or D A M D^{-1} is actually applied. Note that the 670 specific KSPSolve() method must also be written to handle the post-solve "correction" for the diagonal scaling. 671 672 .keywords: PC, apply, operator 673 674 .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose() 675 @*/ 676 PetscErrorCode PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work) 677 { 678 PetscErrorCode ierr; 679 680 PetscFunctionBegin; 681 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 682 PetscValidHeaderSpecific(x,VEC_CLASSID,3); 683 PetscValidHeaderSpecific(y,VEC_CLASSID,4); 684 PetscValidHeaderSpecific(work,VEC_CLASSID,5); 685 if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 686 if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric"); 687 if (pc->diagonalscale && side == PC_SYMMETRIC) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot include diagonal scaling with symmetric preconditioner application"); 688 if (pc->erroriffailure) {ierr = VecValidValues(x,3,PETSC_TRUE);CHKERRQ(ierr);} 689 690 ierr = PCSetUp(pc);CHKERRQ(ierr); 691 if (pc->diagonalscale) { 692 if (pc->ops->applyBA) { 693 Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */ 694 ierr = VecDuplicate(x,&work2);CHKERRQ(ierr); 695 ierr = PCDiagonalScaleRight(pc,x,work2);CHKERRQ(ierr); 696 ierr = (*pc->ops->applyBA)(pc,side,work2,y,work);CHKERRQ(ierr); 697 ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr); 698 ierr = VecDestroy(&work2);CHKERRQ(ierr); 699 } else if (side == PC_RIGHT) { 700 ierr = PCDiagonalScaleRight(pc,x,y);CHKERRQ(ierr); 701 ierr = PCApply(pc,y,work);CHKERRQ(ierr); 702 ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr); 703 ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr); 704 } else if (side == PC_LEFT) { 705 ierr = PCDiagonalScaleRight(pc,x,y);CHKERRQ(ierr); 706 ierr = MatMult(pc->mat,y,work);CHKERRQ(ierr); 707 ierr = PCApply(pc,work,y);CHKERRQ(ierr); 708 ierr = PCDiagonalScaleLeft(pc,y,y);CHKERRQ(ierr); 709 } else if (side == PC_SYMMETRIC) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot provide diagonal scaling with symmetric application of preconditioner"); 710 } else { 711 if (pc->ops->applyBA) { 712 ierr = (*pc->ops->applyBA)(pc,side,x,y,work);CHKERRQ(ierr); 713 } else if (side == PC_RIGHT) { 714 ierr = PCApply(pc,x,work);CHKERRQ(ierr); 715 ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr); 716 } else if (side == PC_LEFT) { 717 ierr = MatMult(pc->mat,x,work);CHKERRQ(ierr); 718 ierr = PCApply(pc,work,y);CHKERRQ(ierr); 719 } else if (side == PC_SYMMETRIC) { 720 /* There's an extra copy here; maybe should provide 2 work vectors instead? */ 721 ierr = PCApplySymmetricRight(pc,x,work);CHKERRQ(ierr); 722 ierr = MatMult(pc->mat,work,y);CHKERRQ(ierr); 723 ierr = VecCopy(y,work);CHKERRQ(ierr); 724 ierr = PCApplySymmetricLeft(pc,work,y);CHKERRQ(ierr); 725 } 726 } 727 if (pc->erroriffailure) {ierr = VecValidValues(y,4,PETSC_FALSE);CHKERRQ(ierr);} 728 PetscFunctionReturn(0); 729 } 730 731 #undef __FUNCT__ 732 #define __FUNCT__ "PCApplyBAorABTranspose" 733 /*@ 734 PCApplyBAorABTranspose - Applies the transpose of the preconditioner 735 and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning, 736 NOT tr(B*A) = tr(A)*tr(B). 737 738 Collective on PC and Vec 739 740 Input Parameters: 741 + pc - the preconditioner context 742 . side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC 743 . x - input vector 744 - work - work vector 745 746 Output Parameter: 747 . y - output vector 748 749 750 Notes: this routine is used internally so that the same Krylov code can be used to solve A x = b and A' x = b, with a preconditioner 751 defined by B'. This is why this has the funny form that it computes tr(B) * tr(A) 752 753 Level: developer 754 755 .keywords: PC, apply, operator, transpose 756 757 .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB() 758 @*/ 759 PetscErrorCode PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work) 760 { 761 PetscErrorCode ierr; 762 763 PetscFunctionBegin; 764 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 765 PetscValidHeaderSpecific(x,VEC_CLASSID,3); 766 PetscValidHeaderSpecific(y,VEC_CLASSID,4); 767 PetscValidHeaderSpecific(work,VEC_CLASSID,5); 768 if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 769 if (pc->erroriffailure) {ierr = VecValidValues(x,3,PETSC_TRUE);CHKERRQ(ierr);} 770 if (pc->ops->applyBAtranspose) { 771 ierr = (*pc->ops->applyBAtranspose)(pc,side,x,y,work);CHKERRQ(ierr); 772 if (pc->erroriffailure) {ierr = VecValidValues(y,4,PETSC_FALSE);CHKERRQ(ierr);} 773 PetscFunctionReturn(0); 774 } 775 if (side != PC_LEFT && side != PC_RIGHT) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left"); 776 777 ierr = PCSetUp(pc);CHKERRQ(ierr); 778 if (side == PC_RIGHT) { 779 ierr = PCApplyTranspose(pc,x,work);CHKERRQ(ierr); 780 ierr = MatMultTranspose(pc->mat,work,y);CHKERRQ(ierr); 781 } else if (side == PC_LEFT) { 782 ierr = MatMultTranspose(pc->mat,x,work);CHKERRQ(ierr); 783 ierr = PCApplyTranspose(pc,work,y);CHKERRQ(ierr); 784 } 785 /* add support for PC_SYMMETRIC */ 786 if (pc->erroriffailure) {ierr = VecValidValues(y,4,PETSC_FALSE);CHKERRQ(ierr);} 787 PetscFunctionReturn(0); 788 } 789 790 /* -------------------------------------------------------------------------------*/ 791 792 #undef __FUNCT__ 793 #define __FUNCT__ "PCApplyRichardsonExists" 794 /*@ 795 PCApplyRichardsonExists - Determines whether a particular preconditioner has a 796 built-in fast application of Richardson's method. 797 798 Not Collective 799 800 Input Parameter: 801 . pc - the preconditioner 802 803 Output Parameter: 804 . exists - PETSC_TRUE or PETSC_FALSE 805 806 Level: developer 807 808 .keywords: PC, apply, Richardson, exists 809 810 .seealso: PCApplyRichardson() 811 @*/ 812 PetscErrorCode PCApplyRichardsonExists(PC pc,PetscBool *exists) 813 { 814 PetscFunctionBegin; 815 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 816 PetscValidIntPointer(exists,2); 817 if (pc->ops->applyrichardson) *exists = PETSC_TRUE; 818 else *exists = PETSC_FALSE; 819 PetscFunctionReturn(0); 820 } 821 822 #undef __FUNCT__ 823 #define __FUNCT__ "PCApplyRichardson" 824 /*@ 825 PCApplyRichardson - Applies several steps of Richardson iteration with 826 the particular preconditioner. This routine is usually used by the 827 Krylov solvers and not the application code directly. 828 829 Collective on PC 830 831 Input Parameters: 832 + pc - the preconditioner context 833 . b - the right hand side 834 . w - one work vector 835 . rtol - relative decrease in residual norm convergence criteria 836 . abstol - absolute residual norm convergence criteria 837 . dtol - divergence residual norm increase criteria 838 . its - the number of iterations to apply. 839 - guesszero - if the input x contains nonzero initial guess 840 841 Output Parameter: 842 + outits - number of iterations actually used (for SOR this always equals its) 843 . reason - the reason the apply terminated 844 - y - the solution (also contains initial guess if guesszero is PETSC_FALSE 845 846 Notes: 847 Most preconditioners do not support this function. Use the command 848 PCApplyRichardsonExists() to determine if one does. 849 850 Except for the multigrid PC this routine ignores the convergence tolerances 851 and always runs for the number of iterations 852 853 Level: developer 854 855 .keywords: PC, apply, Richardson 856 857 .seealso: PCApplyRichardsonExists() 858 @*/ 859 PetscErrorCode PCApplyRichardson(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason) 860 { 861 PetscErrorCode ierr; 862 863 PetscFunctionBegin; 864 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 865 PetscValidHeaderSpecific(b,VEC_CLASSID,2); 866 PetscValidHeaderSpecific(y,VEC_CLASSID,3); 867 PetscValidHeaderSpecific(w,VEC_CLASSID,4); 868 if (b == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"b and y must be different vectors"); 869 ierr = PCSetUp(pc);CHKERRQ(ierr); 870 if (!pc->ops->applyrichardson) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply richardson"); 871 ierr = (*pc->ops->applyrichardson)(pc,b,y,w,rtol,abstol,dtol,its,guesszero,outits,reason);CHKERRQ(ierr); 872 PetscFunctionReturn(0); 873 } 874 875 #undef __FUNCT__ 876 #define __FUNCT__ "PCGetSetUpFailedReason" 877 /*@ 878 PCGetSetUpFailedReason - Gets the reason a PCSetUp() failed or 0 if it did not fail 879 880 Logically Collective on PC 881 882 Input Parameter: 883 . pc - the preconditioner context 884 885 Output Parameter: 886 . reason - the reason it failed, currently only -1 887 888 Level: advanced 889 890 .keywords: PC, setup 891 892 .seealso: PCCreate(), PCApply(), PCDestroy() 893 @*/ 894 PetscErrorCode PCGetSetUpFailedReason(PC pc,PCFailedReason *reason) 895 { 896 PetscFunctionBegin; 897 if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled; 898 else *reason = pc->failedreason; 899 PetscFunctionReturn(0); 900 } 901 902 903 /* 904 a setupcall of 0 indicates never setup, 905 1 indicates has been previously setup 906 -1 indicates a PCSetUp() was attempted and failed 907 */ 908 #undef __FUNCT__ 909 #define __FUNCT__ "PCSetUp" 910 /*@ 911 PCSetUp - Prepares for the use of a preconditioner. 912 913 Collective on PC 914 915 Input Parameter: 916 . pc - the preconditioner context 917 918 Level: developer 919 920 .keywords: PC, setup 921 922 .seealso: PCCreate(), PCApply(), PCDestroy() 923 @*/ 924 PetscErrorCode PCSetUp(PC pc) 925 { 926 PetscErrorCode ierr; 927 const char *def; 928 PetscObjectState matstate, matnonzerostate; 929 930 PetscFunctionBegin; 931 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 932 if (!pc->mat) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first"); 933 934 if (pc->setupcalled && pc->reusepreconditioner) { 935 ierr = PetscInfo(pc,"Leaving PC with identical preconditioner since reuse preconditioner is set\n");CHKERRQ(ierr); 936 PetscFunctionReturn(0); 937 } 938 939 ierr = PetscObjectStateGet((PetscObject)pc->pmat,&matstate);CHKERRQ(ierr); 940 ierr = MatGetNonzeroState(pc->pmat,&matnonzerostate);CHKERRQ(ierr); 941 if (!pc->setupcalled) { 942 ierr = PetscInfo(pc,"Setting up PC for first time\n");CHKERRQ(ierr); 943 pc->flag = DIFFERENT_NONZERO_PATTERN; 944 } else if (matstate == pc->matstate) { 945 ierr = PetscInfo(pc,"Leaving PC with identical preconditioner since operator is unchanged\n");CHKERRQ(ierr); 946 PetscFunctionReturn(0); 947 } else { 948 if (matnonzerostate > pc->matnonzerostate) { 949 ierr = PetscInfo(pc,"Setting up PC with different nonzero pattern\n");CHKERRQ(ierr); 950 pc->flag = DIFFERENT_NONZERO_PATTERN; 951 } else { 952 ierr = PetscInfo(pc,"Setting up PC with same nonzero pattern\n");CHKERRQ(ierr); 953 pc->flag = SAME_NONZERO_PATTERN; 954 } 955 } 956 pc->matstate = matstate; 957 pc->matnonzerostate = matnonzerostate; 958 959 if (!((PetscObject)pc)->type_name) { 960 ierr = PCGetDefaultType_Private(pc,&def);CHKERRQ(ierr); 961 ierr = PCSetType(pc,def);CHKERRQ(ierr); 962 } 963 964 ierr = MatSetErrorIfFailure(pc->pmat,pc->erroriffailure);CHKERRQ(ierr); 965 ierr = MatSetErrorIfFailure(pc->mat,pc->erroriffailure);CHKERRQ(ierr); 966 ierr = PetscLogEventBegin(PC_SetUp,pc,0,0,0);CHKERRQ(ierr); 967 if (pc->ops->setup) { 968 ierr = (*pc->ops->setup)(pc);CHKERRQ(ierr); 969 } 970 ierr = PetscLogEventEnd(PC_SetUp,pc,0,0,0);CHKERRQ(ierr); 971 if (!pc->setupcalled) pc->setupcalled = 1; 972 PetscFunctionReturn(0); 973 } 974 975 #undef __FUNCT__ 976 #define __FUNCT__ "PCSetUpOnBlocks" 977 /*@ 978 PCSetUpOnBlocks - Sets up the preconditioner for each block in 979 the block Jacobi, block Gauss-Seidel, and overlapping Schwarz 980 methods. 981 982 Collective on PC 983 984 Input Parameters: 985 . pc - the preconditioner context 986 987 Level: developer 988 989 .keywords: PC, setup, blocks 990 991 .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp() 992 @*/ 993 PetscErrorCode PCSetUpOnBlocks(PC pc) 994 { 995 PetscErrorCode ierr; 996 997 PetscFunctionBegin; 998 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 999 if (!pc->ops->setuponblocks) PetscFunctionReturn(0); 1000 ierr = PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);CHKERRQ(ierr); 1001 ierr = (*pc->ops->setuponblocks)(pc);CHKERRQ(ierr); 1002 ierr = PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);CHKERRQ(ierr); 1003 PetscFunctionReturn(0); 1004 } 1005 1006 #undef __FUNCT__ 1007 #define __FUNCT__ "PCSetModifySubMatrices" 1008 /*@C 1009 PCSetModifySubMatrices - Sets a user-defined routine for modifying the 1010 submatrices that arise within certain subdomain-based preconditioners. 1011 The basic submatrices are extracted from the preconditioner matrix as 1012 usual; the user can then alter these (for example, to set different boundary 1013 conditions for each submatrix) before they are used for the local solves. 1014 1015 Logically Collective on PC 1016 1017 Input Parameters: 1018 + pc - the preconditioner context 1019 . func - routine for modifying the submatrices 1020 - ctx - optional user-defined context (may be null) 1021 1022 Calling sequence of func: 1023 $ func (PC pc,PetscInt nsub,IS *row,IS *col,Mat *submat,void *ctx); 1024 1025 . row - an array of index sets that contain the global row numbers 1026 that comprise each local submatrix 1027 . col - an array of index sets that contain the global column numbers 1028 that comprise each local submatrix 1029 . submat - array of local submatrices 1030 - ctx - optional user-defined context for private data for the 1031 user-defined func routine (may be null) 1032 1033 Notes: 1034 PCSetModifySubMatrices() MUST be called before KSPSetUp() and 1035 KSPSolve(). 1036 1037 A routine set by PCSetModifySubMatrices() is currently called within 1038 the block Jacobi (PCBJACOBI) and additive Schwarz (PCASM) 1039 preconditioners. All other preconditioners ignore this routine. 1040 1041 Level: advanced 1042 1043 .keywords: PC, set, modify, submatrices 1044 1045 .seealso: PCModifySubMatrices(), PCASMGetSubMatrices() 1046 @*/ 1047 PetscErrorCode PCSetModifySubMatrices(PC pc,PetscErrorCode (*func)(PC,PetscInt,const IS[],const IS[],Mat[],void*),void *ctx) 1048 { 1049 PetscFunctionBegin; 1050 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1051 pc->modifysubmatrices = func; 1052 pc->modifysubmatricesP = ctx; 1053 PetscFunctionReturn(0); 1054 } 1055 1056 #undef __FUNCT__ 1057 #define __FUNCT__ "PCModifySubMatrices" 1058 /*@C 1059 PCModifySubMatrices - Calls an optional user-defined routine within 1060 certain preconditioners if one has been set with PCSetModifySubMarices(). 1061 1062 Collective on PC 1063 1064 Input Parameters: 1065 + pc - the preconditioner context 1066 . nsub - the number of local submatrices 1067 . row - an array of index sets that contain the global row numbers 1068 that comprise each local submatrix 1069 . col - an array of index sets that contain the global column numbers 1070 that comprise each local submatrix 1071 . submat - array of local submatrices 1072 - ctx - optional user-defined context for private data for the 1073 user-defined routine (may be null) 1074 1075 Output Parameter: 1076 . submat - array of local submatrices (the entries of which may 1077 have been modified) 1078 1079 Notes: 1080 The user should NOT generally call this routine, as it will 1081 automatically be called within certain preconditioners (currently 1082 block Jacobi, additive Schwarz) if set. 1083 1084 The basic submatrices are extracted from the preconditioner matrix 1085 as usual; the user can then alter these (for example, to set different 1086 boundary conditions for each submatrix) before they are used for the 1087 local solves. 1088 1089 Level: developer 1090 1091 .keywords: PC, modify, submatrices 1092 1093 .seealso: PCSetModifySubMatrices() 1094 @*/ 1095 PetscErrorCode PCModifySubMatrices(PC pc,PetscInt nsub,const IS row[],const IS col[],Mat submat[],void *ctx) 1096 { 1097 PetscErrorCode ierr; 1098 1099 PetscFunctionBegin; 1100 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1101 if (!pc->modifysubmatrices) PetscFunctionReturn(0); 1102 ierr = PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);CHKERRQ(ierr); 1103 ierr = (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);CHKERRQ(ierr); 1104 ierr = PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);CHKERRQ(ierr); 1105 PetscFunctionReturn(0); 1106 } 1107 1108 #undef __FUNCT__ 1109 #define __FUNCT__ "PCSetOperators" 1110 /*@ 1111 PCSetOperators - Sets the matrix associated with the linear system and 1112 a (possibly) different one associated with the preconditioner. 1113 1114 Logically Collective on PC and Mat 1115 1116 Input Parameters: 1117 + pc - the preconditioner context 1118 . Amat - the matrix that defines the linear system 1119 - Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat. 1120 1121 Notes: 1122 Passing a NULL for Amat or Pmat removes the matrix that is currently used. 1123 1124 If you wish to replace either Amat or Pmat but leave the other one untouched then 1125 first call KSPGetOperators() to get the one you wish to keep, call PetscObjectReference() 1126 on it and then pass it back in in your call to KSPSetOperators(). 1127 1128 More Notes about Repeated Solution of Linear Systems: 1129 PETSc does NOT reset the matrix entries of either Amat or Pmat 1130 to zero after a linear solve; the user is completely responsible for 1131 matrix assembly. See the routine MatZeroEntries() if desiring to 1132 zero all elements of a matrix. 1133 1134 Level: intermediate 1135 1136 .keywords: PC, set, operators, matrix, linear system 1137 1138 .seealso: PCGetOperators(), MatZeroEntries() 1139 @*/ 1140 PetscErrorCode PCSetOperators(PC pc,Mat Amat,Mat Pmat) 1141 { 1142 PetscErrorCode ierr; 1143 PetscInt m1,n1,m2,n2; 1144 1145 PetscFunctionBegin; 1146 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1147 if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 1148 if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3); 1149 if (Amat) PetscCheckSameComm(pc,1,Amat,2); 1150 if (Pmat) PetscCheckSameComm(pc,1,Pmat,3); 1151 if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) { 1152 ierr = MatGetLocalSize(Amat,&m1,&n1);CHKERRQ(ierr); 1153 ierr = MatGetLocalSize(pc->mat,&m2,&n2);CHKERRQ(ierr); 1154 if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot change local size of Amat after use old sizes %D %D new sizes %D %D",m2,n2,m1,n1); 1155 ierr = MatGetLocalSize(Pmat,&m1,&n1);CHKERRQ(ierr); 1156 ierr = MatGetLocalSize(pc->pmat,&m2,&n2);CHKERRQ(ierr); 1157 if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot change local size of Pmat after use old sizes %D %D new sizes %D %D",m2,n2,m1,n1); 1158 } 1159 1160 if (Pmat != pc->pmat) { 1161 /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */ 1162 pc->matnonzerostate = -1; 1163 pc->matstate = -1; 1164 } 1165 1166 /* reference first in case the matrices are the same */ 1167 if (Amat) {ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);} 1168 ierr = MatDestroy(&pc->mat);CHKERRQ(ierr); 1169 if (Pmat) {ierr = PetscObjectReference((PetscObject)Pmat);CHKERRQ(ierr);} 1170 ierr = MatDestroy(&pc->pmat);CHKERRQ(ierr); 1171 pc->mat = Amat; 1172 pc->pmat = Pmat; 1173 PetscFunctionReturn(0); 1174 } 1175 1176 #undef __FUNCT__ 1177 #define __FUNCT__ "PCSetReusePreconditioner" 1178 /*@ 1179 PCSetReusePreconditioner - reuse the current preconditioner even if the operator in the preconditioner has changed. 1180 1181 Logically Collective on PC 1182 1183 Input Parameters: 1184 + pc - the preconditioner context 1185 - flag - PETSC_TRUE do not compute a new preconditioner, PETSC_FALSE do compute a new preconditioner 1186 1187 Level: intermediate 1188 1189 .seealso: PCGetOperators(), MatZeroEntries(), PCGetReusePreconditioner(), KSPSetReusePreconditioner() 1190 @*/ 1191 PetscErrorCode PCSetReusePreconditioner(PC pc,PetscBool flag) 1192 { 1193 PetscFunctionBegin; 1194 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1195 pc->reusepreconditioner = flag; 1196 PetscFunctionReturn(0); 1197 } 1198 1199 #undef __FUNCT__ 1200 #define __FUNCT__ "PCGetReusePreconditioner" 1201 /*@ 1202 PCGetReusePreconditioner - Determines if the PC reuses the current preconditioner even if the operator in the preconditioner has changed. 1203 1204 Not Collective 1205 1206 Input Parameter: 1207 . pc - the preconditioner context 1208 1209 Output Parameter: 1210 . flag - PETSC_TRUE do not compute a new preconditioner, PETSC_FALSE do compute a new preconditioner 1211 1212 Level: intermediate 1213 1214 .seealso: PCGetOperators(), MatZeroEntries(), PCSetReusePreconditioner() 1215 @*/ 1216 PetscErrorCode PCGetReusePreconditioner(PC pc,PetscBool *flag) 1217 { 1218 PetscFunctionBegin; 1219 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1220 *flag = pc->reusepreconditioner; 1221 PetscFunctionReturn(0); 1222 } 1223 1224 #undef __FUNCT__ 1225 #define __FUNCT__ "PCGetOperators" 1226 /*@C 1227 PCGetOperators - Gets the matrix associated with the linear system and 1228 possibly a different one associated with the preconditioner. 1229 1230 Not collective, though parallel Mats are returned if the PC is parallel 1231 1232 Input Parameter: 1233 . pc - the preconditioner context 1234 1235 Output Parameters: 1236 + Amat - the matrix defining the linear system 1237 - Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat. 1238 1239 Level: intermediate 1240 1241 Notes: Does not increase the reference count of the matrices, so you should not destroy them 1242 1243 Alternative usage: If the operators have NOT been set with KSP/PCSetOperators() then the operators 1244 are created in PC and returned to the user. In this case, if both operators 1245 mat and pmat are requested, two DIFFERENT operators will be returned. If 1246 only one is requested both operators in the PC will be the same (i.e. as 1247 if one had called KSP/PCSetOperators() with the same argument for both Mats). 1248 The user must set the sizes of the returned matrices and their type etc just 1249 as if the user created them with MatCreate(). For example, 1250 1251 $ KSP/PCGetOperators(ksp/pc,&Amat,NULL); is equivalent to 1252 $ set size, type, etc of Amat 1253 1254 $ MatCreate(comm,&mat); 1255 $ KSP/PCSetOperators(ksp/pc,Amat,Amat); 1256 $ PetscObjectDereference((PetscObject)mat); 1257 $ set size, type, etc of Amat 1258 1259 and 1260 1261 $ KSP/PCGetOperators(ksp/pc,&Amat,&Pmat); is equivalent to 1262 $ set size, type, etc of Amat and Pmat 1263 1264 $ MatCreate(comm,&Amat); 1265 $ MatCreate(comm,&Pmat); 1266 $ KSP/PCSetOperators(ksp/pc,Amat,Pmat); 1267 $ PetscObjectDereference((PetscObject)Amat); 1268 $ PetscObjectDereference((PetscObject)Pmat); 1269 $ set size, type, etc of Amat and Pmat 1270 1271 The rational for this support is so that when creating a TS, SNES, or KSP the hierarchy 1272 of underlying objects (i.e. SNES, KSP, PC, Mat) and their livespans can be completely 1273 managed by the top most level object (i.e. the TS, SNES, or KSP). Another way to look 1274 at this is when you create a SNES you do not NEED to create a KSP and attach it to 1275 the SNES object (the SNES object manages it for you). Similarly when you create a KSP 1276 you do not need to attach a PC to it (the KSP object manages the PC object for you). 1277 Thus, why should YOU have to create the Mat and attach it to the SNES/KSP/PC, when 1278 it can be created for you? 1279 1280 1281 .keywords: PC, get, operators, matrix, linear system 1282 1283 .seealso: PCSetOperators(), KSPGetOperators(), KSPSetOperators(), PCGetOperatorsSet() 1284 @*/ 1285 PetscErrorCode PCGetOperators(PC pc,Mat *Amat,Mat *Pmat) 1286 { 1287 PetscErrorCode ierr; 1288 1289 PetscFunctionBegin; 1290 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1291 if (Amat) { 1292 if (!pc->mat) { 1293 if (pc->pmat && !Pmat) { /* Apmat has been set, but user did not request it, so use for Amat */ 1294 pc->mat = pc->pmat; 1295 ierr = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr); 1296 } else { /* both Amat and Pmat are empty */ 1297 ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pc->mat);CHKERRQ(ierr); 1298 if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */ 1299 pc->pmat = pc->mat; 1300 ierr = PetscObjectReference((PetscObject)pc->pmat);CHKERRQ(ierr); 1301 } 1302 } 1303 } 1304 *Amat = pc->mat; 1305 } 1306 if (Pmat) { 1307 if (!pc->pmat) { 1308 if (pc->mat && !Amat) { /* Amat has been set but was not requested, so use for pmat */ 1309 pc->pmat = pc->mat; 1310 ierr = PetscObjectReference((PetscObject)pc->pmat);CHKERRQ(ierr); 1311 } else { 1312 ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pc->pmat);CHKERRQ(ierr); 1313 if (!Amat) { /* user did NOT request Amat, so make same as Pmat */ 1314 pc->mat = pc->pmat; 1315 ierr = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr); 1316 } 1317 } 1318 } 1319 *Pmat = pc->pmat; 1320 } 1321 PetscFunctionReturn(0); 1322 } 1323 1324 #undef __FUNCT__ 1325 #define __FUNCT__ "PCGetOperatorsSet" 1326 /*@C 1327 PCGetOperatorsSet - Determines if the matrix associated with the linear system and 1328 possibly a different one associated with the preconditioner have been set in the PC. 1329 1330 Not collective, though the results on all processes should be the same 1331 1332 Input Parameter: 1333 . pc - the preconditioner context 1334 1335 Output Parameters: 1336 + mat - the matrix associated with the linear system was set 1337 - pmat - matrix associated with the preconditioner was set, usually the same 1338 1339 Level: intermediate 1340 1341 .keywords: PC, get, operators, matrix, linear system 1342 1343 .seealso: PCSetOperators(), KSPGetOperators(), KSPSetOperators(), PCGetOperators() 1344 @*/ 1345 PetscErrorCode PCGetOperatorsSet(PC pc,PetscBool *mat,PetscBool *pmat) 1346 { 1347 PetscFunctionBegin; 1348 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1349 if (mat) *mat = (pc->mat) ? PETSC_TRUE : PETSC_FALSE; 1350 if (pmat) *pmat = (pc->pmat) ? PETSC_TRUE : PETSC_FALSE; 1351 PetscFunctionReturn(0); 1352 } 1353 1354 #undef __FUNCT__ 1355 #define __FUNCT__ "PCFactorGetMatrix" 1356 /*@ 1357 PCFactorGetMatrix - Gets the factored matrix from the 1358 preconditioner context. This routine is valid only for the LU, 1359 incomplete LU, Cholesky, and incomplete Cholesky methods. 1360 1361 Not Collective on PC though Mat is parallel if PC is parallel 1362 1363 Input Parameters: 1364 . pc - the preconditioner context 1365 1366 Output parameters: 1367 . mat - the factored matrix 1368 1369 Level: advanced 1370 1371 Notes: Does not increase the reference count for the matrix so DO NOT destroy it 1372 1373 .keywords: PC, get, factored, matrix 1374 @*/ 1375 PetscErrorCode PCFactorGetMatrix(PC pc,Mat *mat) 1376 { 1377 PetscErrorCode ierr; 1378 1379 PetscFunctionBegin; 1380 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1381 PetscValidPointer(mat,2); 1382 if (pc->ops->getfactoredmatrix) { 1383 ierr = (*pc->ops->getfactoredmatrix)(pc,mat);CHKERRQ(ierr); 1384 } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC type does not support getting factor matrix"); 1385 PetscFunctionReturn(0); 1386 } 1387 1388 #undef __FUNCT__ 1389 #define __FUNCT__ "PCSetOptionsPrefix" 1390 /*@C 1391 PCSetOptionsPrefix - Sets the prefix used for searching for all 1392 PC options in the database. 1393 1394 Logically Collective on PC 1395 1396 Input Parameters: 1397 + pc - the preconditioner context 1398 - prefix - the prefix string to prepend to all PC option requests 1399 1400 Notes: 1401 A hyphen (-) must NOT be given at the beginning of the prefix name. 1402 The first character of all runtime options is AUTOMATICALLY the 1403 hyphen. 1404 1405 Level: advanced 1406 1407 .keywords: PC, set, options, prefix, database 1408 1409 .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix() 1410 @*/ 1411 PetscErrorCode PCSetOptionsPrefix(PC pc,const char prefix[]) 1412 { 1413 PetscErrorCode ierr; 1414 1415 PetscFunctionBegin; 1416 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1417 ierr = PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr); 1418 PetscFunctionReturn(0); 1419 } 1420 1421 #undef __FUNCT__ 1422 #define __FUNCT__ "PCAppendOptionsPrefix" 1423 /*@C 1424 PCAppendOptionsPrefix - Appends to the prefix used for searching for all 1425 PC options in the database. 1426 1427 Logically Collective on PC 1428 1429 Input Parameters: 1430 + pc - the preconditioner context 1431 - prefix - the prefix string to prepend to all PC option requests 1432 1433 Notes: 1434 A hyphen (-) must NOT be given at the beginning of the prefix name. 1435 The first character of all runtime options is AUTOMATICALLY the 1436 hyphen. 1437 1438 Level: advanced 1439 1440 .keywords: PC, append, options, prefix, database 1441 1442 .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix() 1443 @*/ 1444 PetscErrorCode PCAppendOptionsPrefix(PC pc,const char prefix[]) 1445 { 1446 PetscErrorCode ierr; 1447 1448 PetscFunctionBegin; 1449 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1450 ierr = PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr); 1451 PetscFunctionReturn(0); 1452 } 1453 1454 #undef __FUNCT__ 1455 #define __FUNCT__ "PCGetOptionsPrefix" 1456 /*@C 1457 PCGetOptionsPrefix - Gets the prefix used for searching for all 1458 PC options in the database. 1459 1460 Not Collective 1461 1462 Input Parameters: 1463 . pc - the preconditioner context 1464 1465 Output Parameters: 1466 . prefix - pointer to the prefix string used, is returned 1467 1468 Notes: On the fortran side, the user should pass in a string 'prifix' of 1469 sufficient length to hold the prefix. 1470 1471 Level: advanced 1472 1473 .keywords: PC, get, options, prefix, database 1474 1475 .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix() 1476 @*/ 1477 PetscErrorCode PCGetOptionsPrefix(PC pc,const char *prefix[]) 1478 { 1479 PetscErrorCode ierr; 1480 1481 PetscFunctionBegin; 1482 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1483 PetscValidPointer(prefix,2); 1484 ierr = PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);CHKERRQ(ierr); 1485 PetscFunctionReturn(0); 1486 } 1487 1488 #undef __FUNCT__ 1489 #define __FUNCT__ "PCPreSolveChangeRHS" 1490 PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC pc,PetscBool *change) 1491 { 1492 PetscErrorCode ierr; 1493 1494 PetscFunctionBegin; 1495 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1496 PetscValidPointer(change,2); 1497 *change = PETSC_FALSE; 1498 ierr = PetscTryMethod(pc,"PCPreSolveChangeRHS_C",(PC,PetscBool*),(pc,change));CHKERRQ(ierr); 1499 PetscFunctionReturn(0); 1500 } 1501 1502 #undef __FUNCT__ 1503 #define __FUNCT__ "PCPreSolve" 1504 /*@ 1505 PCPreSolve - Optional pre-solve phase, intended for any 1506 preconditioner-specific actions that must be performed before 1507 the iterative solve itself. 1508 1509 Collective on PC 1510 1511 Input Parameters: 1512 + pc - the preconditioner context 1513 - ksp - the Krylov subspace context 1514 1515 Level: developer 1516 1517 Sample of Usage: 1518 .vb 1519 PCPreSolve(pc,ksp); 1520 KSPSolve(ksp,b,x); 1521 PCPostSolve(pc,ksp); 1522 .ve 1523 1524 Notes: 1525 The pre-solve phase is distinct from the PCSetUp() phase. 1526 1527 KSPSolve() calls this directly, so is rarely called by the user. 1528 1529 .keywords: PC, pre-solve 1530 1531 .seealso: PCPostSolve() 1532 @*/ 1533 PetscErrorCode PCPreSolve(PC pc,KSP ksp) 1534 { 1535 PetscErrorCode ierr; 1536 Vec x,rhs; 1537 1538 PetscFunctionBegin; 1539 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1540 PetscValidHeaderSpecific(ksp,KSP_CLASSID,2); 1541 pc->presolvedone++; 1542 if (pc->presolvedone > 2) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot embed PCPreSolve() more than twice"); 1543 ierr = KSPGetSolution(ksp,&x);CHKERRQ(ierr); 1544 ierr = KSPGetRhs(ksp,&rhs);CHKERRQ(ierr); 1545 1546 if (pc->ops->presolve) { 1547 ierr = (*pc->ops->presolve)(pc,ksp,rhs,x);CHKERRQ(ierr); 1548 } 1549 PetscFunctionReturn(0); 1550 } 1551 1552 #undef __FUNCT__ 1553 #define __FUNCT__ "PCPostSolve" 1554 /*@ 1555 PCPostSolve - Optional post-solve phase, intended for any 1556 preconditioner-specific actions that must be performed after 1557 the iterative solve itself. 1558 1559 Collective on PC 1560 1561 Input Parameters: 1562 + pc - the preconditioner context 1563 - ksp - the Krylov subspace context 1564 1565 Sample of Usage: 1566 .vb 1567 PCPreSolve(pc,ksp); 1568 KSPSolve(ksp,b,x); 1569 PCPostSolve(pc,ksp); 1570 .ve 1571 1572 Note: 1573 KSPSolve() calls this routine directly, so it is rarely called by the user. 1574 1575 Level: developer 1576 1577 .keywords: PC, post-solve 1578 1579 .seealso: PCPreSolve(), KSPSolve() 1580 @*/ 1581 PetscErrorCode PCPostSolve(PC pc,KSP ksp) 1582 { 1583 PetscErrorCode ierr; 1584 Vec x,rhs; 1585 1586 PetscFunctionBegin; 1587 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1588 PetscValidHeaderSpecific(ksp,KSP_CLASSID,2); 1589 pc->presolvedone--; 1590 ierr = KSPGetSolution(ksp,&x);CHKERRQ(ierr); 1591 ierr = KSPGetRhs(ksp,&rhs);CHKERRQ(ierr); 1592 if (pc->ops->postsolve) { 1593 ierr = (*pc->ops->postsolve)(pc,ksp,rhs,x);CHKERRQ(ierr); 1594 } 1595 PetscFunctionReturn(0); 1596 } 1597 1598 #undef __FUNCT__ 1599 #define __FUNCT__ "PCLoad" 1600 /*@C 1601 PCLoad - Loads a PC that has been stored in binary with PCView(). 1602 1603 Collective on PetscViewer 1604 1605 Input Parameters: 1606 + newdm - the newly loaded PC, this needs to have been created with PCCreate() or 1607 some related function before a call to PCLoad(). 1608 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() 1609 1610 Level: intermediate 1611 1612 Notes: 1613 The type is determined by the data in the file, any type set into the PC before this call is ignored. 1614 1615 Notes for advanced users: 1616 Most users should not need to know the details of the binary storage 1617 format, since PCLoad() and PCView() completely hide these details. 1618 But for anyone who's interested, the standard binary matrix storage 1619 format is 1620 .vb 1621 has not yet been determined 1622 .ve 1623 1624 .seealso: PetscViewerBinaryOpen(), PCView(), MatLoad(), VecLoad() 1625 @*/ 1626 PetscErrorCode PCLoad(PC newdm, PetscViewer viewer) 1627 { 1628 PetscErrorCode ierr; 1629 PetscBool isbinary; 1630 PetscInt classid; 1631 char type[256]; 1632 1633 PetscFunctionBegin; 1634 PetscValidHeaderSpecific(newdm,PC_CLASSID,1); 1635 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 1636 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 1637 if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 1638 1639 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 1640 if (classid != PC_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not PC next in file"); 1641 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 1642 ierr = PCSetType(newdm, type);CHKERRQ(ierr); 1643 if (newdm->ops->load) { 1644 ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr); 1645 } 1646 PetscFunctionReturn(0); 1647 } 1648 1649 #include <petscdraw.h> 1650 #if defined(PETSC_HAVE_SAWS) 1651 #include <petscviewersaws.h> 1652 #endif 1653 #undef __FUNCT__ 1654 #define __FUNCT__ "PCView" 1655 /*@C 1656 PCView - Prints the PC data structure. 1657 1658 Collective on PC 1659 1660 Input Parameters: 1661 + PC - the PC context 1662 - viewer - optional visualization context 1663 1664 Note: 1665 The available visualization contexts include 1666 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 1667 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 1668 output where only the first processor opens 1669 the file. All other processors send their 1670 data to the first processor to print. 1671 1672 The user can open an alternative visualization contexts with 1673 PetscViewerASCIIOpen() (output to a specified file). 1674 1675 Level: developer 1676 1677 .keywords: PC, view 1678 1679 .seealso: KSPView(), PetscViewerASCIIOpen() 1680 @*/ 1681 PetscErrorCode PCView(PC pc,PetscViewer viewer) 1682 { 1683 PCType cstr; 1684 PetscErrorCode ierr; 1685 PetscBool iascii,isstring,isbinary,isdraw; 1686 PetscViewerFormat format; 1687 #if defined(PETSC_HAVE_SAWS) 1688 PetscBool issaws; 1689 #endif 1690 1691 PetscFunctionBegin; 1692 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1693 if (!viewer) { 1694 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&viewer);CHKERRQ(ierr); 1695 } 1696 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 1697 PetscCheckSameComm(pc,1,viewer,2); 1698 1699 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1700 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr); 1701 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 1702 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 1703 #if defined(PETSC_HAVE_SAWS) 1704 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);CHKERRQ(ierr); 1705 #endif 1706 1707 if (iascii) { 1708 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1709 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)pc,viewer);CHKERRQ(ierr); 1710 if (!pc->setupcalled) { 1711 ierr = PetscViewerASCIIPrintf(viewer," PC has not been set up so information may be incomplete\n");CHKERRQ(ierr); 1712 } 1713 if (pc->ops->view) { 1714 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1715 ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr); 1716 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1717 } 1718 if (pc->mat) { 1719 ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr); 1720 if (pc->pmat == pc->mat) { 1721 ierr = PetscViewerASCIIPrintf(viewer," linear system matrix = precond matrix:\n");CHKERRQ(ierr); 1722 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1723 ierr = MatView(pc->mat,viewer);CHKERRQ(ierr); 1724 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1725 } else { 1726 if (pc->pmat) { 1727 ierr = PetscViewerASCIIPrintf(viewer," linear system matrix followed by preconditioner matrix:\n");CHKERRQ(ierr); 1728 } else { 1729 ierr = PetscViewerASCIIPrintf(viewer," linear system matrix:\n");CHKERRQ(ierr); 1730 } 1731 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1732 ierr = MatView(pc->mat,viewer);CHKERRQ(ierr); 1733 if (pc->pmat) {ierr = MatView(pc->pmat,viewer);CHKERRQ(ierr);} 1734 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1735 } 1736 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1737 } 1738 } else if (isstring) { 1739 ierr = PCGetType(pc,&cstr);CHKERRQ(ierr); 1740 ierr = PetscViewerStringSPrintf(viewer," %-7.7s",cstr);CHKERRQ(ierr); 1741 if (pc->ops->view) {ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr);} 1742 } else if (isbinary) { 1743 PetscInt classid = PC_FILE_CLASSID; 1744 MPI_Comm comm; 1745 PetscMPIInt rank; 1746 char type[256]; 1747 1748 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 1749 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1750 if (!rank) { 1751 ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 1752 ierr = PetscStrncpy(type,((PetscObject)pc)->type_name,256);CHKERRQ(ierr); 1753 ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 1754 } 1755 if (pc->ops->view) { 1756 ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr); 1757 } 1758 } else if (isdraw) { 1759 PetscDraw draw; 1760 char str[25]; 1761 PetscReal x,y,bottom,h; 1762 PetscInt n; 1763 1764 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 1765 ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 1766 if (pc->mat) { 1767 ierr = MatGetSize(pc->mat,&n,NULL);CHKERRQ(ierr); 1768 ierr = PetscSNPrintf(str,25,"PC: %s (%D)",((PetscObject)pc)->type_name,n);CHKERRQ(ierr); 1769 } else { 1770 ierr = PetscSNPrintf(str,25,"PC: %s",((PetscObject)pc)->type_name);CHKERRQ(ierr); 1771 } 1772 ierr = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); 1773 bottom = y - h; 1774 ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); 1775 if (pc->ops->view) { 1776 ierr = (*pc->ops->view)(pc,viewer);CHKERRQ(ierr); 1777 } 1778 ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 1779 #if defined(PETSC_HAVE_SAWS) 1780 } else if (issaws) { 1781 PetscMPIInt rank; 1782 1783 ierr = PetscObjectName((PetscObject)pc);CHKERRQ(ierr); 1784 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 1785 if (!((PetscObject)pc)->amsmem && !rank) { 1786 ierr = PetscObjectViewSAWs((PetscObject)pc,viewer);CHKERRQ(ierr); 1787 } 1788 if (pc->mat) {ierr = MatView(pc->mat,viewer);CHKERRQ(ierr);} 1789 if (pc->pmat && pc->pmat != pc->mat) {ierr = MatView(pc->pmat,viewer);CHKERRQ(ierr);} 1790 #endif 1791 } 1792 PetscFunctionReturn(0); 1793 } 1794 1795 #undef __FUNCT__ 1796 #define __FUNCT__ "PCRegister" 1797 /*@C 1798 PCRegister - Adds a method to the preconditioner package. 1799 1800 Not collective 1801 1802 Input Parameters: 1803 + name_solver - name of a new user-defined solver 1804 - routine_create - routine to create method context 1805 1806 Notes: 1807 PCRegister() may be called multiple times to add several user-defined preconditioners. 1808 1809 Sample usage: 1810 .vb 1811 PCRegister("my_solver", MySolverCreate); 1812 .ve 1813 1814 Then, your solver can be chosen with the procedural interface via 1815 $ PCSetType(pc,"my_solver") 1816 or at runtime via the option 1817 $ -pc_type my_solver 1818 1819 Level: advanced 1820 1821 .keywords: PC, register 1822 1823 .seealso: PCRegisterAll(), PCRegisterDestroy() 1824 @*/ 1825 PetscErrorCode PCRegister(const char sname[],PetscErrorCode (*function)(PC)) 1826 { 1827 PetscErrorCode ierr; 1828 1829 PetscFunctionBegin; 1830 ierr = PetscFunctionListAdd(&PCList,sname,function);CHKERRQ(ierr); 1831 PetscFunctionReturn(0); 1832 } 1833 1834 #undef __FUNCT__ 1835 #define __FUNCT__ "PCComputeExplicitOperator" 1836 /*@ 1837 PCComputeExplicitOperator - Computes the explicit preconditioned operator. 1838 1839 Collective on PC 1840 1841 Input Parameter: 1842 . pc - the preconditioner object 1843 1844 Output Parameter: 1845 . mat - the explict preconditioned operator 1846 1847 Notes: 1848 This computation is done by applying the operators to columns of the 1849 identity matrix. 1850 1851 Currently, this routine uses a dense matrix format when 1 processor 1852 is used and a sparse format otherwise. This routine is costly in general, 1853 and is recommended for use only with relatively small systems. 1854 1855 Level: advanced 1856 1857 .keywords: PC, compute, explicit, operator 1858 1859 .seealso: KSPComputeExplicitOperator() 1860 1861 @*/ 1862 PetscErrorCode PCComputeExplicitOperator(PC pc,Mat *mat) 1863 { 1864 Vec in,out; 1865 PetscErrorCode ierr; 1866 PetscInt i,M,m,*rows,start,end; 1867 PetscMPIInt size; 1868 MPI_Comm comm; 1869 PetscScalar *array,one = 1.0; 1870 1871 PetscFunctionBegin; 1872 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1873 PetscValidPointer(mat,2); 1874 1875 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 1876 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1877 1878 if (!pc->pmat) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"You must call KSPSetOperators() or PCSetOperators() before this call"); 1879 ierr = MatCreateVecs(pc->pmat,&in,0);CHKERRQ(ierr); 1880 ierr = VecDuplicate(in,&out);CHKERRQ(ierr); 1881 ierr = VecGetOwnershipRange(in,&start,&end);CHKERRQ(ierr); 1882 ierr = VecGetSize(in,&M);CHKERRQ(ierr); 1883 ierr = VecGetLocalSize(in,&m);CHKERRQ(ierr); 1884 ierr = PetscMalloc1(m+1,&rows);CHKERRQ(ierr); 1885 for (i=0; i<m; i++) rows[i] = start + i; 1886 1887 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 1888 ierr = MatSetSizes(*mat,m,m,M,M);CHKERRQ(ierr); 1889 if (size == 1) { 1890 ierr = MatSetType(*mat,MATSEQDENSE);CHKERRQ(ierr); 1891 ierr = MatSeqDenseSetPreallocation(*mat,NULL);CHKERRQ(ierr); 1892 } else { 1893 ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr); 1894 ierr = MatMPIAIJSetPreallocation(*mat,0,NULL,0,NULL);CHKERRQ(ierr); 1895 } 1896 ierr = MatSetOption(*mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 1897 1898 for (i=0; i<M; i++) { 1899 1900 ierr = VecSet(in,0.0);CHKERRQ(ierr); 1901 ierr = VecSetValues(in,1,&i,&one,INSERT_VALUES);CHKERRQ(ierr); 1902 ierr = VecAssemblyBegin(in);CHKERRQ(ierr); 1903 ierr = VecAssemblyEnd(in);CHKERRQ(ierr); 1904 1905 /* should fix, allowing user to choose side */ 1906 ierr = PCApply(pc,in,out);CHKERRQ(ierr); 1907 1908 ierr = VecGetArray(out,&array);CHKERRQ(ierr); 1909 ierr = MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);CHKERRQ(ierr); 1910 ierr = VecRestoreArray(out,&array);CHKERRQ(ierr); 1911 1912 } 1913 ierr = PetscFree(rows);CHKERRQ(ierr); 1914 ierr = VecDestroy(&out);CHKERRQ(ierr); 1915 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1916 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1917 PetscFunctionReturn(0); 1918 } 1919 1920 #undef __FUNCT__ 1921 #define __FUNCT__ "PCSetCoordinates" 1922 /*@ 1923 PCSetCoordinates - sets the coordinates of all the nodes on the local process 1924 1925 Collective on PC 1926 1927 Input Parameters: 1928 + pc - the solver context 1929 . dim - the dimension of the coordinates 1, 2, or 3 1930 - coords - the coordinates 1931 1932 Level: intermediate 1933 1934 Notes: coords is an array of the 3D coordinates for the nodes on 1935 the local processor. So if there are 108 equation on a processor 1936 for a displacement finite element discretization of elasticity (so 1937 that there are 36 = 108/3 nodes) then the array must have 108 1938 double precision values (ie, 3 * 36). These x y z coordinates 1939 should be ordered for nodes 0 to N-1 like so: [ 0.x, 0.y, 0.z, 1.x, 1940 ... , N-1.z ]. 1941 1942 .seealso: MatSetNearNullSpace 1943 @*/ 1944 PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) 1945 { 1946 PetscErrorCode ierr; 1947 1948 PetscFunctionBegin; 1949 ierr = PetscTryMethod(pc,"PCSetCoordinates_C",(PC,PetscInt,PetscInt,PetscReal*),(pc,dim,nloc,coords));CHKERRQ(ierr); 1950 PetscFunctionReturn(0); 1951 } 1952