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