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