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 Notes: 189 190 .seealso: `PF`, `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(PETSC_SUCCESS); 202 } 203 204 /*@C 205 PFViewFromOptions - View a `PF` based on options set in the options database 206 207 Collective 208 209 Input Parameters: 210 + A - the `PF` context 211 . obj - Optional object that provides the prefix used to search the options database 212 - name - command line option 213 214 Level: intermediate 215 216 Note: 217 See `PetscObjectViewFromOptions()` for the variety of viewer options available 218 219 .seealso: `PF`, `PFView`, `PetscObjectViewFromOptions()`, `PFCreate()` 220 @*/ 221 PetscErrorCode PFViewFromOptions(PF A, PetscObject obj, const char name[]) 222 { 223 PetscFunctionBegin; 224 PetscValidHeaderSpecific(A, PF_CLASSID, 1); 225 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 226 PetscFunctionReturn(PETSC_SUCCESS); 227 } 228 229 /*@ 230 PFView - Prints information about a mathematical function 231 232 Collective unless `viewer` is `PETSC_VIEWER_STDOUT_SELF` 233 234 Input Parameters: 235 + PF - the `PF` context 236 - viewer - optional visualization context 237 238 Level: developer 239 240 Note: 241 The available visualization contexts include 242 + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 243 - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 244 output where only the first processor opens 245 the file. All other processors send their 246 data to the first processor to print. 247 248 The user can open an alternative visualization contexts with 249 `PetscViewerASCIIOpen()` (output to a specified file). 250 251 .seealso: `PF`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()` 252 @*/ 253 PetscErrorCode PFView(PF pf, PetscViewer viewer) 254 { 255 PetscBool iascii; 256 PetscViewerFormat format; 257 258 PetscFunctionBegin; 259 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 260 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf), &viewer)); 261 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 262 PetscCheckSameComm(pf, 1, viewer, 2); 263 264 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 265 if (iascii) { 266 PetscCall(PetscViewerGetFormat(viewer, &format)); 267 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pf, viewer)); 268 if (pf->ops->view) { 269 PetscCall(PetscViewerASCIIPushTab(viewer)); 270 PetscCall((*pf->ops->view)(pf->data, viewer)); 271 PetscCall(PetscViewerASCIIPopTab(viewer)); 272 } 273 } 274 PetscFunctionReturn(PETSC_SUCCESS); 275 } 276 277 /*@C 278 PFRegister - Adds a method to the mathematical function package. 279 280 Not Collective 281 282 Input Parameters: 283 + sname - name of a new user-defined solver 284 - function - routine to create method context 285 286 Sample usage: 287 .vb 288 PFRegister("my_function",MyFunctionSetCreate); 289 .ve 290 291 Then, your solver can be chosen with the procedural interface via 292 $ PFSetType(pf,"my_function") 293 or at runtime via the option 294 $ -pf_type my_function 295 296 Level: advanced 297 298 Note: 299 `PFRegister()` may be called multiple times to add several user-defined functions 300 301 .seealso: `PF`, `PFRegisterAll()`, `PFRegisterDestroy()`, `PFRegister()` 302 @*/ 303 PetscErrorCode PFRegister(const char sname[], PetscErrorCode (*function)(PF, void *)) 304 { 305 PetscFunctionBegin; 306 PetscCall(PFInitializePackage()); 307 PetscCall(PetscFunctionListAdd(&PFList, sname, function)); 308 PetscFunctionReturn(PETSC_SUCCESS); 309 } 310 311 /*@C 312 PFGetType - Gets the `PFType` name (as a string) from the `PF` 313 context. 314 315 Not Collective 316 317 Input Parameter: 318 . pf - the function context 319 320 Output Parameter: 321 . type - name of function 322 323 Level: intermediate 324 325 .seealso: `PF`, `PFSetType()` 326 @*/ 327 PetscErrorCode PFGetType(PF pf, PFType *type) 328 { 329 PetscFunctionBegin; 330 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 331 PetscValidPointer(type, 2); 332 *type = ((PetscObject)pf)->type_name; 333 PetscFunctionReturn(PETSC_SUCCESS); 334 } 335 336 /*@C 337 PFSetType - Builds `PF` for a particular function 338 339 Collective 340 341 Input Parameters: 342 + pf - the function context. 343 . type - a known method 344 - ctx - optional type dependent context 345 346 Options Database Key: 347 . -pf_type <type> - Sets PF type 348 349 Level: intermediate 350 351 Note: 352 See "petsc/include/petscpf.h" for available methods (for instance, `PFCONSTANT`) 353 354 .seealso: `PF`, `PFSet()`, `PFRegister()`, `PFCreate()`, `DMDACreatePF()` 355 @*/ 356 PetscErrorCode PFSetType(PF pf, PFType type, void *ctx) 357 { 358 PetscBool match; 359 PetscErrorCode (*r)(PF, void *); 360 361 PetscFunctionBegin; 362 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 363 PetscValidCharPointer(type, 2); 364 365 PetscCall(PetscObjectTypeCompare((PetscObject)pf, type, &match)); 366 if (match) PetscFunctionReturn(PETSC_SUCCESS); 367 368 PetscTryTypeMethod(pf, destroy); 369 pf->data = NULL; 370 371 /* Determine the PFCreateXXX routine for a particular function */ 372 PetscCall(PetscFunctionListFind(PFList, type, &r)); 373 PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PF type %s", type); 374 pf->ops->destroy = NULL; 375 pf->ops->view = NULL; 376 pf->ops->apply = NULL; 377 pf->ops->applyvec = NULL; 378 379 /* Call the PFCreateXXX routine for this particular function */ 380 PetscCall((*r)(pf, ctx)); 381 382 PetscCall(PetscObjectChangeTypeName((PetscObject)pf, type)); 383 PetscFunctionReturn(PETSC_SUCCESS); 384 } 385 386 /*@ 387 PFSetFromOptions - Sets `PF` options from the options database. 388 389 Collective 390 391 Input Parameters: 392 . pf - the mathematical function context 393 394 Level: intermediate 395 396 Notes: 397 To see all options, run your program with the -help option 398 or consult the users manual. 399 400 .seealso: `PF` 401 @*/ 402 PetscErrorCode PFSetFromOptions(PF pf) 403 { 404 char type[256]; 405 PetscBool flg; 406 407 PetscFunctionBegin; 408 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 409 410 PetscObjectOptionsBegin((PetscObject)pf); 411 PetscCall(PetscOptionsFList("-pf_type", "Type of function", "PFSetType", PFList, NULL, type, 256, &flg)); 412 if (flg) PetscCall(PFSetType(pf, type, NULL)); 413 PetscTryTypeMethod(pf, setfromoptions, PetscOptionsObject); 414 415 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 416 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pf, PetscOptionsObject)); 417 PetscOptionsEnd(); 418 PetscFunctionReturn(PETSC_SUCCESS); 419 } 420 421 static PetscBool PFPackageInitialized = PETSC_FALSE; 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