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