1 2 /* 3 This provides a simple shell for Fortran (and C programmers) to 4 create their own preconditioner without writing much interface code. 5 */ 6 7 #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 8 #include <petsc/private/vecimpl.h> 9 10 typedef struct { 11 void *ctx; /* user provided contexts for preconditioner */ 12 13 PetscErrorCode (*destroy)(PC); 14 PetscErrorCode (*setup)(PC); 15 PetscErrorCode (*apply)(PC,Vec,Vec); 16 PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec); 17 PetscErrorCode (*presolve)(PC,KSP,Vec,Vec); 18 PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec); 19 PetscErrorCode (*view)(PC,PetscViewer); 20 PetscErrorCode (*applytranspose)(PC,Vec,Vec); 21 PetscErrorCode (*applyrich)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*); 22 23 char *name; 24 } PC_Shell; 25 26 #undef __FUNCT__ 27 #define __FUNCT__ "PCShellGetContext" 28 /*@C 29 PCShellGetContext - Returns the user-provided context associated with a shell PC 30 31 Not Collective 32 33 Input Parameter: 34 . pc - should have been created with PCSetType(pc,shell) 35 36 Output Parameter: 37 . ctx - the user provided context 38 39 Level: advanced 40 41 Notes: 42 This routine is intended for use within various shell routines 43 44 Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this 45 function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument. 46 47 .keywords: PC, shell, get, context 48 49 .seealso: PCShellSetContext() 50 @*/ 51 PetscErrorCode PCShellGetContext(PC pc,void **ctx) 52 { 53 PetscErrorCode ierr; 54 PetscBool flg; 55 56 PetscFunctionBegin; 57 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 58 PetscValidPointer(ctx,2); 59 ierr = PetscObjectTypeCompare((PetscObject)pc,PCSHELL,&flg);CHKERRQ(ierr); 60 if (!flg) *ctx = 0; 61 else *ctx = ((PC_Shell*)(pc->data))->ctx; 62 PetscFunctionReturn(0); 63 } 64 65 #undef __FUNCT__ 66 #define __FUNCT__ "PCShellSetContext" 67 /*@ 68 PCShellSetContext - sets the context for a shell PC 69 70 Logically Collective on PC 71 72 Input Parameters: 73 + pc - the shell PC 74 - ctx - the context 75 76 Level: advanced 77 78 Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this 79 function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument. 80 81 82 83 .seealso: PCShellGetContext(), PCSHELL 84 @*/ 85 PetscErrorCode PCShellSetContext(PC pc,void *ctx) 86 { 87 PC_Shell *shell = (PC_Shell*)pc->data; 88 PetscErrorCode ierr; 89 PetscBool flg; 90 91 PetscFunctionBegin; 92 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 93 ierr = PetscObjectTypeCompare((PetscObject)pc,PCSHELL,&flg);CHKERRQ(ierr); 94 if (flg) shell->ctx = ctx; 95 PetscFunctionReturn(0); 96 } 97 98 #undef __FUNCT__ 99 #define __FUNCT__ "PCSetUp_Shell" 100 static PetscErrorCode PCSetUp_Shell(PC pc) 101 { 102 PC_Shell *shell = (PC_Shell*)pc->data; 103 PetscErrorCode ierr; 104 105 PetscFunctionBegin; 106 if (!shell->setup) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No setup() routine provided to Shell PC"); 107 PetscStackCall("PCSHELL user function setup()",ierr = (*shell->setup)(pc);CHKERRQ(ierr)); 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "PCApply_Shell" 113 static PetscErrorCode PCApply_Shell(PC pc,Vec x,Vec y) 114 { 115 PC_Shell *shell = (PC_Shell*)pc->data; 116 PetscErrorCode ierr; 117 PetscObjectState instate,outstate; 118 119 PetscFunctionBegin; 120 if (!shell->apply) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No apply() routine provided to Shell PC"); 121 ierr = PetscObjectStateGet((PetscObject)y, &instate);CHKERRQ(ierr); 122 PetscStackCall("PCSHELL user function apply()",ierr = (*shell->apply)(pc,x,y);CHKERRQ(ierr)); 123 ierr = PetscObjectStateGet((PetscObject)y, &outstate);CHKERRQ(ierr); 124 if (instate == outstate) { 125 /* increase the state of the output vector since the user did not update its state themselve as should have been done */ 126 ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr); 127 } 128 ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr); 129 PetscFunctionReturn(0); 130 } 131 132 #undef __FUNCT__ 133 #define __FUNCT__ "PCApplyBA_Shell" 134 static PetscErrorCode PCApplyBA_Shell(PC pc,PCSide side,Vec x,Vec y,Vec w) 135 { 136 PC_Shell *shell = (PC_Shell*)pc->data; 137 PetscErrorCode ierr; 138 PetscObjectState instate,outstate; 139 140 PetscFunctionBegin; 141 if (!shell->applyBA) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No applyBA() routine provided to Shell PC"); 142 ierr = PetscObjectStateGet((PetscObject)w, &instate);CHKERRQ(ierr); 143 PetscStackCall("PCSHELL user function applyBA()",ierr = (*shell->applyBA)(pc,side,x,y,w);CHKERRQ(ierr)); 144 ierr = PetscObjectStateGet((PetscObject)w, &outstate);CHKERRQ(ierr); 145 if (instate == outstate) { 146 /* increase the state of the output vector since the user did not update its state themselve as should have been done */ 147 ierr = PetscObjectStateIncrease((PetscObject)w);CHKERRQ(ierr); 148 } 149 PetscFunctionReturn(0); 150 } 151 152 #undef __FUNCT__ 153 #define __FUNCT__ "PCPreSolve_Shell" 154 static PetscErrorCode PCPreSolve_Shell(PC pc,KSP ksp,Vec b,Vec x) 155 { 156 PC_Shell *shell = (PC_Shell*)pc->data; 157 PetscErrorCode ierr; 158 159 PetscFunctionBegin; 160 if (!shell->presolve) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No presolve() routine provided to Shell PC"); 161 PetscStackCall("PCSHELL user function presolve()",ierr = (*shell->presolve)(pc,ksp,b,x);CHKERRQ(ierr)); 162 PetscFunctionReturn(0); 163 } 164 165 #undef __FUNCT__ 166 #define __FUNCT__ "PCPostSolve_Shell" 167 static PetscErrorCode PCPostSolve_Shell(PC pc,KSP ksp,Vec b,Vec x) 168 { 169 PC_Shell *shell = (PC_Shell*)pc->data; 170 PetscErrorCode ierr; 171 172 PetscFunctionBegin; 173 if (!shell->postsolve) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No postsolve() routine provided to Shell PC"); 174 PetscStackCall("PCSHELL user function postsolve()",ierr = (*shell->postsolve)(pc,ksp,b,x);CHKERRQ(ierr)); 175 PetscFunctionReturn(0); 176 } 177 178 #undef __FUNCT__ 179 #define __FUNCT__ "PCApplyTranspose_Shell" 180 static PetscErrorCode PCApplyTranspose_Shell(PC pc,Vec x,Vec y) 181 { 182 PC_Shell *shell = (PC_Shell*)pc->data; 183 PetscErrorCode ierr; 184 PetscObjectState instate,outstate; 185 186 PetscFunctionBegin; 187 if (!shell->applytranspose) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No applytranspose() routine provided to Shell PC"); 188 ierr = PetscObjectStateGet((PetscObject)y, &instate);CHKERRQ(ierr); 189 PetscStackCall("PCSHELL user function applytranspose()",ierr = (*shell->applytranspose)(pc,x,y);CHKERRQ(ierr)); 190 ierr = PetscObjectStateGet((PetscObject)y, &outstate);CHKERRQ(ierr); 191 if (instate == outstate) { 192 /* increase the state of the output vector since the user did not update its state themself as should have been done */ 193 ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr); 194 } 195 PetscFunctionReturn(0); 196 } 197 198 #undef __FUNCT__ 199 #define __FUNCT__ "PCApplyRichardson_Shell" 200 static PetscErrorCode PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt it,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason) 201 { 202 PetscErrorCode ierr; 203 PC_Shell *shell = (PC_Shell*)pc->data; 204 PetscObjectState instate,outstate; 205 206 PetscFunctionBegin; 207 if (!shell->applyrich) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No applyrichardson() routine provided to Shell PC"); 208 ierr = PetscObjectStateGet((PetscObject)y, &instate);CHKERRQ(ierr); 209 PetscStackCall("PCSHELL user function applyrichardson()",ierr = (*shell->applyrich)(pc,x,y,w,rtol,abstol,dtol,it,guesszero,outits,reason);CHKERRQ(ierr)); 210 ierr = PetscObjectStateGet((PetscObject)y, &outstate);CHKERRQ(ierr); 211 if (instate == outstate) { 212 /* increase the state of the output vector since the user did not update its state themself as should have been done */ 213 ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr); 214 } 215 PetscFunctionReturn(0); 216 } 217 218 #undef __FUNCT__ 219 #define __FUNCT__ "PCDestroy_Shell" 220 static PetscErrorCode PCDestroy_Shell(PC pc) 221 { 222 PC_Shell *shell = (PC_Shell*)pc->data; 223 PetscErrorCode ierr; 224 225 PetscFunctionBegin; 226 ierr = PetscFree(shell->name);CHKERRQ(ierr); 227 if (shell->destroy) PetscStackCall("PCSHELL user function destroy()",ierr = (*shell->destroy)(pc);CHKERRQ(ierr)); 228 ierr = PetscFree(pc->data);CHKERRQ(ierr); 229 PetscFunctionReturn(0); 230 } 231 232 #undef __FUNCT__ 233 #define __FUNCT__ "PCView_Shell" 234 static PetscErrorCode PCView_Shell(PC pc,PetscViewer viewer) 235 { 236 PC_Shell *shell = (PC_Shell*)pc->data; 237 PetscErrorCode ierr; 238 PetscBool iascii; 239 240 PetscFunctionBegin; 241 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 242 if (iascii) { 243 if (shell->name) { 244 ierr = PetscViewerASCIIPrintf(viewer," Shell: %s\n",shell->name);CHKERRQ(ierr); 245 } else { 246 ierr = PetscViewerASCIIPrintf(viewer," Shell: no name\n");CHKERRQ(ierr); 247 } 248 } 249 if (shell->view) { 250 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 251 ierr = (*shell->view)(pc,viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 253 } 254 PetscFunctionReturn(0); 255 } 256 257 /* ------------------------------------------------------------------------------*/ 258 #undef __FUNCT__ 259 #define __FUNCT__ "PCShellSetDestroy_Shell" 260 static PetscErrorCode PCShellSetDestroy_Shell(PC pc, PetscErrorCode (*destroy)(PC)) 261 { 262 PC_Shell *shell= (PC_Shell*)pc->data; 263 264 PetscFunctionBegin; 265 shell->destroy = destroy; 266 PetscFunctionReturn(0); 267 } 268 269 #undef __FUNCT__ 270 #define __FUNCT__ "PCShellSetSetUp_Shell" 271 static PetscErrorCode PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*setup)(PC)) 272 { 273 PC_Shell *shell = (PC_Shell*)pc->data;; 274 275 PetscFunctionBegin; 276 shell->setup = setup; 277 if (setup) pc->ops->setup = PCSetUp_Shell; 278 else pc->ops->setup = 0; 279 PetscFunctionReturn(0); 280 } 281 282 #undef __FUNCT__ 283 #define __FUNCT__ "PCShellSetApply_Shell" 284 static PetscErrorCode PCShellSetApply_Shell(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec)) 285 { 286 PC_Shell *shell = (PC_Shell*)pc->data; 287 288 PetscFunctionBegin; 289 shell->apply = apply; 290 PetscFunctionReturn(0); 291 } 292 293 #undef __FUNCT__ 294 #define __FUNCT__ "PCShellSetApplyBA_Shell" 295 static PetscErrorCode PCShellSetApplyBA_Shell(PC pc,PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec)) 296 { 297 PC_Shell *shell = (PC_Shell*)pc->data; 298 299 PetscFunctionBegin; 300 shell->applyBA = applyBA; 301 if (applyBA) pc->ops->applyBA = PCApplyBA_Shell; 302 else pc->ops->applyBA = 0; 303 PetscFunctionReturn(0); 304 } 305 306 #undef __FUNCT__ 307 #define __FUNCT__ "PCShellSetPreSolve_Shell" 308 static PetscErrorCode PCShellSetPreSolve_Shell(PC pc,PetscErrorCode (*presolve)(PC,KSP,Vec,Vec)) 309 { 310 PC_Shell *shell = (PC_Shell*)pc->data; 311 312 PetscFunctionBegin; 313 shell->presolve = presolve; 314 if (presolve) pc->ops->presolve = PCPreSolve_Shell; 315 else pc->ops->presolve = 0; 316 PetscFunctionReturn(0); 317 } 318 319 #undef __FUNCT__ 320 #define __FUNCT__ "PCShellSetPostSolve_Shell" 321 static PetscErrorCode PCShellSetPostSolve_Shell(PC pc,PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec)) 322 { 323 PC_Shell *shell = (PC_Shell*)pc->data; 324 325 PetscFunctionBegin; 326 shell->postsolve = postsolve; 327 if (postsolve) pc->ops->postsolve = PCPostSolve_Shell; 328 else pc->ops->postsolve = 0; 329 PetscFunctionReturn(0); 330 } 331 332 #undef __FUNCT__ 333 #define __FUNCT__ "PCShellSetView_Shell" 334 static PetscErrorCode PCShellSetView_Shell(PC pc,PetscErrorCode (*view)(PC,PetscViewer)) 335 { 336 PC_Shell *shell = (PC_Shell*)pc->data; 337 338 PetscFunctionBegin; 339 shell->view = view; 340 PetscFunctionReturn(0); 341 } 342 343 #undef __FUNCT__ 344 #define __FUNCT__ "PCShellSetApplyTranspose_Shell" 345 static PetscErrorCode PCShellSetApplyTranspose_Shell(PC pc,PetscErrorCode (*applytranspose)(PC,Vec,Vec)) 346 { 347 PC_Shell *shell = (PC_Shell*)pc->data; 348 349 PetscFunctionBegin; 350 shell->applytranspose = applytranspose; 351 if (applytranspose) pc->ops->applytranspose = PCApplyTranspose_Shell; 352 else pc->ops->applytranspose = 0; 353 PetscFunctionReturn(0); 354 } 355 356 #undef __FUNCT__ 357 #define __FUNCT__ "PCShellSetApplyRichardson_Shell" 358 static PetscErrorCode PCShellSetApplyRichardson_Shell(PC pc,PetscErrorCode (*applyrich)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool ,PetscInt*,PCRichardsonConvergedReason*)) 359 { 360 PC_Shell *shell = (PC_Shell*)pc->data; 361 362 PetscFunctionBegin; 363 shell->applyrich = applyrich; 364 if (applyrich) pc->ops->applyrichardson = PCApplyRichardson_Shell; 365 else pc->ops->applyrichardson = 0; 366 PetscFunctionReturn(0); 367 } 368 369 #undef __FUNCT__ 370 #define __FUNCT__ "PCShellSetName_Shell" 371 static PetscErrorCode PCShellSetName_Shell(PC pc,const char name[]) 372 { 373 PC_Shell *shell = (PC_Shell*)pc->data; 374 PetscErrorCode ierr; 375 376 PetscFunctionBegin; 377 ierr = PetscFree(shell->name);CHKERRQ(ierr); 378 ierr = PetscStrallocpy(name,&shell->name);CHKERRQ(ierr); 379 PetscFunctionReturn(0); 380 } 381 382 #undef __FUNCT__ 383 #define __FUNCT__ "PCShellGetName_Shell" 384 static PetscErrorCode PCShellGetName_Shell(PC pc,const char *name[]) 385 { 386 PC_Shell *shell = (PC_Shell*)pc->data; 387 388 PetscFunctionBegin; 389 *name = shell->name; 390 PetscFunctionReturn(0); 391 } 392 393 /* -------------------------------------------------------------------------------*/ 394 395 #undef __FUNCT__ 396 #define __FUNCT__ "PCShellSetDestroy" 397 /*@C 398 PCShellSetDestroy - Sets routine to use to destroy the user-provided 399 application context. 400 401 Logically Collective on PC 402 403 Input Parameters: 404 + pc - the preconditioner context 405 . destroy - the application-provided destroy routine 406 407 Calling sequence of destroy: 408 .vb 409 PetscErrorCode destroy (PC) 410 .ve 411 412 . ptr - the application context 413 414 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 415 416 Level: developer 417 418 .keywords: PC, shell, set, destroy, user-provided 419 420 .seealso: PCShellSetApply(), PCShellSetContext() 421 @*/ 422 PetscErrorCode PCShellSetDestroy(PC pc,PetscErrorCode (*destroy)(PC)) 423 { 424 PetscErrorCode ierr; 425 426 PetscFunctionBegin; 427 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 428 ierr = PetscTryMethod(pc,"PCShellSetDestroy_C",(PC,PetscErrorCode (*)(PC)),(pc,destroy));CHKERRQ(ierr); 429 PetscFunctionReturn(0); 430 } 431 432 433 #undef __FUNCT__ 434 #define __FUNCT__ "PCShellSetSetUp" 435 /*@C 436 PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the 437 matrix operator is changed. 438 439 Logically Collective on PC 440 441 Input Parameters: 442 + pc - the preconditioner context 443 . setup - the application-provided setup routine 444 445 Calling sequence of setup: 446 .vb 447 PetscErrorCode setup (PC pc) 448 .ve 449 450 . pc - the preconditioner, get the application context with PCShellGetContext() 451 452 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 453 454 Level: developer 455 456 .keywords: PC, shell, set, setup, user-provided 457 458 .seealso: PCShellSetApplyRichardson(), PCShellSetApply(), PCShellSetContext() 459 @*/ 460 PetscErrorCode PCShellSetSetUp(PC pc,PetscErrorCode (*setup)(PC)) 461 { 462 PetscErrorCode ierr; 463 464 PetscFunctionBegin; 465 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 466 ierr = PetscTryMethod(pc,"PCShellSetSetUp_C",(PC,PetscErrorCode (*)(PC)),(pc,setup));CHKERRQ(ierr); 467 PetscFunctionReturn(0); 468 } 469 470 471 #undef __FUNCT__ 472 #define __FUNCT__ "PCShellSetView" 473 /*@C 474 PCShellSetView - Sets routine to use as viewer of shell preconditioner 475 476 Logically Collective on PC 477 478 Input Parameters: 479 + pc - the preconditioner context 480 - view - the application-provided view routine 481 482 Calling sequence of apply: 483 .vb 484 PetscErrorCode view(PC pc,PetscViewer v) 485 .ve 486 487 + pc - the preconditioner, get the application context with PCShellGetContext() 488 - v - viewer 489 490 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 491 492 Level: developer 493 494 .keywords: PC, shell, set, apply, user-provided 495 496 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose() 497 @*/ 498 PetscErrorCode PCShellSetView(PC pc,PetscErrorCode (*view)(PC,PetscViewer)) 499 { 500 PetscErrorCode ierr; 501 502 PetscFunctionBegin; 503 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 504 ierr = PetscTryMethod(pc,"PCShellSetView_C",(PC,PetscErrorCode (*)(PC,PetscViewer)),(pc,view));CHKERRQ(ierr); 505 PetscFunctionReturn(0); 506 } 507 508 #undef __FUNCT__ 509 #define __FUNCT__ "PCShellSetApply" 510 /*@C 511 PCShellSetApply - Sets routine to use as preconditioner. 512 513 Logically Collective on PC 514 515 Input Parameters: 516 + pc - the preconditioner context 517 - apply - the application-provided preconditioning routine 518 519 Calling sequence of apply: 520 .vb 521 PetscErrorCode apply (PC pc,Vec xin,Vec xout) 522 .ve 523 524 + pc - the preconditioner, get the application context with PCShellGetContext() 525 . xin - input vector 526 - xout - output vector 527 528 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 529 530 Developer Notes: There should also be a PCShellSetApplySymmetricRight() and PCShellSetApplySymmetricLeft(). 531 532 Level: developer 533 534 .keywords: PC, shell, set, apply, user-provided 535 536 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApplyBA() 537 @*/ 538 PetscErrorCode PCShellSetApply(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec)) 539 { 540 PetscErrorCode ierr; 541 542 PetscFunctionBegin; 543 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 544 ierr = PetscTryMethod(pc,"PCShellSetApply_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));CHKERRQ(ierr); 545 PetscFunctionReturn(0); 546 } 547 548 #undef __FUNCT__ 549 #define __FUNCT__ "PCShellSetApplyBA" 550 /*@C 551 PCShellSetApplyBA - Sets routine to use as preconditioner times operator. 552 553 Logically Collective on PC 554 555 Input Parameters: 556 + pc - the preconditioner context 557 - applyBA - the application-provided BA routine 558 559 Calling sequence of apply: 560 .vb 561 PetscErrorCode applyBA (PC pc,Vec xin,Vec xout) 562 .ve 563 564 + pc - the preconditioner, get the application context with PCShellGetContext() 565 . xin - input vector 566 - xout - output vector 567 568 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 569 570 Level: developer 571 572 .keywords: PC, shell, set, apply, user-provided 573 574 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApply() 575 @*/ 576 PetscErrorCode PCShellSetApplyBA(PC pc,PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec)) 577 { 578 PetscErrorCode ierr; 579 580 PetscFunctionBegin; 581 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 582 ierr = PetscTryMethod(pc,"PCShellSetApplyBA_C",(PC,PetscErrorCode (*)(PC,PCSide,Vec,Vec,Vec)),(pc,applyBA));CHKERRQ(ierr); 583 PetscFunctionReturn(0); 584 } 585 586 #undef __FUNCT__ 587 #define __FUNCT__ "PCShellSetApplyTranspose" 588 /*@C 589 PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose. 590 591 Logically Collective on PC 592 593 Input Parameters: 594 + pc - the preconditioner context 595 - apply - the application-provided preconditioning transpose routine 596 597 Calling sequence of apply: 598 .vb 599 PetscErrorCode applytranspose (PC pc,Vec xin,Vec xout) 600 .ve 601 602 + pc - the preconditioner, get the application context with PCShellGetContext() 603 . xin - input vector 604 - xout - output vector 605 606 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 607 608 Level: developer 609 610 Notes: 611 Uses the same context variable as PCShellSetApply(). 612 613 .keywords: PC, shell, set, apply, user-provided 614 615 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply(), PCSetContext(), PCShellSetApplyBA() 616 @*/ 617 PetscErrorCode PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(PC,Vec,Vec)) 618 { 619 PetscErrorCode ierr; 620 621 PetscFunctionBegin; 622 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 623 ierr = PetscTryMethod(pc,"PCShellSetApplyTranspose_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,applytranspose));CHKERRQ(ierr); 624 PetscFunctionReturn(0); 625 } 626 627 #undef __FUNCT__ 628 #define __FUNCT__ "PCShellSetPreSolve" 629 /*@C 630 PCShellSetPreSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is 631 applied. This usually does something like scale the linear system in some application 632 specific way. 633 634 Logically Collective on PC 635 636 Input Parameters: 637 + pc - the preconditioner context 638 - presolve - the application-provided presolve routine 639 640 Calling sequence of presolve: 641 .vb 642 PetscErrorCode presolve (PC,KSP ksp,Vec b,Vec x) 643 .ve 644 645 + pc - the preconditioner, get the application context with PCShellGetContext() 646 . xin - input vector 647 - xout - output vector 648 649 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 650 651 Level: developer 652 653 .keywords: PC, shell, set, apply, user-provided 654 655 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPostSolve(), PCShellSetContext() 656 @*/ 657 PetscErrorCode PCShellSetPreSolve(PC pc,PetscErrorCode (*presolve)(PC,KSP,Vec,Vec)) 658 { 659 PetscErrorCode ierr; 660 661 PetscFunctionBegin; 662 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 663 ierr = PetscTryMethod(pc,"PCShellSetPreSolve_C",(PC,PetscErrorCode (*)(PC,KSP,Vec,Vec)),(pc,presolve));CHKERRQ(ierr); 664 PetscFunctionReturn(0); 665 } 666 667 #undef __FUNCT__ 668 #define __FUNCT__ "PCShellSetPostSolve" 669 /*@C 670 PCShellSetPostSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is 671 applied. This usually does something like scale the linear system in some application 672 specific way. 673 674 Logically Collective on PC 675 676 Input Parameters: 677 + pc - the preconditioner context 678 - postsolve - the application-provided presolve routine 679 680 Calling sequence of postsolve: 681 .vb 682 PetscErrorCode postsolve(PC,KSP ksp,Vec b,Vec x) 683 .ve 684 685 + pc - the preconditioner, get the application context with PCShellGetContext() 686 . xin - input vector 687 - xout - output vector 688 689 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 690 691 Level: developer 692 693 .keywords: PC, shell, set, apply, user-provided 694 695 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPreSolve(), PCShellSetContext() 696 @*/ 697 PetscErrorCode PCShellSetPostSolve(PC pc,PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec)) 698 { 699 PetscErrorCode ierr; 700 701 PetscFunctionBegin; 702 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 703 ierr = PetscTryMethod(pc,"PCShellSetPostSolve_C",(PC,PetscErrorCode (*)(PC,KSP,Vec,Vec)),(pc,postsolve));CHKERRQ(ierr); 704 PetscFunctionReturn(0); 705 } 706 707 #undef __FUNCT__ 708 #define __FUNCT__ "PCShellSetName" 709 /*@C 710 PCShellSetName - Sets an optional name to associate with a shell 711 preconditioner. 712 713 Not Collective 714 715 Input Parameters: 716 + pc - the preconditioner context 717 - name - character string describing shell preconditioner 718 719 Level: developer 720 721 .keywords: PC, shell, set, name, user-provided 722 723 .seealso: PCShellGetName() 724 @*/ 725 PetscErrorCode PCShellSetName(PC pc,const char name[]) 726 { 727 PetscErrorCode ierr; 728 729 PetscFunctionBegin; 730 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 731 ierr = PetscTryMethod(pc,"PCShellSetName_C",(PC,const char []),(pc,name));CHKERRQ(ierr); 732 PetscFunctionReturn(0); 733 } 734 735 #undef __FUNCT__ 736 #define __FUNCT__ "PCShellGetName" 737 /*@C 738 PCShellGetName - Gets an optional name that the user has set for a shell 739 preconditioner. 740 741 Not Collective 742 743 Input Parameter: 744 . pc - the preconditioner context 745 746 Output Parameter: 747 . name - character string describing shell preconditioner (you should not free this) 748 749 Level: developer 750 751 .keywords: PC, shell, get, name, user-provided 752 753 .seealso: PCShellSetName() 754 @*/ 755 PetscErrorCode PCShellGetName(PC pc,const char *name[]) 756 { 757 PetscErrorCode ierr; 758 759 PetscFunctionBegin; 760 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 761 PetscValidPointer(name,2); 762 ierr = PetscUseMethod(pc,"PCShellGetName_C",(PC,const char*[]),(pc,name));CHKERRQ(ierr); 763 PetscFunctionReturn(0); 764 } 765 766 #undef __FUNCT__ 767 #define __FUNCT__ "PCShellSetApplyRichardson" 768 /*@C 769 PCShellSetApplyRichardson - Sets routine to use as preconditioner 770 in Richardson iteration. 771 772 Logically Collective on PC 773 774 Input Parameters: 775 + pc - the preconditioner context 776 - apply - the application-provided preconditioning routine 777 778 Calling sequence of apply: 779 .vb 780 PetscErrorCode apply (PC pc,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt maxits) 781 .ve 782 783 + pc - the preconditioner, get the application context with PCShellGetContext() 784 . b - right-hand-side 785 . x - current iterate 786 . r - work space 787 . rtol - relative tolerance of residual norm to stop at 788 . abstol - absolute tolerance of residual norm to stop at 789 . dtol - if residual norm increases by this factor than return 790 - maxits - number of iterations to run 791 792 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 793 794 Level: developer 795 796 .keywords: PC, shell, set, apply, Richardson, user-provided 797 798 .seealso: PCShellSetApply(), PCShellSetContext() 799 @*/ 800 PetscErrorCode PCShellSetApplyRichardson(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*)) 801 { 802 PetscErrorCode ierr; 803 804 PetscFunctionBegin; 805 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 806 ierr = PetscTryMethod(pc,"PCShellSetApplyRichardson_C",(PC,PetscErrorCode (*)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*)),(pc,apply));CHKERRQ(ierr); 807 PetscFunctionReturn(0); 808 } 809 810 /*MC 811 PCSHELL - Creates a new preconditioner class for use with your 812 own private data storage format. 813 814 Level: advanced 815 > 816 Concepts: providing your own preconditioner 817 818 Usage: 819 $ extern PetscErrorCode apply(PC,Vec,Vec); 820 $ extern PetscErrorCode applyba(PC,PCSide,Vec,Vec,Vec); 821 $ extern PetscErrorCode applytranspose(PC,Vec,Vec); 822 $ extern PetscErrorCode setup(PC); 823 $ extern PetscErrorCode destroy(PC); 824 $ 825 $ PCCreate(comm,&pc); 826 $ PCSetType(pc,PCSHELL); 827 $ PCShellSetContext(pc,ctx) 828 $ PCShellSetApply(pc,apply); 829 $ PCShellSetApplyBA(pc,applyba); (optional) 830 $ PCShellSetApplyTranspose(pc,applytranspose); (optional) 831 $ PCShellSetSetUp(pc,setup); (optional) 832 $ PCShellSetDestroy(pc,destroy); (optional) 833 834 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 835 MATSHELL, PCShellSetSetUp(), PCShellSetApply(), PCShellSetView(), 836 PCShellSetApplyTranspose(), PCShellSetName(), PCShellSetApplyRichardson(), 837 PCShellGetName(), PCShellSetContext(), PCShellGetContext(), PCShellSetApplyBA() 838 M*/ 839 840 #undef __FUNCT__ 841 #define __FUNCT__ "PCCreate_Shell" 842 PETSC_EXTERN PetscErrorCode PCCreate_Shell(PC pc) 843 { 844 PetscErrorCode ierr; 845 PC_Shell *shell; 846 847 PetscFunctionBegin; 848 ierr = PetscNewLog(pc,&shell);CHKERRQ(ierr); 849 pc->data = (void*)shell; 850 851 pc->ops->destroy = PCDestroy_Shell; 852 pc->ops->view = PCView_Shell; 853 pc->ops->apply = PCApply_Shell; 854 pc->ops->applytranspose = 0; 855 pc->ops->applyrichardson = 0; 856 pc->ops->setup = 0; 857 pc->ops->presolve = 0; 858 pc->ops->postsolve = 0; 859 860 shell->apply = 0; 861 shell->applytranspose = 0; 862 shell->name = 0; 863 shell->applyrich = 0; 864 shell->presolve = 0; 865 shell->postsolve = 0; 866 shell->ctx = 0; 867 shell->setup = 0; 868 shell->view = 0; 869 shell->destroy = 0; 870 871 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetDestroy_C",PCShellSetDestroy_Shell);CHKERRQ(ierr); 872 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetSetUp_C",PCShellSetSetUp_Shell);CHKERRQ(ierr); 873 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApply_C",PCShellSetApply_Shell);CHKERRQ(ierr); 874 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyBA_C",PCShellSetApplyBA_Shell);CHKERRQ(ierr); 875 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPreSolve_C",PCShellSetPreSolve_Shell);CHKERRQ(ierr); 876 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPostSolve_C",PCShellSetPostSolve_Shell);CHKERRQ(ierr); 877 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetView_C",PCShellSetView_Shell);CHKERRQ(ierr); 878 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",PCShellSetApplyTranspose_Shell);CHKERRQ(ierr); 879 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetName_C",PCShellSetName_Shell);CHKERRQ(ierr); 880 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellGetName_C",PCShellGetName_Shell);CHKERRQ(ierr); 881 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",PCShellSetApplyRichardson_Shell);CHKERRQ(ierr); 882 PetscFunctionReturn(0); 883 } 884 885 886 887 888 889 890