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 PetscCall((*pf->ops->apply)(pf->data,n,xx,yy)); 166 PetscCall(VecRestoreArray(x,&xx)); 167 PetscCall(VecRestoreArray(y,&yy)); 168 } 169 if (nox) { 170 PetscCall(VecDestroy(&x)); 171 } 172 PetscFunctionReturn(0); 173 } 174 175 /*@ 176 PFApply - Applies the mathematical function to an array of values. 177 178 Collective on PF 179 180 Input Parameters: 181 + pf - the function context 182 . n - number of pointwise function evaluations to perform, each pointwise function evaluation 183 is a function of dimin variables and computes dimout variables where dimin and dimout are defined 184 in the call to PFCreate() 185 - x - input array 186 187 Output Parameter: 188 . y - output array 189 190 Level: beginner 191 192 Notes: 193 194 .seealso: `PFApplyVec()`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFSet()` 195 @*/ 196 PetscErrorCode PFApply(PF pf,PetscInt n,const PetscScalar *x,PetscScalar *y) 197 { 198 PetscFunctionBegin; 199 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 200 PetscValidScalarPointer(x,3); 201 PetscValidScalarPointer(y,4); 202 PetscCheck(x != y,PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different arrays"); 203 204 PetscCall((*pf->ops->apply)(pf->data,n,x,y)); 205 PetscFunctionReturn(0); 206 } 207 208 /*@C 209 PFViewFromOptions - View from Options 210 211 Collective on PF 212 213 Input Parameters: 214 + A - the PF context 215 . obj - Optional object 216 - name - command line option 217 218 Level: intermediate 219 .seealso: `PF`, `PFView`, `PetscObjectViewFromOptions()`, `PFCreate()` 220 @*/ 221 PetscErrorCode PFViewFromOptions(PF A,PetscObject obj,const char name[]) 222 { 223 PetscFunctionBegin; 224 PetscValidHeaderSpecific(A,PF_CLASSID,1); 225 PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name)); 226 PetscFunctionReturn(0); 227 } 228 229 /*@ 230 PFView - Prints information about a mathematical function 231 232 Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF 233 234 Input Parameters: 235 + PF - the PF context 236 - viewer - optional visualization context 237 238 Note: 239 The available visualization contexts include 240 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 241 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 242 output where only the first processor opens 243 the file. All other processors send their 244 data to the first processor to print. 245 246 The user can open an alternative visualization contexts with 247 PetscViewerASCIIOpen() (output to a specified file). 248 249 Level: developer 250 251 .seealso: `PetscViewerCreate()`, `PetscViewerASCIIOpen()` 252 @*/ 253 PetscErrorCode PFView(PF pf,PetscViewer viewer) 254 { 255 PetscBool iascii; 256 PetscViewerFormat format; 257 258 PetscFunctionBegin; 259 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 260 if (!viewer) { 261 PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf),&viewer)); 262 } 263 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 264 PetscCheckSameComm(pf,1,viewer,2); 265 266 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 267 if (iascii) { 268 PetscCall(PetscViewerGetFormat(viewer,&format)); 269 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer)); 270 if (pf->ops->view) { 271 PetscCall(PetscViewerASCIIPushTab(viewer)); 272 PetscCall((*pf->ops->view)(pf->data,viewer)); 273 PetscCall(PetscViewerASCIIPopTab(viewer)); 274 } 275 } 276 PetscFunctionReturn(0); 277 } 278 279 /*@C 280 PFRegister - Adds a method to the mathematical function package. 281 282 Not collective 283 284 Input Parameters: 285 + name_solver - name of a new user-defined solver 286 - routine_create - routine to create method context 287 288 Notes: 289 PFRegister() may be called multiple times to add several user-defined functions 290 291 Sample usage: 292 .vb 293 PFRegister("my_function",MyFunctionSetCreate); 294 .ve 295 296 Then, your solver can be chosen with the procedural interface via 297 $ PFSetType(pf,"my_function") 298 or at runtime via the option 299 $ -pf_type my_function 300 301 Level: advanced 302 303 .seealso: `PFRegisterAll()`, `PFRegisterDestroy()`, `PFRegister()` 304 @*/ 305 PetscErrorCode PFRegister(const char sname[],PetscErrorCode (*function)(PF,void*)) 306 { 307 PetscFunctionBegin; 308 PetscCall(PFInitializePackage()); 309 PetscCall(PetscFunctionListAdd(&PFList,sname,function)); 310 PetscFunctionReturn(0); 311 } 312 313 /*@C 314 PFGetType - Gets the PF method type and name (as a string) from the PF 315 context. 316 317 Not Collective 318 319 Input Parameter: 320 . pf - the function context 321 322 Output Parameter: 323 . type - name of function 324 325 Level: intermediate 326 327 .seealso: `PFSetType()` 328 329 @*/ 330 PetscErrorCode PFGetType(PF pf,PFType *type) 331 { 332 PetscFunctionBegin; 333 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 334 PetscValidPointer(type,2); 335 *type = ((PetscObject)pf)->type_name; 336 PetscFunctionReturn(0); 337 } 338 339 /*@C 340 PFSetType - Builds PF for a particular function 341 342 Collective on PF 343 344 Input Parameters: 345 + pf - the function context. 346 . type - a known method 347 - ctx - optional type dependent context 348 349 Options Database Key: 350 . -pf_type <type> - Sets PF type 351 352 Notes: 353 See "petsc/include/petscpf.h" for available methods (for instance, 354 PFCONSTANT) 355 356 Level: intermediate 357 358 .seealso: `PFSet()`, `PFRegister()`, `PFCreate()`, `DMDACreatePF()` 359 360 @*/ 361 PetscErrorCode PFSetType(PF pf,PFType type,void *ctx) 362 { 363 PetscBool match; 364 PetscErrorCode (*r)(PF,void*); 365 366 PetscFunctionBegin; 367 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 368 PetscValidCharPointer(type,2); 369 370 PetscCall(PetscObjectTypeCompare((PetscObject)pf,type,&match)); 371 if (match) PetscFunctionReturn(0); 372 373 if (pf->ops->destroy) PetscCall((*pf->ops->destroy)(pf)); 374 pf->data = NULL; 375 376 /* Determine the PFCreateXXX routine for a particular function */ 377 PetscCall(PetscFunctionListFind(PFList,type,&r)); 378 PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type); 379 pf->ops->destroy = NULL; 380 pf->ops->view = NULL; 381 pf->ops->apply = NULL; 382 pf->ops->applyvec = NULL; 383 384 /* Call the PFCreateXXX routine for this particular function */ 385 PetscCall((*r)(pf,ctx)); 386 387 PetscCall(PetscObjectChangeTypeName((PetscObject)pf,type)); 388 PetscFunctionReturn(0); 389 } 390 391 /*@ 392 PFSetFromOptions - Sets PF options from the options database. 393 394 Collective on PF 395 396 Input Parameters: 397 . pf - the mathematical function context 398 399 Options Database Keys: 400 401 Notes: 402 To see all options, run your program with the -help option 403 or consult the users manual. 404 405 Level: intermediate 406 407 .seealso: 408 @*/ 409 PetscErrorCode PFSetFromOptions(PF pf) 410 { 411 char type[256]; 412 PetscBool flg; 413 414 PetscFunctionBegin; 415 PetscValidHeaderSpecific(pf,PF_CLASSID,1); 416 417 PetscObjectOptionsBegin((PetscObject)pf); 418 PetscCall(PetscOptionsFList("-pf_type","Type of function","PFSetType",PFList,NULL,type,256,&flg)); 419 if (flg) PetscCall(PFSetType(pf,type,NULL)); 420 if (pf->ops->setfromoptions) PetscCall((*pf->ops->setfromoptions)(PetscOptionsObject,pf)); 421 422 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 423 PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pf)); 424 PetscOptionsEnd(); 425 PetscFunctionReturn(0); 426 } 427 428 static PetscBool PFPackageInitialized = PETSC_FALSE; 429 /*@C 430 PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is 431 called from PetscFinalize(). 432 433 Level: developer 434 435 .seealso: `PetscFinalize()` 436 @*/ 437 PetscErrorCode PFFinalizePackage(void) 438 { 439 PetscFunctionBegin; 440 PetscCall(PetscFunctionListDestroy(&PFList)); 441 PFPackageInitialized = PETSC_FALSE; 442 PFRegisterAllCalled = PETSC_FALSE; 443 PetscFunctionReturn(0); 444 } 445 446 /*@C 447 PFInitializePackage - This function initializes everything in the PF package. It is called 448 from PetscDLLibraryRegister_petscvec() when using dynamic libraries, and on the first call to PFCreate() 449 when using shared or static libraries. 450 451 Level: developer 452 453 .seealso: `PetscInitialize()` 454 @*/ 455 PetscErrorCode PFInitializePackage(void) 456 { 457 char logList[256]; 458 PetscBool opt,pkg; 459 460 PetscFunctionBegin; 461 if (PFPackageInitialized) PetscFunctionReturn(0); 462 PFPackageInitialized = PETSC_TRUE; 463 /* Register Classes */ 464 PetscCall(PetscClassIdRegister("PointFunction",&PF_CLASSID)); 465 /* Register Constructors */ 466 PetscCall(PFRegisterAll()); 467 /* Process Info */ 468 { 469 PetscClassId classids[1]; 470 471 classids[0] = PF_CLASSID; 472 PetscCall(PetscInfoProcessClass("pf", 1, classids)); 473 } 474 /* Process summary exclusions */ 475 PetscCall(PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt)); 476 if (opt) { 477 PetscCall(PetscStrInList("pf",logList,',',&pkg)); 478 if (pkg) PetscCall(PetscLogEventExcludeClass(PF_CLASSID)); 479 } 480 /* Register package finalizer */ 481 PetscCall(PetscRegisterFinalize(PFFinalizePackage)); 482 PetscFunctionReturn(0); 483 } 484