1 /* 2 This provides a simple shell for Fortran (and C programmers) to 3 create their own preconditioner without writing much interface code. 4 */ 5 6 #include "src/ksp/pc/pcimpl.h" /*I "petscpc.h" I*/ 7 #include "vecimpl.h" 8 9 EXTERN_C_BEGIN 10 typedef struct { 11 void *ctx,*ctxrich; /* user provided contexts for preconditioner */ 12 PetscErrorCode (*setup)(void*); 13 PetscErrorCode (*apply)(void*,Vec,Vec); 14 PetscErrorCode (*view)(void*,PetscViewer); 15 PetscErrorCode (*applytranspose)(void*,Vec,Vec); 16 PetscErrorCode (*applyrich)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int); 17 char *name; 18 } PC_Shell; 19 EXTERN_C_END 20 21 #undef __FUNCT__ 22 #define __FUNCT__ "PCApply_SetUp" 23 static PetscErrorCode PCSetUp_Shell(PC pc) 24 { 25 PC_Shell *shell; 26 PetscErrorCode ierr; 27 28 PetscFunctionBegin; 29 shell = (PC_Shell*)pc->data; 30 if (shell->setup) { 31 ierr = (*shell->setup)(shell->ctx);CHKERRQ(ierr); 32 } 33 PetscFunctionReturn(0); 34 } 35 36 #undef __FUNCT__ 37 #define __FUNCT__ "PCApply_Shell" 38 static PetscErrorCode PCApply_Shell(PC pc,Vec x,Vec y) 39 { 40 PC_Shell *shell; 41 PetscErrorCode ierr; 42 43 PetscFunctionBegin; 44 shell = (PC_Shell*)pc->data; 45 if (!shell->apply) SETERRQ(PETSC_ERR_USER,"No apply() routine provided to Shell PC"); 46 ierr = (*shell->apply)(shell->ctx,x,y);CHKERRQ(ierr); 47 PetscFunctionReturn(0); 48 } 49 50 #undef __FUNCT__ 51 #define __FUNCT__ "PCApplyTranspose_Shell" 52 static PetscErrorCode PCApplyTranspose_Shell(PC pc,Vec x,Vec y) 53 { 54 PC_Shell *shell; 55 PetscErrorCode ierr; 56 57 PetscFunctionBegin; 58 shell = (PC_Shell*)pc->data; 59 if (!shell->applytranspose) SETERRQ(PETSC_ERR_USER,"No applytranspose() routine provided to Shell PC"); 60 ierr = (*shell->applytranspose)(shell->ctx,x,y);CHKERRQ(ierr); 61 PetscFunctionReturn(0); 62 } 63 64 #undef __FUNCT__ 65 #define __FUNCT__ "PCApplyRichardson_Shell" 66 static PetscErrorCode PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int it) 67 { 68 PetscErrorCode ierr; 69 PC_Shell *shell; 70 71 PetscFunctionBegin; 72 shell = (PC_Shell*)pc->data; 73 ierr = (*shell->applyrich)(shell->ctxrich,x,y,w,rtol,atol,dtol,it);CHKERRQ(ierr); 74 PetscFunctionReturn(0); 75 } 76 77 #undef __FUNCT__ 78 #define __FUNCT__ "PCDestroy_Shell" 79 static PetscErrorCode PCDestroy_Shell(PC pc) 80 { 81 PC_Shell *shell = (PC_Shell*)pc->data; 82 PetscErrorCode ierr; 83 84 PetscFunctionBegin; 85 if (shell->name) {ierr = PetscFree(shell->name);} 86 ierr = PetscFree(shell);CHKERRQ(ierr); 87 PetscFunctionReturn(0); 88 } 89 90 #undef __FUNCT__ 91 #define __FUNCT__ "PCView_Shell" 92 static PetscErrorCode PCView_Shell(PC pc,PetscViewer viewer) 93 { 94 PC_Shell *shell = (PC_Shell*)pc->data; 95 PetscErrorCode ierr; 96 PetscTruth iascii; 97 98 PetscFunctionBegin; 99 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 100 if (iascii) { 101 if (shell->name) {ierr = PetscViewerASCIIPrintf(viewer," Shell: %s\n",shell->name);CHKERRQ(ierr);} 102 else {ierr = PetscViewerASCIIPrintf(viewer," Shell: no name\n");CHKERRQ(ierr);} 103 } 104 if (shell->view) { 105 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 106 ierr = (*shell->view)(shell->ctx,viewer);CHKERRQ(ierr); 107 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 108 } 109 PetscFunctionReturn(0); 110 } 111 112 /* ------------------------------------------------------------------------------*/ 113 EXTERN_C_BEGIN 114 #undef __FUNCT__ 115 #define __FUNCT__ "PCShellSetSetUp_Shell" 116 PetscErrorCode PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*setup)(void*)) 117 { 118 PC_Shell *shell; 119 120 PetscFunctionBegin; 121 shell = (PC_Shell*)pc->data; 122 shell->setup = setup; 123 PetscFunctionReturn(0); 124 } 125 EXTERN_C_END 126 127 EXTERN_C_BEGIN 128 #undef __FUNCT__ 129 #define __FUNCT__ "PCShellSetApply_Shell" 130 PetscErrorCode PCShellSetApply_Shell(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec),void *ptr) 131 { 132 PC_Shell *shell; 133 134 PetscFunctionBegin; 135 shell = (PC_Shell*)pc->data; 136 shell->apply = apply; 137 shell->ctx = ptr; 138 PetscFunctionReturn(0); 139 } 140 EXTERN_C_END 141 142 EXTERN_C_BEGIN 143 #undef __FUNCT__ 144 #define __FUNCT__ "PCShellSetView_Shell" 145 PetscErrorCode PCShellSetView_Shell(PC pc,PetscErrorCode (*view)(void*,PetscViewer)) 146 { 147 PC_Shell *shell; 148 149 PetscFunctionBegin; 150 shell = (PC_Shell*)pc->data; 151 shell->view = view; 152 PetscFunctionReturn(0); 153 } 154 EXTERN_C_END 155 156 EXTERN_C_BEGIN 157 #undef __FUNCT__ 158 #define __FUNCT__ "PCShellSetApplyTranspose_Shell" 159 PetscErrorCode PCShellSetApplyTranspose_Shell(PC pc,PetscErrorCode (*applytranspose)(void*,Vec,Vec)) 160 { 161 PC_Shell *shell; 162 163 PetscFunctionBegin; 164 shell = (PC_Shell*)pc->data; 165 shell->applytranspose = applytranspose; 166 PetscFunctionReturn(0); 167 } 168 EXTERN_C_END 169 170 EXTERN_C_BEGIN 171 #undef __FUNCT__ 172 #define __FUNCT__ "PCShellSetName_Shell" 173 PetscErrorCode PCShellSetName_Shell(PC pc,const char name[]) 174 { 175 PC_Shell *shell; 176 PetscErrorCode ierr; 177 178 PetscFunctionBegin; 179 shell = (PC_Shell*)pc->data; 180 ierr = PetscStrallocpy(name,&shell->name);CHKERRQ(ierr); 181 PetscFunctionReturn(0); 182 } 183 EXTERN_C_END 184 185 EXTERN_C_BEGIN 186 #undef __FUNCT__ 187 #define __FUNCT__ "PCShellGetName_Shell" 188 PetscErrorCode PCShellGetName_Shell(PC pc,char *name[]) 189 { 190 PC_Shell *shell; 191 192 PetscFunctionBegin; 193 shell = (PC_Shell*)pc->data; 194 *name = shell->name; 195 PetscFunctionReturn(0); 196 } 197 EXTERN_C_END 198 199 EXTERN_C_BEGIN 200 #undef __FUNCT__ 201 #define __FUNCT__ "PCShellSetApplyRichardson_Shell" 202 PetscErrorCode PCShellSetApplyRichardson_Shell(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr) 203 { 204 PC_Shell *shell; 205 206 PetscFunctionBegin; 207 shell = (PC_Shell*)pc->data; 208 pc->ops->applyrichardson = PCApplyRichardson_Shell; 209 shell->applyrich = apply; 210 shell->ctxrich = ptr; 211 PetscFunctionReturn(0); 212 } 213 EXTERN_C_END 214 215 /* -------------------------------------------------------------------------------*/ 216 217 #undef __FUNCT__ 218 #define __FUNCT__ "PCShellSetSetUp" 219 /*@C 220 PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the 221 matrix operator is changed. 222 223 Collective on PC 224 225 Input Parameters: 226 + pc - the preconditioner context 227 . setup - the application-provided setup routine 228 229 Calling sequence of setup: 230 .vb 231 int setup (void *ptr) 232 .ve 233 234 . ptr - the application context 235 236 Level: developer 237 238 .keywords: PC, shell, set, setup, user-provided 239 240 .seealso: PCShellSetApplyRichardson(), PCShellSetApply() 241 @*/ 242 PetscErrorCode PCShellSetSetUp(PC pc,PetscErrorCode (*setup)(void*)) 243 { 244 PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*)); 245 246 PetscFunctionBegin; 247 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 248 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetSetUp_C",(void (**)(void))&f);CHKERRQ(ierr); 249 if (f) { 250 ierr = (*f)(pc,setup);CHKERRQ(ierr); 251 } 252 PetscFunctionReturn(0); 253 } 254 255 256 #undef __FUNCT__ 257 #define __FUNCT__ "PCShellSetView" 258 /*@C 259 PCShellSetView - Sets routine to use as viewer of shell preconditioner 260 261 Collective on PC 262 263 Input Parameters: 264 + pc - the preconditioner context 265 - view - the application-provided view routine 266 267 Calling sequence of apply: 268 .vb 269 int view(void *ptr,PetscViewer v) 270 .ve 271 272 + ptr - the application context 273 - v - viewer 274 275 Level: developer 276 277 .keywords: PC, shell, set, apply, user-provided 278 279 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose() 280 @*/ 281 PetscErrorCode PCShellSetView(PC pc,PetscErrorCode (*view)(void*,PetscViewer)) 282 { 283 PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,PetscViewer)); 284 285 PetscFunctionBegin; 286 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 287 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetView_C",(void (**)(void))&f);CHKERRQ(ierr); 288 if (f) { 289 ierr = (*f)(pc,view);CHKERRQ(ierr); 290 } 291 PetscFunctionReturn(0); 292 } 293 294 #undef __FUNCT__ 295 #define __FUNCT__ "PCShellSetApply" 296 /*@C 297 PCShellSetApply - Sets routine to use as preconditioner. 298 299 Collective on PC 300 301 Input Parameters: 302 + pc - the preconditioner context 303 . apply - the application-provided preconditioning routine 304 - ptr - pointer to data needed by this routine 305 306 Calling sequence of apply: 307 .vb 308 int apply (void *ptr,Vec xin,Vec xout) 309 .ve 310 311 + ptr - the application context 312 . xin - input vector 313 - xout - output vector 314 315 Level: developer 316 317 .keywords: PC, shell, set, apply, user-provided 318 319 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose() 320 @*/ 321 PetscErrorCode PCShellSetApply(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec),void *ptr) 322 { 323 PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec),void *); 324 325 PetscFunctionBegin; 326 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 327 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApply_C",(void (**)(void))&f);CHKERRQ(ierr); 328 if (f) { 329 ierr = (*f)(pc,apply,ptr);CHKERRQ(ierr); 330 } 331 PetscFunctionReturn(0); 332 } 333 334 #undef __FUNCT__ 335 #define __FUNCT__ "PCShellSetApplyTranspose" 336 /*@C 337 PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose. 338 339 Collective on PC 340 341 Input Parameters: 342 + pc - the preconditioner context 343 - apply - the application-provided preconditioning transpose routine 344 345 Calling sequence of apply: 346 .vb 347 int applytranspose (void *ptr,Vec xin,Vec xout) 348 .ve 349 350 + ptr - the application context 351 . xin - input vector 352 - xout - output vector 353 354 Level: developer 355 356 Notes: 357 Uses the same context variable as PCShellSetApply(). 358 359 .keywords: PC, shell, set, apply, user-provided 360 361 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply() 362 @*/ 363 PetscErrorCode PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(void*,Vec,Vec)) 364 { 365 PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec)); 366 367 PetscFunctionBegin; 368 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 369 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",(void (**)(void))&f);CHKERRQ(ierr); 370 if (f) { 371 ierr = (*f)(pc,applytranspose);CHKERRQ(ierr); 372 } 373 PetscFunctionReturn(0); 374 } 375 376 #undef __FUNCT__ 377 #define __FUNCT__ "PCShellSetName" 378 /*@C 379 PCShellSetName - Sets an optional name to associate with a shell 380 preconditioner. 381 382 Not Collective 383 384 Input Parameters: 385 + pc - the preconditioner context 386 - name - character string describing shell preconditioner 387 388 Level: developer 389 390 .keywords: PC, shell, set, name, user-provided 391 392 .seealso: PCShellGetName() 393 @*/ 394 PetscErrorCode PCShellSetName(PC pc,const char name[]) 395 { 396 PetscErrorCode ierr,(*f)(PC,const char []); 397 398 PetscFunctionBegin; 399 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 400 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetName_C",(void (**)(void))&f);CHKERRQ(ierr); 401 if (f) { 402 ierr = (*f)(pc,name);CHKERRQ(ierr); 403 } 404 PetscFunctionReturn(0); 405 } 406 407 #undef __FUNCT__ 408 #define __FUNCT__ "PCShellGetName" 409 /*@C 410 PCShellGetName - Gets an optional name that the user has set for a shell 411 preconditioner. 412 413 Not Collective 414 415 Input Parameter: 416 . pc - the preconditioner context 417 418 Output Parameter: 419 . name - character string describing shell preconditioner (you should not free this) 420 421 Level: developer 422 423 .keywords: PC, shell, get, name, user-provided 424 425 .seealso: PCShellSetName() 426 @*/ 427 PetscErrorCode PCShellGetName(PC pc,char *name[]) 428 { 429 PetscErrorCode ierr,(*f)(PC,char *[]); 430 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 433 PetscValidPointer(name,2); 434 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellGetName_C",(void (**)(void))&f);CHKERRQ(ierr); 435 if (f) { 436 ierr = (*f)(pc,name);CHKERRQ(ierr); 437 } else { 438 SETERRQ(PETSC_ERR_ARG_WRONG,"Not shell preconditioner, cannot get name"); 439 } 440 PetscFunctionReturn(0); 441 } 442 443 #undef __FUNCT__ 444 #define __FUNCT__ "PCShellSetApplyRichardson" 445 /*@C 446 PCShellSetApplyRichardson - Sets routine to use as preconditioner 447 in Richardson iteration. 448 449 Collective on PC 450 451 Input Parameters: 452 + pc - the preconditioner context 453 . apply - the application-provided preconditioning routine 454 - ptr - pointer to data needed by this routine 455 456 Calling sequence of apply: 457 .vb 458 int apply (void *ptr,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal atol,PetscReal dtol,int maxits) 459 .ve 460 461 + ptr - the application context 462 . b - right-hand-side 463 . x - current iterate 464 . r - work space 465 . rtol - relative tolerance of residual norm to stop at 466 . atol - absolute tolerance of residual norm to stop at 467 . dtol - if residual norm increases by this factor than return 468 - maxits - number of iterations to run 469 470 Level: developer 471 472 .keywords: PC, shell, set, apply, Richardson, user-provided 473 474 .seealso: PCShellSetApply() 475 @*/ 476 PetscErrorCode PCShellSetApplyRichardson(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr) 477 { 478 PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *); 479 480 PetscFunctionBegin; 481 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 482 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",(void (**)(void))&f);CHKERRQ(ierr); 483 if (f) { 484 ierr = (*f)(pc,apply,ptr);CHKERRQ(ierr); 485 } 486 PetscFunctionReturn(0); 487 } 488 489 /*MC 490 PCSHELL - Creates a new preconditioner class for use with your 491 own private data storage format. 492 493 Level: advanced 494 495 Concepts: providing your own preconditioner 496 497 Usage: 498 $ PetscErrorCode (*mult)(void*,Vec,Vec); 499 $ PetscErrorCode (*setup)(void*); 500 $ PCCreate(comm,&pc); 501 $ PCSetType(pc,PCSHELL); 502 $ PCShellSetApply(pc,mult,ctx); 503 $ PCShellSetSetUp(pc,setup); (optional) 504 505 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 506 KSPSHELL(), MATSHELL(), PCShellSetUp(), PCShellSetApply(), PCShellSetView(), 507 PCShellSetApplyTranpose(), PCShellSetName(), PCShellSetApplyRichardson(), 508 PCShellGetName() 509 M*/ 510 511 EXTERN_C_BEGIN 512 #undef __FUNCT__ 513 #define __FUNCT__ "PCCreate_Shell" 514 PetscErrorCode PCCreate_Shell(PC pc) 515 { 516 PetscErrorCode ierr; 517 PC_Shell *shell; 518 519 PetscFunctionBegin; 520 pc->ops->destroy = PCDestroy_Shell; 521 ierr = PetscNew(PC_Shell,&shell);CHKERRQ(ierr); 522 PetscLogObjectMemory(pc,sizeof(PC_Shell)); 523 524 pc->data = (void*)shell; 525 pc->name = 0; 526 527 pc->ops->apply = PCApply_Shell; 528 pc->ops->view = PCView_Shell; 529 pc->ops->applytranspose = PCApplyTranspose_Shell; 530 pc->ops->applyrichardson = 0; 531 pc->ops->setup = PCSetUp_Shell; 532 pc->ops->view = PCView_Shell; 533 534 shell->apply = 0; 535 shell->applytranspose = 0; 536 shell->name = 0; 537 shell->applyrich = 0; 538 shell->ctxrich = 0; 539 shell->ctx = 0; 540 shell->setup = 0; 541 shell->view = 0; 542 543 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetSetUp_C","PCShellSetSetUp_Shell", 544 PCShellSetSetUp_Shell);CHKERRQ(ierr); 545 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApply_C","PCShellSetApply_Shell", 546 PCShellSetApply_Shell);CHKERRQ(ierr); 547 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetView_C","PCShellSetView_Shell", 548 PCShellSetView_Shell);CHKERRQ(ierr); 549 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyTranspose_C", 550 "PCShellSetApplyTranspose_Shell", 551 PCShellSetApplyTranspose_Shell);CHKERRQ(ierr); 552 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetName_C","PCShellSetName_Shell", 553 PCShellSetName_Shell);CHKERRQ(ierr); 554 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellGetName_C","PCShellGetName_Shell", 555 PCShellGetName_Shell);CHKERRQ(ierr); 556 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyRichardson_C", 557 "PCShellSetApplyRichardson_Shell", 558 PCShellSetApplyRichardson_Shell);CHKERRQ(ierr); 559 560 PetscFunctionReturn(0); 561 } 562 EXTERN_C_END 563 564 565 566 567 568 569