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