1 /* 2 The PF mathematical functions interface routines, callable by users. 3 */ 4 #include <../src/vec/pf/pfimpl.h> /*I "petscpf.h" I*/ 5 6 /* Logging support */ 7 PetscClassId PF_CLASSID = 0; 8 9 PetscFList PFList = PETSC_NULL; /* list of all registered PD functions */ 10 PetscBool PFRegisterAllCalled = PETSC_FALSE; 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "PFSet" 14 /*@C 15 PFSet - Sets the C/C++/Fortran functions to be used by the PF function 16 17 Collective on PF 18 19 Input Parameter: 20 + pf - the function context 21 . apply - function to apply to an array 22 . applyvec - function to apply to a Vec 23 . view - function that prints information about the PF 24 . destroy - function to free the private function context 25 - ctx - private function context 26 27 Level: beginner 28 29 .keywords: PF, setting 30 31 .seealso: PFCreate(), PFDestroy(), PFSetType(), PFApply(), PFApplyVec() 32 @*/ 33 PetscErrorCode PFSet(PF pf,PetscErrorCode (*apply)(void*,PetscInt,const PetscScalar*,PetscScalar*),PetscErrorCode (*applyvec)(void*,Vec,Vec),PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*destroy)(void*),void*ctx) 34 { 35 PetscFunctionBegin; 36 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 37 pf->data = ctx; 38 39 pf->ops->destroy = destroy; 40 pf->ops->apply = apply; 41 pf->ops->applyvec = applyvec; 42 pf->ops->view = view; 43 44 PetscFunctionReturn(0); 45 } 46 47 #undef __FUNCT__ 48 #define __FUNCT__ "PFDestroy" 49 /*@C 50 PFDestroy - Destroys PF context that was created with PFCreate(). 51 52 Collective on PF 53 54 Input Parameter: 55 . pf - the function context 56 57 Level: beginner 58 59 .keywords: PF, destroy 60 61 .seealso: PFCreate(), PFSet(), PFSetType() 62 @*/ 63 PetscErrorCode PFDestroy(PF *pf) 64 { 65 PetscErrorCode ierr; 66 PetscBool flg = PETSC_FALSE; 67 68 PetscFunctionBegin; 69 if (!*pf) PetscFunctionReturn(0); 70 PetscValidHeaderSpecific((*pf),PF_CLASSID,1); 71 if (--((PetscObject)(*pf))->refct > 0) PetscFunctionReturn(0); 72 73 ierr = PetscOptionsGetBool(((PetscObject)(*pf))->prefix,"-pf_view",&flg,PETSC_NULL);CHKERRQ(ierr); 74 if (flg) { 75 PetscViewer viewer; 76 ierr = PetscViewerASCIIGetStdout(((PetscObject)(*pf))->comm,&viewer);CHKERRQ(ierr); 77 ierr = PFView((*pf),viewer);CHKERRQ(ierr); 78 } 79 80 /* if memory was published with AMS then destroy it */ 81 ierr = PetscObjectDepublish((*pf));CHKERRQ(ierr); 82 83 if ((*pf)->ops->destroy) {ierr = (*(*pf)->ops->destroy)((*pf)->data);CHKERRQ(ierr);} 84 ierr = PetscHeaderDestroy(pf);CHKERRQ(ierr); 85 PetscFunctionReturn(0); 86 } 87 88 #undef __FUNCT__ 89 #define __FUNCT__ "PFCreate" 90 /*@C 91 PFCreate - Creates a mathematical function context. 92 93 Collective on MPI_Comm 94 95 Input Parameter: 96 + comm - MPI communicator 97 . dimin - dimension of the space you are mapping from 98 - dimout - dimension of the space you are mapping to 99 100 Output Parameter: 101 . pf - the function context 102 103 Level: developer 104 105 .keywords: PF, create, context 106 107 .seealso: PFSet(), PFApply(), PFDestroy(), PFApplyVec() 108 @*/ 109 PetscErrorCode PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf) 110 { 111 PF newpf; 112 PetscErrorCode ierr; 113 114 PetscFunctionBegin; 115 PetscValidPointer(pf,1); 116 *pf = PETSC_NULL; 117 #ifndef PETSC_USE_DYNAMIC_LIBRARIES 118 ierr = PFInitializePackage(PETSC_NULL);CHKERRQ(ierr); 119 #endif 120 121 ierr = PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_CLASSID,-1,"PF","Mathematical functions","Vec",comm,PFDestroy,PFView);CHKERRQ(ierr); 122 newpf->data = 0; 123 124 newpf->ops->destroy = 0; 125 newpf->ops->apply = 0; 126 newpf->ops->applyvec = 0; 127 newpf->ops->view = 0; 128 newpf->dimin = dimin; 129 newpf->dimout = dimout; 130 131 *pf = newpf; 132 PetscFunctionReturn(0); 133 134 } 135 136 /* -------------------------------------------------------------------------------*/ 137 138 #undef __FUNCT__ 139 #define __FUNCT__ "PFApplyVec" 140 /*@ 141 PFApplyVec - Applies the mathematical function to a vector 142 143 Collective on PF 144 145 Input Parameters: 146 + pf - the function context 147 - x - input vector (or PETSC_NULL for the vector (0,1, .... N-1) 148 149 Output Parameter: 150 . y - output vector 151 152 Level: beginner 153 154 .keywords: PF, apply 155 156 .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet() 157 @*/ 158 PetscErrorCode PFApplyVec(PF pf,Vec x,Vec y) 159 { 160 PetscErrorCode ierr; 161 PetscInt i,rstart,rend,n,p; 162 PetscBool nox = PETSC_FALSE; 163 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 166 PetscValidHeaderSpecific(y,VEC_CLASSID,3); 167 if (x) { 168 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 169 if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors"); 170 } else { 171 PetscScalar *xx; 172 PetscInt lsize; 173 174 ierr = VecGetLocalSize(y,&lsize);CHKERRQ(ierr); 175 lsize = pf->dimin*lsize/pf->dimout; 176 ierr = VecCreateMPI(((PetscObject)y)->comm,lsize,PETSC_DETERMINE,&x);CHKERRQ(ierr); 177 nox = PETSC_TRUE; 178 ierr = VecGetOwnershipRange(x,&rstart,&rend);CHKERRQ(ierr); 179 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 180 for (i=rstart; i<rend; i++) { 181 xx[i-rstart] = (PetscScalar)i; 182 } 183 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 184 } 185 186 ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr); 187 ierr = VecGetLocalSize(y,&p);CHKERRQ(ierr); 188 if ((pf->dimin*(n/pf->dimin)) != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local input vector length %D not divisible by dimin %D of function",n,pf->dimin); 189 if ((pf->dimout*(p/pf->dimout)) != p) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local output vector length %D not divisible by dimout %D of function",p,pf->dimout); 190 if ((n/pf->dimin) != (p/pf->dimout)) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local vector lengths %D %D are wrong for dimin and dimout %D %D of function",n,p,pf->dimin,pf->dimout); 191 192 if (pf->ops->applyvec) { 193 ierr = (*pf->ops->applyvec)(pf->data,x,y);CHKERRQ(ierr); 194 } else { 195 PetscScalar *xx,*yy; 196 197 ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr); 198 n = n/pf->dimin; 199 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 200 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 201 if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF"); 202 ierr = (*pf->ops->apply)(pf->data,n,xx,yy);CHKERRQ(ierr); 203 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 204 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 205 } 206 if (nox) { 207 ierr = VecDestroy(&x);CHKERRQ(ierr); 208 } 209 PetscFunctionReturn(0); 210 } 211 212 #undef __FUNCT__ 213 #define __FUNCT__ "PFApply" 214 /*@ 215 PFApply - Applies the mathematical function to an array of values. 216 217 Collective on PF 218 219 Input Parameters: 220 + pf - the function context 221 . n - number of pointwise function evaluations to perform, each pointwise function evaluation 222 is a function of dimin variables and computes dimout variables where dimin and dimout are defined 223 in the call to PFCreate() 224 - x - input array 225 226 Output Parameter: 227 . y - output array 228 229 Level: beginner 230 231 Notes: 232 233 .keywords: PF, apply 234 235 .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet() 236 @*/ 237 PetscErrorCode PFApply(PF pf,PetscInt n,const PetscScalar* x,PetscScalar* y) 238 { 239 PetscErrorCode ierr; 240 241 PetscFunctionBegin; 242 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 243 PetscValidScalarPointer(x,2); 244 PetscValidScalarPointer(y,3); 245 if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different arrays"); 246 if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF"); 247 248 ierr = (*pf->ops->apply)(pf->data,n,x,y);CHKERRQ(ierr); 249 PetscFunctionReturn(0); 250 } 251 252 #undef __FUNCT__ 253 #define __FUNCT__ "PFView" 254 /*@ 255 PFView - Prints information about a mathematical function 256 257 Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF 258 259 Input Parameters: 260 + PF - the PF context 261 - viewer - optional visualization context 262 263 Note: 264 The available visualization contexts include 265 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 266 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 267 output where only the first processor opens 268 the file. All other processors send their 269 data to the first processor to print. 270 271 The user can open an alternative visualization contexts with 272 PetscViewerASCIIOpen() (output to a specified file). 273 274 Level: developer 275 276 .keywords: PF, view 277 278 .seealso: PetscViewerCreate(), PetscViewerASCIIOpen() 279 @*/ 280 PetscErrorCode PFView(PF pf,PetscViewer viewer) 281 { 282 PetscErrorCode ierr; 283 PetscBool iascii; 284 PetscViewerFormat format; 285 286 PetscFunctionBegin; 287 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 288 if (!viewer) { 289 ierr = PetscViewerASCIIGetStdout(((PetscObject)pf)->comm,&viewer);CHKERRQ(ierr); 290 } 291 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 292 PetscCheckSameComm(pf,1,viewer,2); 293 294 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 295 if (iascii) { 296 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 297 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer,"PF Object");CHKERRQ(ierr); 298 if (pf->ops->view) { 299 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 300 ierr = (*pf->ops->view)(pf->data,viewer);CHKERRQ(ierr); 301 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 302 } 303 } else { 304 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name); 305 } 306 PetscFunctionReturn(0); 307 } 308 309 /*MC 310 PFRegisterDynamic - Adds a method to the mathematical function package. 311 312 Synopsis: 313 #include "petscpf.h" 314 PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF)) 315 316 Not collective 317 318 Input Parameters: 319 + name_solver - name of a new user-defined solver 320 . path - path (either absolute or relative) the library containing this solver 321 . name_create - name of routine to create method context 322 - routine_create - routine to create method context 323 324 Notes: 325 PFRegisterDynamic() may be called multiple times to add several user-defined functions 326 327 If dynamic libraries are used, then the fourth input argument (routine_create) 328 is ignored. 329 330 Sample usage: 331 .vb 332 PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib", 333 "MyFunctionCreate",MyFunctionSetCreate); 334 .ve 335 336 Then, your solver can be chosen with the procedural interface via 337 $ PFSetType(pf,"my_function") 338 or at runtime via the option 339 $ -pf_type my_function 340 341 Level: advanced 342 343 ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 344 occuring in pathname will be replaced with appropriate values. 345 346 .keywords: PF, register 347 348 .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister() 349 M*/ 350 351 #undef __FUNCT__ 352 #define __FUNCT__ "PFRegister" 353 PetscErrorCode PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*)) 354 { 355 PetscErrorCode ierr; 356 char fullname[PETSC_MAX_PATH_LEN]; 357 358 PetscFunctionBegin; 359 ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr); 360 ierr = PetscFListAdd(PETSC_COMM_WORLD,&PFList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr); 361 PetscFunctionReturn(0); 362 } 363 364 #undef __FUNCT__ 365 #define __FUNCT__ "PFGetType" 366 /*@C 367 PFGetType - Gets the PF method type and name (as a string) from the PF 368 context. 369 370 Not Collective 371 372 Input Parameter: 373 . pf - the function context 374 375 Output Parameter: 376 . type - name of function 377 378 Level: intermediate 379 380 .keywords: PF, get, method, name, type 381 382 .seealso: PFSetType() 383 384 @*/ 385 PetscErrorCode PFGetType(PF pf,PFType *type) 386 { 387 PetscFunctionBegin; 388 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 389 PetscValidPointer(type,2); 390 *type = ((PetscObject)pf)->type_name; 391 PetscFunctionReturn(0); 392 } 393 394 395 #undef __FUNCT__ 396 #define __FUNCT__ "PFSetType" 397 /*@C 398 PFSetType - Builds PF for a particular function 399 400 Collective on PF 401 402 Input Parameter: 403 + pf - the function context. 404 . type - a known method 405 - ctx - optional type dependent context 406 407 Options Database Key: 408 . -pf_type <type> - Sets PF type 409 410 411 Notes: 412 See "petsc/include/petscpf.h" for available methods (for instance, 413 PFCONSTANT) 414 415 Level: intermediate 416 417 .keywords: PF, set, method, type 418 419 .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DMDACreatePF() 420 421 @*/ 422 PetscErrorCode PFSetType(PF pf,PFType type,void *ctx) 423 { 424 PetscErrorCode ierr,(*r)(PF,void*); 425 PetscBool match; 426 427 PetscFunctionBegin; 428 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 429 PetscValidCharPointer(type,2); 430 431 ierr = PetscObjectTypeCompare((PetscObject)pf,type,&match);CHKERRQ(ierr); 432 if (match) PetscFunctionReturn(0); 433 434 if (pf->ops->destroy) {ierr = (*pf->ops->destroy)(pf);CHKERRQ(ierr);} 435 pf->data = 0; 436 437 /* Determine the PFCreateXXX routine for a particular function */ 438 ierr = PetscFListFind(((PetscObject)pf)->comm,PFList,type,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr); 439 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type); 440 pf->ops->destroy = 0; 441 pf->ops->view = 0; 442 pf->ops->apply = 0; 443 pf->ops->applyvec = 0; 444 445 /* Call the PFCreateXXX routine for this particular function */ 446 ierr = (*r)(pf,ctx);CHKERRQ(ierr); 447 448 ierr = PetscObjectChangeTypeName((PetscObject)pf,type);CHKERRQ(ierr); 449 PetscFunctionReturn(0); 450 } 451 452 #undef __FUNCT__ 453 #define __FUNCT__ "PFSetFromOptions" 454 /*@ 455 PFSetFromOptions - Sets PF options from the options database. 456 457 Collective on PF 458 459 Input Parameters: 460 . pf - the mathematical function context 461 462 Options Database Keys: 463 464 Notes: 465 To see all options, run your program with the -help option 466 or consult the users manual. 467 468 Level: intermediate 469 470 .keywords: PF, set, from, options, database 471 472 .seealso: 473 @*/ 474 PetscErrorCode PFSetFromOptions(PF pf) 475 { 476 PetscErrorCode ierr; 477 char type[256]; 478 PetscBool flg; 479 480 PetscFunctionBegin; 481 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 482 483 ierr = PetscObjectOptionsBegin((PetscObject)pf);CHKERRQ(ierr); 484 ierr = PetscOptionsList("-pf_type","Type of function","PFSetType",PFList,0,type,256,&flg);CHKERRQ(ierr); 485 if (flg) { 486 ierr = PFSetType(pf,type,PETSC_NULL);CHKERRQ(ierr); 487 } 488 if (pf->ops->setfromoptions) { 489 ierr = (*pf->ops->setfromoptions)(pf);CHKERRQ(ierr); 490 } 491 492 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 493 ierr = PetscObjectProcessOptionsHandlers((PetscObject)pf);CHKERRQ(ierr); 494 ierr = PetscOptionsEnd();CHKERRQ(ierr); 495 496 PetscFunctionReturn(0); 497 } 498 499 static PetscBool PFPackageInitialized = PETSC_FALSE; 500 #undef __FUNCT__ 501 #define __FUNCT__ "PFFinalizePackage" 502 /*@C 503 PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is 504 called from PetscFinalize(). 505 506 Level: developer 507 508 .keywords: Petsc, destroy, package, mathematica 509 .seealso: PetscFinalize() 510 @*/ 511 PetscErrorCode PFFinalizePackage(void) 512 { 513 PetscFunctionBegin; 514 PFPackageInitialized = PETSC_FALSE; 515 PFList = PETSC_NULL; 516 PFRegisterAllCalled = PETSC_FALSE; 517 PetscFunctionReturn(0); 518 } 519 520 #undef __FUNCT__ 521 #define __FUNCT__ "PFInitializePackage" 522 /*@C 523 PFInitializePackage - This function initializes everything in the PF package. It is called 524 from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate() 525 when using static libraries. 526 527 Input Parameter: 528 . path - The dynamic library path, or PETSC_NULL 529 530 Level: developer 531 532 .keywords: Vec, initialize, package 533 .seealso: PetscInitialize() 534 @*/ 535 PetscErrorCode PFInitializePackage(const char path[]) 536 { 537 char logList[256]; 538 char *className; 539 PetscBool opt; 540 PetscErrorCode ierr; 541 542 PetscFunctionBegin; 543 if (PFPackageInitialized) PetscFunctionReturn(0); 544 PFPackageInitialized = PETSC_TRUE; 545 /* Register Classes */ 546 ierr = PetscClassIdRegister("PointFunction",&PF_CLASSID);CHKERRQ(ierr); 547 /* Register Constructors */ 548 ierr = PFRegisterAll(path);CHKERRQ(ierr); 549 /* Process info exclusions */ 550 ierr = PetscOptionsGetString(PETSC_NULL, "-info_exclude", logList, 256, &opt);CHKERRQ(ierr); 551 if (opt) { 552 ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr); 553 if (className) { 554 ierr = PetscInfoDeactivateClass(PF_CLASSID);CHKERRQ(ierr); 555 } 556 } 557 /* Process summary exclusions */ 558 ierr = PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);CHKERRQ(ierr); 559 if (opt) { 560 ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr); 561 if (className) { 562 ierr = PetscLogEventDeactivateClass(PF_CLASSID);CHKERRQ(ierr); 563 } 564 } 565 ierr = PetscRegisterFinalize(PFFinalizePackage);CHKERRQ(ierr); 566 PetscFunctionReturn(0); 567 } 568 569 570 571 572 573 574 575 576 577