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