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