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