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