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