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