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 Level: developer 609 610 .keywords: PC, shell, set, apply, user-provided 611 612 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApplyBA(), PCShellSetApplySymmetricRight(),PCShellSetApplySymmetricLeft() 613 @*/ 614 PetscErrorCode PCShellSetApply(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec)) 615 { 616 PetscErrorCode ierr; 617 618 PetscFunctionBegin; 619 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 620 ierr = PetscTryMethod(pc,"PCShellSetApply_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));CHKERRQ(ierr); 621 PetscFunctionReturn(0); 622 } 623 624 #undef __FUNCT__ 625 #define __FUNCT__ "PCShellSetApplySymmetricLeft" 626 /*@C 627 PCShellSetApplySymmetricLeft - Sets routine to use as left preconditioner (when the PC_SYMMETRIC is used). 628 629 Logically Collective on PC 630 631 Input Parameters: 632 + pc - the preconditioner context 633 - apply - the application-provided left preconditioning routine 634 635 Calling sequence of apply: 636 .vb 637 PetscErrorCode apply (PC pc,Vec xin,Vec xout) 638 .ve 639 640 + pc - the preconditioner, get the application context with PCShellGetContext() 641 . xin - input vector 642 - xout - output vector 643 644 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 645 646 Level: developer 647 648 .keywords: PC, shell, set, apply, user-provided 649 650 .seealso: PCShellSetApply(), PCShellSetApplySymmetricLeft(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext() 651 @*/ 652 PetscErrorCode PCShellSetApplySymmetricLeft(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec)) 653 { 654 PetscErrorCode ierr; 655 656 PetscFunctionBegin; 657 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 658 ierr = PetscTryMethod(pc,"PCShellSetApplySymmetricLeft_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));CHKERRQ(ierr); 659 PetscFunctionReturn(0); 660 } 661 662 #undef __FUNCT__ 663 #define __FUNCT__ "PCShellSetApplySymmetricRight" 664 /*@C 665 PCShellSetApplySymmetricRight - Sets routine to use as right preconditioner (when the PC_SYMMETRIC is used). 666 667 Logically Collective on PC 668 669 Input Parameters: 670 + pc - the preconditioner context 671 - apply - the application-provided right preconditioning routine 672 673 Calling sequence of apply: 674 .vb 675 PetscErrorCode apply (PC pc,Vec xin,Vec xout) 676 .ve 677 678 + pc - the preconditioner, get the application context with PCShellGetContext() 679 . xin - input vector 680 - xout - output vector 681 682 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 683 684 Level: developer 685 686 .keywords: PC, shell, set, apply, user-provided 687 688 .seealso: PCShellSetApply(), PCShellSetApplySymmetricLeft(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext() 689 @*/ 690 PetscErrorCode PCShellSetApplySymmetricRight(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec)) 691 { 692 PetscErrorCode ierr; 693 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 696 ierr = PetscTryMethod(pc,"PCShellSetApplySymmetricRight_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));CHKERRQ(ierr); 697 PetscFunctionReturn(0); 698 } 699 700 #undef __FUNCT__ 701 #define __FUNCT__ "PCShellSetApplyBA" 702 /*@C 703 PCShellSetApplyBA - Sets routine to use as preconditioner times operator. 704 705 Logically Collective on PC 706 707 Input Parameters: 708 + pc - the preconditioner context 709 - applyBA - the application-provided BA routine 710 711 Calling sequence of apply: 712 .vb 713 PetscErrorCode applyBA (PC pc,Vec xin,Vec xout) 714 .ve 715 716 + pc - the preconditioner, get the application context with PCShellGetContext() 717 . xin - input vector 718 - xout - output vector 719 720 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 721 722 Level: developer 723 724 .keywords: PC, shell, set, apply, user-provided 725 726 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApply() 727 @*/ 728 PetscErrorCode PCShellSetApplyBA(PC pc,PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec)) 729 { 730 PetscErrorCode ierr; 731 732 PetscFunctionBegin; 733 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 734 ierr = PetscTryMethod(pc,"PCShellSetApplyBA_C",(PC,PetscErrorCode (*)(PC,PCSide,Vec,Vec,Vec)),(pc,applyBA));CHKERRQ(ierr); 735 PetscFunctionReturn(0); 736 } 737 738 #undef __FUNCT__ 739 #define __FUNCT__ "PCShellSetApplyTranspose" 740 /*@C 741 PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose. 742 743 Logically Collective on PC 744 745 Input Parameters: 746 + pc - the preconditioner context 747 - apply - the application-provided preconditioning transpose routine 748 749 Calling sequence of apply: 750 .vb 751 PetscErrorCode applytranspose (PC pc,Vec xin,Vec xout) 752 .ve 753 754 + pc - the preconditioner, get the application context with PCShellGetContext() 755 . xin - input vector 756 - xout - output vector 757 758 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 759 760 Level: developer 761 762 Notes: 763 Uses the same context variable as PCShellSetApply(). 764 765 .keywords: PC, shell, set, apply, user-provided 766 767 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply(), PCSetContext(), PCShellSetApplyBA() 768 @*/ 769 PetscErrorCode PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(PC,Vec,Vec)) 770 { 771 PetscErrorCode ierr; 772 773 PetscFunctionBegin; 774 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 775 ierr = PetscTryMethod(pc,"PCShellSetApplyTranspose_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,applytranspose));CHKERRQ(ierr); 776 PetscFunctionReturn(0); 777 } 778 779 #undef __FUNCT__ 780 #define __FUNCT__ "PCShellSetPreSolve" 781 /*@C 782 PCShellSetPreSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is 783 applied. This usually does something like scale the linear system in some application 784 specific way. 785 786 Logically Collective on PC 787 788 Input Parameters: 789 + pc - the preconditioner context 790 - presolve - the application-provided presolve routine 791 792 Calling sequence of presolve: 793 .vb 794 PetscErrorCode presolve (PC,KSP ksp,Vec b,Vec x) 795 .ve 796 797 + pc - the preconditioner, get the application context with PCShellGetContext() 798 . xin - input vector 799 - xout - output vector 800 801 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 802 803 Level: developer 804 805 .keywords: PC, shell, set, apply, user-provided 806 807 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPostSolve(), PCShellSetContext() 808 @*/ 809 PetscErrorCode PCShellSetPreSolve(PC pc,PetscErrorCode (*presolve)(PC,KSP,Vec,Vec)) 810 { 811 PetscErrorCode ierr; 812 813 PetscFunctionBegin; 814 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 815 ierr = PetscTryMethod(pc,"PCShellSetPreSolve_C",(PC,PetscErrorCode (*)(PC,KSP,Vec,Vec)),(pc,presolve));CHKERRQ(ierr); 816 PetscFunctionReturn(0); 817 } 818 819 #undef __FUNCT__ 820 #define __FUNCT__ "PCShellSetPostSolve" 821 /*@C 822 PCShellSetPostSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is 823 applied. This usually does something like scale the linear system in some application 824 specific way. 825 826 Logically Collective on PC 827 828 Input Parameters: 829 + pc - the preconditioner context 830 - postsolve - the application-provided presolve routine 831 832 Calling sequence of postsolve: 833 .vb 834 PetscErrorCode postsolve(PC,KSP ksp,Vec b,Vec x) 835 .ve 836 837 + pc - the preconditioner, get the application context with PCShellGetContext() 838 . xin - input vector 839 - xout - output vector 840 841 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 842 843 Level: developer 844 845 .keywords: PC, shell, set, apply, user-provided 846 847 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPreSolve(), PCShellSetContext() 848 @*/ 849 PetscErrorCode PCShellSetPostSolve(PC pc,PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec)) 850 { 851 PetscErrorCode ierr; 852 853 PetscFunctionBegin; 854 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 855 ierr = PetscTryMethod(pc,"PCShellSetPostSolve_C",(PC,PetscErrorCode (*)(PC,KSP,Vec,Vec)),(pc,postsolve));CHKERRQ(ierr); 856 PetscFunctionReturn(0); 857 } 858 859 #undef __FUNCT__ 860 #define __FUNCT__ "PCShellSetName" 861 /*@C 862 PCShellSetName - Sets an optional name to associate with a shell 863 preconditioner. 864 865 Not Collective 866 867 Input Parameters: 868 + pc - the preconditioner context 869 - name - character string describing shell preconditioner 870 871 Level: developer 872 873 .keywords: PC, shell, set, name, user-provided 874 875 .seealso: PCShellGetName() 876 @*/ 877 PetscErrorCode PCShellSetName(PC pc,const char name[]) 878 { 879 PetscErrorCode ierr; 880 881 PetscFunctionBegin; 882 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 883 ierr = PetscTryMethod(pc,"PCShellSetName_C",(PC,const char []),(pc,name));CHKERRQ(ierr); 884 PetscFunctionReturn(0); 885 } 886 887 #undef __FUNCT__ 888 #define __FUNCT__ "PCShellGetName" 889 /*@C 890 PCShellGetName - Gets an optional name that the user has set for a shell 891 preconditioner. 892 893 Not Collective 894 895 Input Parameter: 896 . pc - the preconditioner context 897 898 Output Parameter: 899 . name - character string describing shell preconditioner (you should not free this) 900 901 Level: developer 902 903 .keywords: PC, shell, get, name, user-provided 904 905 .seealso: PCShellSetName() 906 @*/ 907 PetscErrorCode PCShellGetName(PC pc,const char *name[]) 908 { 909 PetscErrorCode ierr; 910 911 PetscFunctionBegin; 912 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 913 PetscValidPointer(name,2); 914 ierr = PetscUseMethod(pc,"PCShellGetName_C",(PC,const char*[]),(pc,name));CHKERRQ(ierr); 915 PetscFunctionReturn(0); 916 } 917 918 #undef __FUNCT__ 919 #define __FUNCT__ "PCShellSetApplyRichardson" 920 /*@C 921 PCShellSetApplyRichardson - Sets routine to use as preconditioner 922 in Richardson iteration. 923 924 Logically Collective on PC 925 926 Input Parameters: 927 + pc - the preconditioner context 928 - apply - the application-provided preconditioning routine 929 930 Calling sequence of apply: 931 .vb 932 PetscErrorCode apply (PC pc,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt maxits) 933 .ve 934 935 + pc - the preconditioner, get the application context with PCShellGetContext() 936 . b - right-hand-side 937 . x - current iterate 938 . r - work space 939 . rtol - relative tolerance of residual norm to stop at 940 . abstol - absolute tolerance of residual norm to stop at 941 . dtol - if residual norm increases by this factor than return 942 - maxits - number of iterations to run 943 944 Notes: the function MUST return an error code of 0 on success and nonzero on failure. 945 946 Level: developer 947 948 .keywords: PC, shell, set, apply, Richardson, user-provided 949 950 .seealso: PCShellSetApply(), PCShellSetContext() 951 @*/ 952 PetscErrorCode PCShellSetApplyRichardson(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*)) 953 { 954 PetscErrorCode ierr; 955 956 PetscFunctionBegin; 957 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 958 ierr = PetscTryMethod(pc,"PCShellSetApplyRichardson_C",(PC,PetscErrorCode (*)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*)),(pc,apply));CHKERRQ(ierr); 959 PetscFunctionReturn(0); 960 } 961 962 /*MC 963 PCSHELL - Creates a new preconditioner class for use with your 964 own private data storage format. 965 966 Level: advanced 967 > 968 Concepts: providing your own preconditioner 969 970 Usage: 971 $ extern PetscErrorCode apply(PC,Vec,Vec); 972 $ extern PetscErrorCode applyba(PC,PCSide,Vec,Vec,Vec); 973 $ extern PetscErrorCode applytranspose(PC,Vec,Vec); 974 $ extern PetscErrorCode setup(PC); 975 $ extern PetscErrorCode destroy(PC); 976 $ 977 $ PCCreate(comm,&pc); 978 $ PCSetType(pc,PCSHELL); 979 $ PCShellSetContext(pc,ctx) 980 $ PCShellSetApply(pc,apply); 981 $ PCShellSetApplyBA(pc,applyba); (optional) 982 $ PCShellSetApplyTranspose(pc,applytranspose); (optional) 983 $ PCShellSetSetUp(pc,setup); (optional) 984 $ PCShellSetDestroy(pc,destroy); (optional) 985 986 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 987 MATSHELL, PCShellSetSetUp(), PCShellSetApply(), PCShellSetView(), 988 PCShellSetApplyTranspose(), PCShellSetName(), PCShellSetApplyRichardson(), 989 PCShellGetName(), PCShellSetContext(), PCShellGetContext(), PCShellSetApplyBA() 990 M*/ 991 992 #undef __FUNCT__ 993 #define __FUNCT__ "PCCreate_Shell" 994 PETSC_EXTERN PetscErrorCode PCCreate_Shell(PC pc) 995 { 996 PetscErrorCode ierr; 997 PC_Shell *shell; 998 999 PetscFunctionBegin; 1000 ierr = PetscNewLog(pc,&shell);CHKERRQ(ierr); 1001 pc->data = (void*)shell; 1002 1003 pc->ops->destroy = PCDestroy_Shell; 1004 pc->ops->view = PCView_Shell; 1005 pc->ops->apply = PCApply_Shell; 1006 pc->ops->applysymmetricleft = PCApplySymmetricLeft_Shell; 1007 pc->ops->applysymmetricright = PCApplySymmetricRight_Shell; 1008 pc->ops->applytranspose = 0; 1009 pc->ops->applyrichardson = 0; 1010 pc->ops->setup = 0; 1011 pc->ops->presolve = 0; 1012 pc->ops->postsolve = 0; 1013 1014 shell->apply = 0; 1015 shell->applytranspose = 0; 1016 shell->name = 0; 1017 shell->applyrich = 0; 1018 shell->presolve = 0; 1019 shell->postsolve = 0; 1020 shell->ctx = 0; 1021 shell->setup = 0; 1022 shell->view = 0; 1023 shell->destroy = 0; 1024 shell->applysymmetricleft = 0; 1025 shell->applysymmetricright = 0; 1026 1027 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetDestroy_C",PCShellSetDestroy_Shell);CHKERRQ(ierr); 1028 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetSetUp_C",PCShellSetSetUp_Shell);CHKERRQ(ierr); 1029 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApply_C",PCShellSetApply_Shell);CHKERRQ(ierr); 1030 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplySymmetricLeft_C",PCShellSetApplySymmetricLeft_Shell);CHKERRQ(ierr); 1031 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplySymmetricRight_C",PCShellSetApplySymmetricRight_Shell);CHKERRQ(ierr); 1032 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyBA_C",PCShellSetApplyBA_Shell);CHKERRQ(ierr); 1033 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPreSolve_C",PCShellSetPreSolve_Shell);CHKERRQ(ierr); 1034 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPostSolve_C",PCShellSetPostSolve_Shell);CHKERRQ(ierr); 1035 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetView_C",PCShellSetView_Shell);CHKERRQ(ierr); 1036 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",PCShellSetApplyTranspose_Shell);CHKERRQ(ierr); 1037 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetName_C",PCShellSetName_Shell);CHKERRQ(ierr); 1038 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellGetName_C",PCShellGetName_Shell);CHKERRQ(ierr); 1039 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",PCShellSetApplyRichardson_Shell);CHKERRQ(ierr); 1040 PetscFunctionReturn(0); 1041 } 1042 1043 1044 1045 1046 1047 1048