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