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