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