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 on PF 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: `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 PetscFunctionBegin; 29 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 30 pf->data = ctx; 31 pf->ops->destroy = destroy; 32 pf->ops->apply = apply; 33 pf->ops->applyvec = applyvec; 34 pf->ops->view = view; 35 PetscFunctionReturn(0); 36 } 37 38 /*@C 39 PFDestroy - Destroys PF context that was created with PFCreate(). 40 41 Collective on PF 42 43 Input Parameter: 44 . pf - the function context 45 46 Level: beginner 47 48 .seealso: `PFCreate()`, `PFSet()`, `PFSetType()` 49 @*/ 50 PetscErrorCode PFDestroy(PF *pf) { 51 PetscFunctionBegin; 52 if (!*pf) PetscFunctionReturn(0); 53 PetscValidHeaderSpecific((*pf), PF_CLASSID, 1); 54 if (--((PetscObject)(*pf))->refct > 0) PetscFunctionReturn(0); 55 56 PetscCall(PFViewFromOptions(*pf, NULL, "-pf_view")); 57 /* if memory was published with SAWs then destroy it */ 58 PetscCall(PetscObjectSAWsViewOff((PetscObject)*pf)); 59 60 if ((*pf)->ops->destroy) PetscCall((*(*pf)->ops->destroy)((*pf)->data)); 61 PetscCall(PetscHeaderDestroy(pf)); 62 PetscFunctionReturn(0); 63 } 64 65 /*@C 66 PFCreate - Creates a mathematical function context. 67 68 Collective 69 70 Input Parameters: 71 + comm - MPI communicator 72 . dimin - dimension of the space you are mapping from 73 - dimout - dimension of the space you are mapping to 74 75 Output Parameter: 76 . pf - the function context 77 78 Level: developer 79 80 .seealso: `PFSet()`, `PFApply()`, `PFDestroy()`, `PFApplyVec()` 81 @*/ 82 PetscErrorCode PFCreate(MPI_Comm comm, PetscInt dimin, PetscInt dimout, PF *pf) { 83 PF newpf; 84 85 PetscFunctionBegin; 86 PetscValidPointer(pf, 4); 87 *pf = NULL; 88 PetscCall(PFInitializePackage()); 89 90 PetscCall(PetscHeaderCreate(newpf, PF_CLASSID, "PF", "Mathematical functions", "Vec", comm, PFDestroy, PFView)); 91 newpf->data = NULL; 92 newpf->ops->destroy = NULL; 93 newpf->ops->apply = NULL; 94 newpf->ops->applyvec = NULL; 95 newpf->ops->view = NULL; 96 newpf->dimin = dimin; 97 newpf->dimout = dimout; 98 99 *pf = newpf; 100 PetscFunctionReturn(0); 101 } 102 103 /* -------------------------------------------------------------------------------*/ 104 105 /*@ 106 PFApplyVec - Applies the mathematical function to a vector 107 108 Collective on PF 109 110 Input Parameters: 111 + pf - the function context 112 - x - input vector (or NULL for the vector (0,1, .... N-1) 113 114 Output Parameter: 115 . y - output vector 116 117 Level: beginner 118 119 .seealso: `PFApply()`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFSet()` 120 @*/ 121 PetscErrorCode PFApplyVec(PF pf, Vec x, Vec y) { 122 PetscInt i, rstart, rend, n, p; 123 PetscBool nox = PETSC_FALSE; 124 125 PetscFunctionBegin; 126 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 127 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 128 if (x) { 129 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 130 PetscCheck(x != y, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 131 } else { 132 PetscScalar *xx; 133 PetscInt lsize; 134 135 PetscCall(VecGetLocalSize(y, &lsize)); 136 lsize = pf->dimin * lsize / pf->dimout; 137 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)y), lsize, PETSC_DETERMINE, &x)); 138 nox = PETSC_TRUE; 139 PetscCall(VecGetOwnershipRange(x, &rstart, &rend)); 140 PetscCall(VecGetArray(x, &xx)); 141 for (i = rstart; i < rend; i++) xx[i - rstart] = (PetscScalar)i; 142 PetscCall(VecRestoreArray(x, &xx)); 143 } 144 145 PetscCall(VecGetLocalSize(x, &n)); 146 PetscCall(VecGetLocalSize(y, &p)); 147 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); 148 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); 149 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); 150 151 if (pf->ops->applyvec) PetscCall((*pf->ops->applyvec)(pf->data, x, y)); 152 else { 153 PetscScalar *xx, *yy; 154 155 PetscCall(VecGetLocalSize(x, &n)); 156 n = n / pf->dimin; 157 PetscCall(VecGetArray(x, &xx)); 158 PetscCall(VecGetArray(y, &yy)); 159 PetscCall((*pf->ops->apply)(pf->data, n, xx, yy)); 160 PetscCall(VecRestoreArray(x, &xx)); 161 PetscCall(VecRestoreArray(y, &yy)); 162 } 163 if (nox) PetscCall(VecDestroy(&x)); 164 PetscFunctionReturn(0); 165 } 166 167 /*@ 168 PFApply - Applies the mathematical function to an array of values. 169 170 Collective on PF 171 172 Input Parameters: 173 + pf - the function context 174 . n - number of pointwise function evaluations to perform, each pointwise function evaluation 175 is a function of dimin variables and computes dimout variables where dimin and dimout are defined 176 in the call to PFCreate() 177 - x - input array 178 179 Output Parameter: 180 . y - output array 181 182 Level: beginner 183 184 Notes: 185 186 .seealso: `PFApplyVec()`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFSet()` 187 @*/ 188 PetscErrorCode PFApply(PF pf, PetscInt n, const PetscScalar *x, PetscScalar *y) { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 191 PetscValidScalarPointer(x, 3); 192 PetscValidScalarPointer(y, 4); 193 PetscCheck(x != y, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "x and y must be different arrays"); 194 195 PetscCall((*pf->ops->apply)(pf->data, n, x, y)); 196 PetscFunctionReturn(0); 197 } 198 199 /*@C 200 PFViewFromOptions - View from Options 201 202 Collective on PF 203 204 Input Parameters: 205 + A - the PF context 206 . obj - Optional object 207 - name - command line option 208 209 Level: intermediate 210 .seealso: `PF`, `PFView`, `PetscObjectViewFromOptions()`, `PFCreate()` 211 @*/ 212 PetscErrorCode PFViewFromOptions(PF A, PetscObject obj, const char name[]) { 213 PetscFunctionBegin; 214 PetscValidHeaderSpecific(A, PF_CLASSID, 1); 215 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 216 PetscFunctionReturn(0); 217 } 218 219 /*@ 220 PFView - Prints information about a mathematical function 221 222 Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF 223 224 Input Parameters: 225 + PF - the PF context 226 - viewer - optional visualization context 227 228 Note: 229 The available visualization contexts include 230 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 231 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 232 output where only the first processor opens 233 the file. All other processors send their 234 data to the first processor to print. 235 236 The user can open an alternative visualization contexts with 237 PetscViewerASCIIOpen() (output to a specified file). 238 239 Level: developer 240 241 .seealso: `PetscViewerCreate()`, `PetscViewerASCIIOpen()` 242 @*/ 243 PetscErrorCode PFView(PF pf, PetscViewer viewer) { 244 PetscBool iascii; 245 PetscViewerFormat format; 246 247 PetscFunctionBegin; 248 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 249 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf), &viewer)); 250 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 251 PetscCheckSameComm(pf, 1, viewer, 2); 252 253 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 254 if (iascii) { 255 PetscCall(PetscViewerGetFormat(viewer, &format)); 256 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pf, viewer)); 257 if (pf->ops->view) { 258 PetscCall(PetscViewerASCIIPushTab(viewer)); 259 PetscCall((*pf->ops->view)(pf->data, viewer)); 260 PetscCall(PetscViewerASCIIPopTab(viewer)); 261 } 262 } 263 PetscFunctionReturn(0); 264 } 265 266 /*@C 267 PFRegister - Adds a method to the mathematical function package. 268 269 Not collective 270 271 Input Parameters: 272 + name_solver - name of a new user-defined solver 273 - routine_create - routine to create method context 274 275 Notes: 276 PFRegister() may be called multiple times to add several user-defined functions 277 278 Sample usage: 279 .vb 280 PFRegister("my_function",MyFunctionSetCreate); 281 .ve 282 283 Then, your solver can be chosen with the procedural interface via 284 $ PFSetType(pf,"my_function") 285 or at runtime via the option 286 $ -pf_type my_function 287 288 Level: advanced 289 290 .seealso: `PFRegisterAll()`, `PFRegisterDestroy()`, `PFRegister()` 291 @*/ 292 PetscErrorCode PFRegister(const char sname[], PetscErrorCode (*function)(PF, void *)) { 293 PetscFunctionBegin; 294 PetscCall(PFInitializePackage()); 295 PetscCall(PetscFunctionListAdd(&PFList, sname, function)); 296 PetscFunctionReturn(0); 297 } 298 299 /*@C 300 PFGetType - Gets the PF method type and name (as a string) from the PF 301 context. 302 303 Not Collective 304 305 Input Parameter: 306 . pf - the function context 307 308 Output Parameter: 309 . type - name of function 310 311 Level: intermediate 312 313 .seealso: `PFSetType()` 314 315 @*/ 316 PetscErrorCode PFGetType(PF pf, PFType *type) { 317 PetscFunctionBegin; 318 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 319 PetscValidPointer(type, 2); 320 *type = ((PetscObject)pf)->type_name; 321 PetscFunctionReturn(0); 322 } 323 324 /*@C 325 PFSetType - Builds PF for a particular function 326 327 Collective on PF 328 329 Input Parameters: 330 + pf - the function context. 331 . type - a known method 332 - ctx - optional type dependent context 333 334 Options Database Key: 335 . -pf_type <type> - Sets PF type 336 337 Notes: 338 See "petsc/include/petscpf.h" for available methods (for instance, 339 PFCONSTANT) 340 341 Level: intermediate 342 343 .seealso: `PFSet()`, `PFRegister()`, `PFCreate()`, `DMDACreatePF()` 344 345 @*/ 346 PetscErrorCode PFSetType(PF pf, PFType type, void *ctx) { 347 PetscBool match; 348 PetscErrorCode (*r)(PF, void *); 349 350 PetscFunctionBegin; 351 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 352 PetscValidCharPointer(type, 2); 353 354 PetscCall(PetscObjectTypeCompare((PetscObject)pf, type, &match)); 355 if (match) PetscFunctionReturn(0); 356 357 PetscTryTypeMethod(pf, destroy); 358 pf->data = NULL; 359 360 /* Determine the PFCreateXXX routine for a particular function */ 361 PetscCall(PetscFunctionListFind(PFList, type, &r)); 362 PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PF type %s", type); 363 pf->ops->destroy = NULL; 364 pf->ops->view = NULL; 365 pf->ops->apply = NULL; 366 pf->ops->applyvec = NULL; 367 368 /* Call the PFCreateXXX routine for this particular function */ 369 PetscCall((*r)(pf, ctx)); 370 371 PetscCall(PetscObjectChangeTypeName((PetscObject)pf, type)); 372 PetscFunctionReturn(0); 373 } 374 375 /*@ 376 PFSetFromOptions - Sets PF options from the options database. 377 378 Collective on PF 379 380 Input Parameters: 381 . pf - the mathematical function context 382 383 Options Database Keys: 384 385 Notes: 386 To see all options, run your program with the -help option 387 or consult the users manual. 388 389 Level: intermediate 390 391 .seealso: 392 @*/ 393 PetscErrorCode PFSetFromOptions(PF pf) { 394 char type[256]; 395 PetscBool flg; 396 397 PetscFunctionBegin; 398 PetscValidHeaderSpecific(pf, PF_CLASSID, 1); 399 400 PetscObjectOptionsBegin((PetscObject)pf); 401 PetscCall(PetscOptionsFList("-pf_type", "Type of function", "PFSetType", PFList, NULL, type, 256, &flg)); 402 if (flg) PetscCall(PFSetType(pf, type, NULL)); 403 PetscTryTypeMethod(pf, setfromoptions, PetscOptionsObject); 404 405 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 406 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pf, PetscOptionsObject)); 407 PetscOptionsEnd(); 408 PetscFunctionReturn(0); 409 } 410 411 static PetscBool PFPackageInitialized = PETSC_FALSE; 412 /*@C 413 PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is 414 called from PetscFinalize(). 415 416 Level: developer 417 418 .seealso: `PetscFinalize()` 419 @*/ 420 PetscErrorCode PFFinalizePackage(void) { 421 PetscFunctionBegin; 422 PetscCall(PetscFunctionListDestroy(&PFList)); 423 PFPackageInitialized = PETSC_FALSE; 424 PFRegisterAllCalled = PETSC_FALSE; 425 PetscFunctionReturn(0); 426 } 427 428 /*@C 429 PFInitializePackage - This function initializes everything in the PF package. It is called 430 from PetscDLLibraryRegister_petscvec() when using dynamic libraries, and on the first call to PFCreate() 431 when using shared or static libraries. 432 433 Level: developer 434 435 .seealso: `PetscInitialize()` 436 @*/ 437 PetscErrorCode PFInitializePackage(void) { 438 char logList[256]; 439 PetscBool opt, pkg; 440 441 PetscFunctionBegin; 442 if (PFPackageInitialized) PetscFunctionReturn(0); 443 PFPackageInitialized = PETSC_TRUE; 444 /* Register Classes */ 445 PetscCall(PetscClassIdRegister("PointFunction", &PF_CLASSID)); 446 /* Register Constructors */ 447 PetscCall(PFRegisterAll()); 448 /* Process Info */ 449 { 450 PetscClassId classids[1]; 451 452 classids[0] = PF_CLASSID; 453 PetscCall(PetscInfoProcessClass("pf", 1, classids)); 454 } 455 /* Process summary exclusions */ 456 PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt)); 457 if (opt) { 458 PetscCall(PetscStrInList("pf", logList, ',', &pkg)); 459 if (pkg) PetscCall(PetscLogEventExcludeClass(PF_CLASSID)); 460 } 461 /* Register package finalizer */ 462 PetscCall(PetscRegisterFinalize(PFFinalizePackage)); 463 PetscFunctionReturn(0); 464 } 465