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