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