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