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 @*/
PFSet(PF pf,PetscErrorCode (* apply)(void *,PetscInt,const PetscScalar *,PetscScalar *),PetscErrorCode (* applyvec)(void *,Vec,Vec),PetscErrorCode (* view)(void *,PetscViewer),PetscErrorCode (* destroy)(PetscCtxRt),PetscCtx ctx)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 @*/
PFDestroy(PF * pf)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 @*/
PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF * pf)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 @*/
PFApplyVec(PF pf,Vec x,Vec y)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 @*/
PFApply(PF pf,PetscInt n,const PetscScalar * x,PetscScalar * y)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 @*/
PFViewFromOptions(PF A,PetscObject obj,const char name[])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 @*/
PFView(PF pf,PetscViewer viewer)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 @*/
PFRegister(const char sname[],PetscErrorCode (* function)(PF,void *))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 @*/
PFGetType(PF pf,PFType * type)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 @*/
PFSetType(PF pf,PFType type,PetscCtx ctx)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 @*/
PFSetFromOptions(PF pf)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 @*/
PFFinalizePackage(void)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 @*/
PFInitializePackage(void)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