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 $ PFSetType(pf, "my_function") 292 or at runtime via the option 293 $ -pf_type my_function 294 295 Level: advanced 296 297 Note: 298 `PFRegister()` may be called multiple times to add several user-defined functions 299 300 .seealso: `PF`, `PFRegisterAll()`, `PFRegisterDestroy()` 301 @*/ 302 PetscErrorCode PFRegister(const char sname[], PetscErrorCode (*function)(PF, void *)) 303 { 304 PetscFunctionBegin; 305 PetscCall(PFInitializePackage()); 306 PetscCall(PetscFunctionListAdd(&PFList, sname, function)); 307 PetscFunctionReturn(PETSC_SUCCESS); 308 } 309 310 /*@ 311 PFGetType - Gets the `PFType` name (as a string) from the `PF` 312 context. 313 314 Not Collective 315 316 Input Parameter: 317 . pf - the function context 318 319 Output Parameter: 320 . type - name of function 321 322 Level: intermediate 323 324 .seealso: `PF`, `PFSetType()` 325 @*/ 326 PetscErrorCode PFGetType(PF pf, PFType *type) 327 { 328 PetscFunctionBegin; 329 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 330 PetscAssertPointer(type, 2); 331 *type = ((PetscObject)pf)->type_name; 332 PetscFunctionReturn(PETSC_SUCCESS); 333 } 334 335 /*@ 336 PFSetType - Builds `PF` for a particular function 337 338 Collective 339 340 Input Parameters: 341 + pf - the function context. 342 . type - a known method 343 - ctx - optional type dependent context 344 345 Options Database Key: 346 . -pf_type <type> - Sets PF type 347 348 Level: intermediate 349 350 Note: 351 See "petsc/include/petscpf.h" for available methods (for instance, `PFCONSTANT`) 352 353 .seealso: `PF`, `PFSet()`, `PFRegister()`, `PFCreate()`, `DMDACreatePF()` 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 PetscAssertPointer(type, 2); 363 364 PetscCall(PetscObjectTypeCompare((PetscObject)pf, type, &match)); 365 if (match) PetscFunctionReturn(PETSC_SUCCESS); 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, PetscObjectComm((PetscObject)pf), 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(PETSC_SUCCESS); 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 Level: intermediate 394 395 Notes: 396 To see all options, run your program with the -help option 397 or consult the users manual. 398 399 .seealso: `PF` 400 @*/ 401 PetscErrorCode PFSetFromOptions(PF pf) 402 { 403 char type[256]; 404 PetscBool flg; 405 406 PetscFunctionBegin; 407 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 408 409 PetscObjectOptionsBegin((PetscObject)pf); 410 PetscCall(PetscOptionsFList("-pf_type", "Type of function", "PFSetType", PFList, NULL, type, 256, &flg)); 411 if (flg) PetscCall(PFSetType(pf, type, NULL)); 412 PetscTryTypeMethod(pf, setfromoptions, PetscOptionsObject); 413 414 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 415 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pf, PetscOptionsObject)); 416 PetscOptionsEnd(); 417 PetscFunctionReturn(PETSC_SUCCESS); 418 } 419 420 static PetscBool PFPackageInitialized = PETSC_FALSE; 421 422 /*@C 423 PFFinalizePackage - This function destroys everything in the PETSc `PF` package. It is 424 called from `PetscFinalize()`. 425 426 Level: developer 427 428 .seealso: `PF`, `PetscFinalize()` 429 @*/ 430 PetscErrorCode PFFinalizePackage(void) 431 { 432 PetscFunctionBegin; 433 PetscCall(PetscFunctionListDestroy(&PFList)); 434 PFPackageInitialized = PETSC_FALSE; 435 PFRegisterAllCalled = PETSC_FALSE; 436 PetscFunctionReturn(PETSC_SUCCESS); 437 } 438 439 /*@C 440 PFInitializePackage - This function initializes everything in the `PF` package. It is called 441 from PetscDLLibraryRegister_petscvec() when using dynamic libraries, and on the first call to `PFCreate()` 442 when using shared or static libraries. 443 444 Level: developer 445 446 .seealso: `PF`, `PetscInitialize()` 447 @*/ 448 PetscErrorCode PFInitializePackage(void) 449 { 450 char logList[256]; 451 PetscBool opt, pkg; 452 453 PetscFunctionBegin; 454 if (PFPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS); 455 PFPackageInitialized = PETSC_TRUE; 456 /* Register Classes */ 457 PetscCall(PetscClassIdRegister("PointFunction", &PF_CLASSID)); 458 /* Register Constructors */ 459 PetscCall(PFRegisterAll()); 460 /* Process Info */ 461 { 462 PetscClassId classids[1]; 463 464 classids[0] = PF_CLASSID; 465 PetscCall(PetscInfoProcessClass("pf", 1, classids)); 466 } 467 /* Process summary exclusions */ 468 PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt)); 469 if (opt) { 470 PetscCall(PetscStrInList("pf", logList, ',', &pkg)); 471 if (pkg) PetscCall(PetscLogEventExcludeClass(PF_CLASSID)); 472 } 473 /* Register package finalizer */ 474 PetscCall(PetscRegisterFinalize(PFFinalizePackage)); 475 PetscFunctionReturn(PETSC_SUCCESS); 476 } 477