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 PetscCall(PFViewFromOptions(*pf,NULL,"-pf_view")); 59 /* if memory was published with SAWs then destroy it */ 60 PetscCall(PetscObjectSAWsViewOff((PetscObject)*pf)); 61 62 if ((*pf)->ops->destroy) PetscCall((*(*pf)->ops->destroy)((*pf)->data)); 63 PetscCall(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 PetscCall(PFInitializePackage()); 92 93 PetscCall(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 PetscCheck(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 PetscCall(VecGetLocalSize(y,&lsize)); 141 lsize = pf->dimin*lsize/pf->dimout; 142 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)y),lsize,PETSC_DETERMINE,&x)); 143 nox = PETSC_TRUE; 144 PetscCall(VecGetOwnershipRange(x,&rstart,&rend)); 145 PetscCall(VecGetArray(x,&xx)); 146 for (i=rstart; i<rend; i++) xx[i-rstart] = (PetscScalar)i; 147 PetscCall(VecRestoreArray(x,&xx)); 148 } 149 150 PetscCall(VecGetLocalSize(x,&n)); 151 PetscCall(VecGetLocalSize(y,&p)); 152 PetscCheck((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 PetscCheck((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 PetscCheck((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 PetscCall((*pf->ops->applyvec)(pf->data,x,y)); 158 } else { 159 PetscScalar *xx,*yy; 160 161 PetscCall(VecGetLocalSize(x,&n)); 162 n = n/pf->dimin; 163 PetscCall(VecGetArray(x,&xx)); 164 PetscCall(VecGetArray(y,&yy)); 165 PetscCheck(pf->ops->apply,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF"); 166 PetscCall((*pf->ops->apply)(pf->data,n,xx,yy)); 167 PetscCall(VecRestoreArray(x,&xx)); 168 PetscCall(VecRestoreArray(y,&yy)); 169 } 170 if (nox) { 171 PetscCall(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 PetscCheck(x != y,PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different arrays"); 204 PetscCheck(pf->ops->apply,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF"); 205 206 PetscCall((*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 PetscCall(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 PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf),&viewer)); 264 } 265 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 266 PetscCheckSameComm(pf,1,viewer,2); 267 268 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 269 if (iascii) { 270 PetscCall(PetscViewerGetFormat(viewer,&format)); 271 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer)); 272 if (pf->ops->view) { 273 PetscCall(PetscViewerASCIIPushTab(viewer)); 274 PetscCall((*pf->ops->view)(pf->data,viewer)); 275 PetscCall(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 PetscCall(PFInitializePackage()); 311 PetscCall(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 PetscCall(PetscObjectTypeCompare((PetscObject)pf,type,&match)); 373 if (match) PetscFunctionReturn(0); 374 375 if (pf->ops->destroy) PetscCall((*pf->ops->destroy)(pf)); 376 pf->data = NULL; 377 378 /* Determine the PFCreateXXX routine for a particular function */ 379 PetscCall(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 PetscCall((*r)(pf,ctx)); 388 389 PetscCall(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 char type[256]; 414 PetscBool flg; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 418 419 PetscObjectOptionsBegin((PetscObject)pf); 420 PetscCall(PetscOptionsFList("-pf_type","Type of function","PFSetType",PFList,NULL,type,256,&flg)); 421 if (flg) { 422 PetscCall(PFSetType(pf,type,NULL)); 423 } 424 if (pf->ops->setfromoptions) { 425 PetscCall((*pf->ops->setfromoptions)(PetscOptionsObject,pf)); 426 } 427 428 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 429 PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pf)); 430 PetscOptionsEnd(); 431 PetscFunctionReturn(0); 432 } 433 434 static PetscBool PFPackageInitialized = PETSC_FALSE; 435 /*@C 436 PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is 437 called from PetscFinalize(). 438 439 Level: developer 440 441 .seealso: `PetscFinalize()` 442 @*/ 443 PetscErrorCode PFFinalizePackage(void) 444 { 445 PetscFunctionBegin; 446 PetscCall(PetscFunctionListDestroy(&PFList)); 447 PFPackageInitialized = PETSC_FALSE; 448 PFRegisterAllCalled = PETSC_FALSE; 449 PetscFunctionReturn(0); 450 } 451 452 /*@C 453 PFInitializePackage - This function initializes everything in the PF package. It is called 454 from PetscDLLibraryRegister_petscvec() when using dynamic libraries, and on the first call to PFCreate() 455 when using shared or static libraries. 456 457 Level: developer 458 459 .seealso: `PetscInitialize()` 460 @*/ 461 PetscErrorCode PFInitializePackage(void) 462 { 463 char logList[256]; 464 PetscBool opt,pkg; 465 466 PetscFunctionBegin; 467 if (PFPackageInitialized) PetscFunctionReturn(0); 468 PFPackageInitialized = PETSC_TRUE; 469 /* Register Classes */ 470 PetscCall(PetscClassIdRegister("PointFunction",&PF_CLASSID)); 471 /* Register Constructors */ 472 PetscCall(PFRegisterAll()); 473 /* Process Info */ 474 { 475 PetscClassId classids[1]; 476 477 classids[0] = PF_CLASSID; 478 PetscCall(PetscInfoProcessClass("pf", 1, classids)); 479 } 480 /* Process summary exclusions */ 481 PetscCall(PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt)); 482 if (opt) { 483 PetscCall(PetscStrInList("pf",logList,',',&pkg)); 484 if (pkg) PetscCall(PetscLogEventExcludeClass(PF_CLASSID)); 485 } 486 /* Register package finalizer */ 487 PetscCall(PetscRegisterFinalize(PFFinalizePackage)); 488 PetscFunctionReturn(0); 489 } 490