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 PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF)) 314 315 Not collective 316 317 Input Parameters: 318 + name_solver - name of a new user-defined solver 319 . path - path (either absolute or relative) the library containing this solver 320 . name_create - name of routine to create method context 321 - routine_create - routine to create method context 322 323 Notes: 324 PFRegisterDynamic() may be called multiple times to add several user-defined functions 325 326 If dynamic libraries are used, then the fourth input argument (routine_create) 327 is ignored. 328 329 Sample usage: 330 .vb 331 PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib", 332 "MyFunctionCreate",MyFunctionSetCreate); 333 .ve 334 335 Then, your solver can be chosen with the procedural interface via 336 $ PFSetType(pf,"my_function") 337 or at runtime via the option 338 $ -pf_type my_function 339 340 Level: advanced 341 342 ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 343 occuring in pathname will be replaced with appropriate values. 344 345 .keywords: PF, register 346 347 .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister() 348 M*/ 349 350 #undef __FUNCT__ 351 #define __FUNCT__ "PFRegister" 352 PetscErrorCode PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*)) 353 { 354 PetscErrorCode ierr; 355 char fullname[PETSC_MAX_PATH_LEN]; 356 357 PetscFunctionBegin; 358 ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr); 359 ierr = PetscFListAdd(&PFList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr); 360 PetscFunctionReturn(0); 361 } 362 363 #undef __FUNCT__ 364 #define __FUNCT__ "PFGetType" 365 /*@C 366 PFGetType - Gets the PF method type and name (as a string) from the PF 367 context. 368 369 Not Collective 370 371 Input Parameter: 372 . pf - the function context 373 374 Output Parameter: 375 . type - name of function 376 377 Level: intermediate 378 379 .keywords: PF, get, method, name, type 380 381 .seealso: PFSetType() 382 383 @*/ 384 PetscErrorCode PFGetType(PF pf,PFType *type) 385 { 386 PetscFunctionBegin; 387 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 388 PetscValidPointer(type,2); 389 *type = ((PetscObject)pf)->type_name; 390 PetscFunctionReturn(0); 391 } 392 393 394 #undef __FUNCT__ 395 #define __FUNCT__ "PFSetType" 396 /*@C 397 PFSetType - Builds PF for a particular function 398 399 Collective on PF 400 401 Input Parameter: 402 + pf - the function context. 403 . type - a known method 404 - ctx - optional type dependent context 405 406 Options Database Key: 407 . -pf_type <type> - Sets PF type 408 409 410 Notes: 411 See "petsc/include/petscpf.h" for available methods (for instance, 412 PFCONSTANT) 413 414 Level: intermediate 415 416 .keywords: PF, set, method, type 417 418 .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DMDACreatePF() 419 420 @*/ 421 PetscErrorCode PFSetType(PF pf,PFType type,void *ctx) 422 { 423 PetscErrorCode ierr,(*r)(PF,void*); 424 PetscBool match; 425 426 PetscFunctionBegin; 427 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 428 PetscValidCharPointer(type,2); 429 430 ierr = PetscObjectTypeCompare((PetscObject)pf,type,&match);CHKERRQ(ierr); 431 if (match) PetscFunctionReturn(0); 432 433 if (pf->ops->destroy) {ierr = (*pf->ops->destroy)(pf);CHKERRQ(ierr);} 434 pf->data = 0; 435 436 /* Determine the PFCreateXXX routine for a particular function */ 437 ierr = PetscFListFind(PFList,((PetscObject)pf)->comm,type,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr); 438 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type); 439 pf->ops->destroy = 0; 440 pf->ops->view = 0; 441 pf->ops->apply = 0; 442 pf->ops->applyvec = 0; 443 444 /* Call the PFCreateXXX routine for this particular function */ 445 ierr = (*r)(pf,ctx);CHKERRQ(ierr); 446 447 ierr = PetscObjectChangeTypeName((PetscObject)pf,type);CHKERRQ(ierr); 448 PetscFunctionReturn(0); 449 } 450 451 #undef __FUNCT__ 452 #define __FUNCT__ "PFSetFromOptions" 453 /*@ 454 PFSetFromOptions - Sets PF options from the options database. 455 456 Collective on PF 457 458 Input Parameters: 459 . pf - the mathematical function context 460 461 Options Database Keys: 462 463 Notes: 464 To see all options, run your program with the -help option 465 or consult the users manual. 466 467 Level: intermediate 468 469 .keywords: PF, set, from, options, database 470 471 .seealso: 472 @*/ 473 PetscErrorCode PFSetFromOptions(PF pf) 474 { 475 PetscErrorCode ierr; 476 char type[256]; 477 PetscBool flg; 478 479 PetscFunctionBegin; 480 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 481 482 ierr = PetscObjectOptionsBegin((PetscObject)pf);CHKERRQ(ierr); 483 ierr = PetscOptionsList("-pf_type","Type of function","PFSetType",PFList,0,type,256,&flg);CHKERRQ(ierr); 484 if (flg) { 485 ierr = PFSetType(pf,type,PETSC_NULL);CHKERRQ(ierr); 486 } 487 if (pf->ops->setfromoptions) { 488 ierr = (*pf->ops->setfromoptions)(pf);CHKERRQ(ierr); 489 } 490 491 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 492 ierr = PetscObjectProcessOptionsHandlers((PetscObject)pf);CHKERRQ(ierr); 493 ierr = PetscOptionsEnd();CHKERRQ(ierr); 494 495 PetscFunctionReturn(0); 496 } 497 498 static PetscBool PFPackageInitialized = PETSC_FALSE; 499 #undef __FUNCT__ 500 #define __FUNCT__ "PFFinalizePackage" 501 /*@C 502 PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is 503 called from PetscFinalize(). 504 505 Level: developer 506 507 .keywords: Petsc, destroy, package, mathematica 508 .seealso: PetscFinalize() 509 @*/ 510 PetscErrorCode PFFinalizePackage(void) 511 { 512 PetscFunctionBegin; 513 PFPackageInitialized = PETSC_FALSE; 514 PFList = PETSC_NULL; 515 PFRegisterAllCalled = PETSC_FALSE; 516 PetscFunctionReturn(0); 517 } 518 519 #undef __FUNCT__ 520 #define __FUNCT__ "PFInitializePackage" 521 /*@C 522 PFInitializePackage - This function initializes everything in the PF package. It is called 523 from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate() 524 when using static libraries. 525 526 Input Parameter: 527 . path - The dynamic library path, or PETSC_NULL 528 529 Level: developer 530 531 .keywords: Vec, initialize, package 532 .seealso: PetscInitialize() 533 @*/ 534 PetscErrorCode PFInitializePackage(const char path[]) 535 { 536 char logList[256]; 537 char *className; 538 PetscBool opt; 539 PetscErrorCode ierr; 540 541 PetscFunctionBegin; 542 if (PFPackageInitialized) PetscFunctionReturn(0); 543 PFPackageInitialized = PETSC_TRUE; 544 /* Register Classes */ 545 ierr = PetscClassIdRegister("PointFunction",&PF_CLASSID);CHKERRQ(ierr); 546 /* Register Constructors */ 547 ierr = PFRegisterAll(path);CHKERRQ(ierr); 548 /* Process info exclusions */ 549 ierr = PetscOptionsGetString(PETSC_NULL, "-info_exclude", logList, 256, &opt);CHKERRQ(ierr); 550 if (opt) { 551 ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr); 552 if (className) { 553 ierr = PetscInfoDeactivateClass(PF_CLASSID);CHKERRQ(ierr); 554 } 555 } 556 /* Process summary exclusions */ 557 ierr = PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);CHKERRQ(ierr); 558 if (opt) { 559 ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr); 560 if (className) { 561 ierr = PetscLogEventDeactivateClass(PF_CLASSID);CHKERRQ(ierr); 562 } 563 } 564 ierr = PetscRegisterFinalize(PFFinalizePackage);CHKERRQ(ierr); 565 PetscFunctionReturn(0); 566 } 567 568 569 570 571 572 573 574 575 576