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