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