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