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