xref: /petsc/src/vec/pf/interface/pf.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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