1 #define PETSCKSP_DLL 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 "vecimpl.h" 10 11 EXTERN_C_BEGIN 12 typedef struct { 13 void *ctx,*ctxrich; /* user provided contexts for preconditioner */ 14 PetscErrorCode (*setup)(void*); 15 PetscErrorCode (*apply)(void*,Vec,Vec); 16 PetscErrorCode (*view)(void*,PetscViewer); 17 PetscErrorCode (*applytranspose)(void*,Vec,Vec); 18 PetscErrorCode (*applyrich)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt); 19 char *name; 20 } PC_Shell; 21 EXTERN_C_END 22 23 #undef __FUNCT__ 24 #define __FUNCT__ "PCApply_SetUp" 25 static PetscErrorCode PCSetUp_Shell(PC pc) 26 { 27 PC_Shell *shell; 28 PetscErrorCode 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 PetscErrorCode PCApply_Shell(PC pc,Vec x,Vec y) 41 { 42 PC_Shell *shell; 43 PetscErrorCode ierr; 44 45 PetscFunctionBegin; 46 shell = (PC_Shell*)pc->data; 47 if (!shell->apply) SETERRQ(PETSC_ERR_USER,"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 PetscErrorCode PCApplyTranspose_Shell(PC pc,Vec x,Vec y) 55 { 56 PC_Shell *shell; 57 PetscErrorCode ierr; 58 59 PetscFunctionBegin; 60 shell = (PC_Shell*)pc->data; 61 if (!shell->applytranspose) SETERRQ(PETSC_ERR_USER,"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 PetscErrorCode PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt it) 69 { 70 PetscErrorCode ierr; 71 PC_Shell *shell; 72 73 PetscFunctionBegin; 74 shell = (PC_Shell*)pc->data; 75 ierr = (*shell->applyrich)(shell->ctxrich,x,y,w,rtol,abstol,dtol,it);CHKERRQ(ierr); 76 PetscFunctionReturn(0); 77 } 78 79 #undef __FUNCT__ 80 #define __FUNCT__ "PCDestroy_Shell" 81 static PetscErrorCode PCDestroy_Shell(PC pc) 82 { 83 PC_Shell *shell = (PC_Shell*)pc->data; 84 PetscErrorCode 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 PetscErrorCode PCView_Shell(PC pc,PetscViewer viewer) 95 { 96 PC_Shell *shell = (PC_Shell*)pc->data; 97 PetscErrorCode ierr; 98 PetscTruth iascii; 99 100 PetscFunctionBegin; 101 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 102 if (iascii) { 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply_Shell(PC pc,PetscErrorCode (*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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView_Shell(PC pc,PetscErrorCode (*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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose_Shell(PC pc,PetscErrorCode (*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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName_Shell(PC pc,const char name[]) 176 { 177 PC_Shell *shell; 178 PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyRichardson_Shell(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt),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 PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp(PC pc,PetscErrorCode (*setup)(void*)) 245 { 246 PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*)); 247 248 PetscFunctionBegin; 249 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 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 PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView(PC pc,PetscErrorCode (*view)(void*,PetscViewer)) 284 { 285 PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,PetscViewer)); 286 287 PetscFunctionBegin; 288 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 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 PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec),void *ptr) 324 { 325 PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec),void *); 326 327 PetscFunctionBegin; 328 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 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 PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(void*,Vec,Vec)) 366 { 367 PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec)); 368 369 PetscFunctionBegin; 370 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName(PC pc,const char name[]) 397 { 398 PetscErrorCode ierr,(*f)(PC,const char []); 399 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetName(PC pc,char *name[]) 430 { 431 PetscErrorCode ierr,(*f)(PC,char *[]); 432 433 PetscFunctionBegin; 434 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 435 PetscValidPointer(name,2); 436 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellGetName_C",(void (**)(void))&f);CHKERRQ(ierr); 437 if (f) { 438 ierr = (*f)(pc,name);CHKERRQ(ierr); 439 } else { 440 SETERRQ(PETSC_ERR_ARG_WRONG,"Not shell preconditioner, cannot get name"); 441 } 442 PetscFunctionReturn(0); 443 } 444 445 #undef __FUNCT__ 446 #define __FUNCT__ "PCShellSetApplyRichardson" 447 /*@C 448 PCShellSetApplyRichardson - Sets routine to use as preconditioner 449 in Richardson iteration. 450 451 Collective on PC 452 453 Input Parameters: 454 + pc - the preconditioner context 455 . apply - the application-provided preconditioning routine 456 - ptr - pointer to data needed by this routine 457 458 Calling sequence of apply: 459 .vb 460 PetscErrorCode apply (void *ptr,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt maxits) 461 .ve 462 463 + ptr - the application context 464 . b - right-hand-side 465 . x - current iterate 466 . r - work space 467 . rtol - relative tolerance of residual norm to stop at 468 . abstol - absolute tolerance of residual norm to stop at 469 . dtol - if residual norm increases by this factor than return 470 - maxits - number of iterations to run 471 472 Level: developer 473 474 .keywords: PC, shell, set, apply, Richardson, user-provided 475 476 .seealso: PCShellSetApply() 477 @*/ 478 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyRichardson(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt),void *ptr) 479 { 480 PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt),void *); 481 482 PetscFunctionBegin; 483 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 484 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",(void (**)(void))&f);CHKERRQ(ierr); 485 if (f) { 486 ierr = (*f)(pc,apply,ptr);CHKERRQ(ierr); 487 } 488 PetscFunctionReturn(0); 489 } 490 491 /*MC 492 PCSHELL - Creates a new preconditioner class for use with your 493 own private data storage format. 494 495 Level: advanced 496 497 Concepts: providing your own preconditioner 498 499 Usage: 500 $ PetscErrorCode (*mult)(void*,Vec,Vec); 501 $ PetscErrorCode (*setup)(void*); 502 $ PCCreate(comm,&pc); 503 $ PCSetType(pc,PCSHELL); 504 $ PCShellSetApply(pc,mult,ctx); 505 $ PCShellSetSetUp(pc,setup); (optional) 506 507 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 508 MATSHELL, PCShellSetUp(), PCShellSetApply(), PCShellSetView(), 509 PCShellSetApplyTranpose(), PCShellSetName(), PCShellSetApplyRichardson(), 510 PCShellGetName() 511 M*/ 512 513 EXTERN_C_BEGIN 514 #undef __FUNCT__ 515 #define __FUNCT__ "PCCreate_Shell" 516 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Shell(PC pc) 517 { 518 PetscErrorCode ierr; 519 PC_Shell *shell; 520 521 PetscFunctionBegin; 522 pc->ops->destroy = PCDestroy_Shell; 523 ierr = PetscNew(PC_Shell,&shell);CHKERRQ(ierr); 524 ierr = PetscLogObjectMemory(pc,sizeof(PC_Shell));CHKERRQ(ierr); 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