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