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