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