xref: /petsc/src/vec/pf/interface/pf.c (revision 67c2884ef72a42a4f3a1babc25bcfa28f347172e)
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 PFunctionList       = NULL;   /* list of all registered PD functions */
8 PetscBool         PFRegisterAllCalled = PETSC_FALSE;
9 
10 #undef __FUNCT__
11 #define __FUNCT__ "PFSet"
12 /*@C
13    PFSet - Sets the C/C++/Fortran functions to be used by the PF function
14 
15    Collective on PF
16 
17    Input Parameter:
18 +  pf - the function context
19 .  apply - function to apply to an array
20 .  applyvec - function to apply to a Vec
21 .  view - function that prints information about the PF
22 .  destroy - function to free the private function context
23 -  ctx - private function context
24 
25    Level: beginner
26 
27 .keywords: PF, setting
28 
29 .seealso: PFCreate(), PFDestroy(), PFSetType(), PFApply(), PFApplyVec()
30 @*/
31 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)
32 {
33   PetscFunctionBegin;
34   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
35   pf->data          = ctx;
36   pf->ops->destroy  = destroy;
37   pf->ops->apply    = apply;
38   pf->ops->applyvec = applyvec;
39   pf->ops->view     = view;
40   PetscFunctionReturn(0);
41 }
42 
43 #undef __FUNCT__
44 #define __FUNCT__ "PFDestroy"
45 /*@C
46    PFDestroy - Destroys PF context that was created with PFCreate().
47 
48    Collective on PF
49 
50    Input Parameter:
51 .  pf - the function context
52 
53    Level: beginner
54 
55 .keywords: PF, destroy
56 
57 .seealso: PFCreate(), PFSet(), PFSetType()
58 @*/
59 PetscErrorCode  PFDestroy(PF *pf)
60 {
61   PetscErrorCode ierr;
62   PetscBool      flg = PETSC_FALSE;
63 
64   PetscFunctionBegin;
65   if (!*pf) PetscFunctionReturn(0);
66   PetscValidHeaderSpecific((*pf),PF_CLASSID,1);
67   if (--((PetscObject)(*pf))->refct > 0) PetscFunctionReturn(0);
68 
69   ierr = PetscOptionsGetBool(((PetscObject)(*pf))->prefix,"-pf_view",&flg,NULL);CHKERRQ(ierr);
70   if (flg) {
71     PetscViewer viewer;
72     ierr = PetscViewerASCIIGetStdout(((PetscObject)(*pf))->comm,&viewer);CHKERRQ(ierr);
73     ierr = PFView((*pf),viewer);CHKERRQ(ierr);
74   }
75 
76   /* if memory was published with AMS then destroy it */
77   ierr = PetscObjectDepublish((*pf));CHKERRQ(ierr);
78 
79   if ((*pf)->ops->destroy) {ierr =  (*(*pf)->ops->destroy)((*pf)->data);CHKERRQ(ierr);}
80   ierr = PetscHeaderDestroy(pf);CHKERRQ(ierr);
81   PetscFunctionReturn(0);
82 }
83 
84 #undef __FUNCT__
85 #define __FUNCT__ "PFCreate"
86 /*@C
87    PFCreate - Creates a mathematical function context.
88 
89    Collective on MPI_Comm
90 
91    Input Parameter:
92 +  comm - MPI communicator
93 .  dimin - dimension of the space you are mapping from
94 -  dimout - dimension of the space you are mapping to
95 
96    Output Parameter:
97 .  pf - the function context
98 
99    Level: developer
100 
101 .keywords: PF, create, context
102 
103 .seealso: PFSet(), PFApply(), PFDestroy(), PFApplyVec()
104 @*/
105 PetscErrorCode  PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
106 {
107   PF             newpf;
108   PetscErrorCode ierr;
109 
110   PetscFunctionBegin;
111   PetscValidPointer(pf,1);
112   *pf = NULL;
113 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
114   ierr = PFInitializePackage(NULL);CHKERRQ(ierr);
115 #endif
116 
117   ierr = PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_CLASSID,"PF","Mathematical functions","Vec",comm,PFDestroy,PFView);CHKERRQ(ierr);
118   newpf->data          = 0;
119   newpf->ops->destroy  = 0;
120   newpf->ops->apply    = 0;
121   newpf->ops->applyvec = 0;
122   newpf->ops->view     = 0;
123   newpf->dimin         = dimin;
124   newpf->dimout        = dimout;
125 
126   *pf                  = newpf;
127   PetscFunctionReturn(0);
128 
129 }
130 
131 /* -------------------------------------------------------------------------------*/
132 
133 #undef __FUNCT__
134 #define __FUNCT__ "PFApplyVec"
135 /*@
136    PFApplyVec - Applies the mathematical function to a vector
137 
138    Collective on PF
139 
140    Input Parameters:
141 +  pf - the function context
142 -  x - input vector (or NULL for the vector (0,1, .... N-1)
143 
144    Output Parameter:
145 .  y - output vector
146 
147    Level: beginner
148 
149 .keywords: PF, apply
150 
151 .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
152 @*/
153 PetscErrorCode  PFApplyVec(PF pf,Vec x,Vec y)
154 {
155   PetscErrorCode ierr;
156   PetscInt       i,rstart,rend,n,p;
157   PetscBool      nox = PETSC_FALSE;
158 
159   PetscFunctionBegin;
160   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
161   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
162   if (x) {
163     PetscValidHeaderSpecific(x,VEC_CLASSID,2);
164     if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors");
165   } else {
166     PetscScalar *xx;
167     PetscInt    lsize;
168 
169     ierr  = VecGetLocalSize(y,&lsize);CHKERRQ(ierr);
170     lsize = pf->dimin*lsize/pf->dimout;
171     ierr  = VecCreateMPI(((PetscObject)y)->comm,lsize,PETSC_DETERMINE,&x);CHKERRQ(ierr);
172     nox   = PETSC_TRUE;
173     ierr  = VecGetOwnershipRange(x,&rstart,&rend);CHKERRQ(ierr);
174     ierr  = VecGetArray(x,&xx);CHKERRQ(ierr);
175     for (i=rstart; i<rend; i++) xx[i-rstart] = (PetscScalar)i;
176     ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
177   }
178 
179   ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr);
180   ierr = VecGetLocalSize(y,&p);CHKERRQ(ierr);
181   if ((pf->dimin*(n/pf->dimin)) != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local input vector length %D not divisible by dimin %D of function",n,pf->dimin);
182   if ((pf->dimout*(p/pf->dimout)) != p) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local output vector length %D not divisible by dimout %D of function",p,pf->dimout);
183   if ((n/pf->dimin) != (p/pf->dimout)) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local vector lengths %D %D are wrong for dimin and dimout %D %D of function",n,p,pf->dimin,pf->dimout);
184 
185   if (pf->ops->applyvec) {
186     ierr = (*pf->ops->applyvec)(pf->data,x,y);CHKERRQ(ierr);
187   } else {
188     PetscScalar *xx,*yy;
189 
190     ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr);
191     n    = n/pf->dimin;
192     ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
193     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
194     if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
195     ierr = (*pf->ops->apply)(pf->data,n,xx,yy);CHKERRQ(ierr);
196     ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
197     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
198   }
199   if (nox) {
200     ierr = VecDestroy(&x);CHKERRQ(ierr);
201   }
202   PetscFunctionReturn(0);
203 }
204 
205 #undef __FUNCT__
206 #define __FUNCT__ "PFApply"
207 /*@
208    PFApply - Applies the mathematical function to an array of values.
209 
210    Collective on PF
211 
212    Input Parameters:
213 +  pf - the function context
214 .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
215        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
216        in the call to PFCreate()
217 -  x - input array
218 
219    Output Parameter:
220 .  y - output array
221 
222    Level: beginner
223 
224    Notes:
225 
226 .keywords: PF, apply
227 
228 .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
229 @*/
230 PetscErrorCode  PFApply(PF pf,PetscInt n,const PetscScalar *x,PetscScalar *y)
231 {
232   PetscErrorCode ierr;
233 
234   PetscFunctionBegin;
235   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
236   PetscValidScalarPointer(x,2);
237   PetscValidScalarPointer(y,3);
238   if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different arrays");
239   if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
240 
241   ierr = (*pf->ops->apply)(pf->data,n,x,y);CHKERRQ(ierr);
242   PetscFunctionReturn(0);
243 }
244 
245 #undef __FUNCT__
246 #define __FUNCT__ "PFView"
247 /*@
248    PFView - Prints information about a mathematical function
249 
250    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
251 
252    Input Parameters:
253 +  PF - the PF context
254 -  viewer - optional visualization context
255 
256    Note:
257    The available visualization contexts include
258 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
259 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
260          output where only the first processor opens
261          the file.  All other processors send their
262          data to the first processor to print.
263 
264    The user can open an alternative visualization contexts with
265    PetscViewerASCIIOpen() (output to a specified file).
266 
267    Level: developer
268 
269 .keywords: PF, view
270 
271 .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
272 @*/
273 PetscErrorCode  PFView(PF pf,PetscViewer viewer)
274 {
275   PetscErrorCode    ierr;
276   PetscBool         iascii;
277   PetscViewerFormat format;
278 
279   PetscFunctionBegin;
280   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
281   if (!viewer) {
282     ierr = PetscViewerASCIIGetStdout(((PetscObject)pf)->comm,&viewer);CHKERRQ(ierr);
283   }
284   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
285   PetscCheckSameComm(pf,1,viewer,2);
286 
287   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
288   if (iascii) {
289     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
290     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer,"PF Object");CHKERRQ(ierr);
291     if (pf->ops->view) {
292       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
293       ierr = (*pf->ops->view)(pf->data,viewer);CHKERRQ(ierr);
294       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
295     }
296   }
297   PetscFunctionReturn(0);
298 }
299 
300 /*MC
301    PFRegisterDynamic - Adds a method to the mathematical function package.
302 
303    Synopsis:
304    #include "petscpf.h"
305    PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))
306 
307    Not collective
308 
309    Input Parameters:
310 +  name_solver - name of a new user-defined solver
311 .  path - path (either absolute or relative) the library containing this solver
312 .  name_create - name of routine to create method context
313 -  routine_create - routine to create method context
314 
315    Notes:
316    PFRegisterDynamic() may be called multiple times to add several user-defined functions
317 
318    If dynamic libraries are used, then the fourth input argument (routine_create)
319    is ignored.
320 
321    Sample usage:
322 .vb
323    PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
324               "MyFunctionCreate",MyFunctionSetCreate);
325 .ve
326 
327    Then, your solver can be chosen with the procedural interface via
328 $     PFSetType(pf,"my_function")
329    or at runtime via the option
330 $     -pf_type my_function
331 
332    Level: advanced
333 
334    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
335  occuring in pathname will be replaced with appropriate values.
336 
337 .keywords: PF, register
338 
339 .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
340 M*/
341 
342 #undef __FUNCT__
343 #define __FUNCT__ "PFRegister"
344 PetscErrorCode  PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
345 {
346   PetscErrorCode ierr;
347   char           fullname[PETSC_MAX_PATH_LEN];
348 
349   PetscFunctionBegin;
350   ierr = PetscFunctionListConcat(path,name,fullname);CHKERRQ(ierr);
351   ierr = PetscFunctionListAdd(PETSC_COMM_WORLD,&PFunctionList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr);
352   PetscFunctionReturn(0);
353 }
354 
355 #undef __FUNCT__
356 #define __FUNCT__ "PFGetType"
357 /*@C
358    PFGetType - Gets the PF method type and name (as a string) from the PF
359    context.
360 
361    Not Collective
362 
363    Input Parameter:
364 .  pf - the function context
365 
366    Output Parameter:
367 .  type - name of function
368 
369    Level: intermediate
370 
371 .keywords: PF, get, method, name, type
372 
373 .seealso: PFSetType()
374 
375 @*/
376 PetscErrorCode  PFGetType(PF pf,PFType *type)
377 {
378   PetscFunctionBegin;
379   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
380   PetscValidPointer(type,2);
381   *type = ((PetscObject)pf)->type_name;
382   PetscFunctionReturn(0);
383 }
384 
385 
386 #undef __FUNCT__
387 #define __FUNCT__ "PFSetType"
388 /*@C
389    PFSetType - Builds PF for a particular function
390 
391    Collective on PF
392 
393    Input Parameter:
394 +  pf - the function context.
395 .  type - a known method
396 -  ctx - optional type dependent context
397 
398    Options Database Key:
399 .  -pf_type <type> - Sets PF type
400 
401 
402   Notes:
403   See "petsc/include/petscpf.h" for available methods (for instance,
404   PFCONSTANT)
405 
406   Level: intermediate
407 
408 .keywords: PF, set, method, type
409 
410 .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DMDACreatePF()
411 
412 @*/
413 PetscErrorCode  PFSetType(PF pf,PFType type,void *ctx)
414 {
415   PetscErrorCode ierr,(*r)(PF,void*);
416   PetscBool      match;
417 
418   PetscFunctionBegin;
419   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
420   PetscValidCharPointer(type,2);
421 
422   ierr = PetscObjectTypeCompare((PetscObject)pf,type,&match);CHKERRQ(ierr);
423   if (match) PetscFunctionReturn(0);
424 
425   if (pf->ops->destroy) {ierr =  (*pf->ops->destroy)(pf);CHKERRQ(ierr);}
426   pf->data = 0;
427 
428   /* Determine the PFCreateXXX routine for a particular function */
429   ierr = PetscFunctionListFind(((PetscObject)pf)->comm,PFunctionList,type,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr);
430   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
431   pf->ops->destroy  = 0;
432   pf->ops->view     = 0;
433   pf->ops->apply    = 0;
434   pf->ops->applyvec = 0;
435 
436   /* Call the PFCreateXXX routine for this particular function */
437   ierr = (*r)(pf,ctx);CHKERRQ(ierr);
438 
439   ierr = PetscObjectChangeTypeName((PetscObject)pf,type);CHKERRQ(ierr);
440   PetscFunctionReturn(0);
441 }
442 
443 #undef __FUNCT__
444 #define __FUNCT__ "PFSetFromOptions"
445 /*@
446    PFSetFromOptions - Sets PF options from the options database.
447 
448    Collective on PF
449 
450    Input Parameters:
451 .  pf - the mathematical function context
452 
453    Options Database Keys:
454 
455    Notes:
456    To see all options, run your program with the -help option
457    or consult the users manual.
458 
459    Level: intermediate
460 
461 .keywords: PF, set, from, options, database
462 
463 .seealso:
464 @*/
465 PetscErrorCode  PFSetFromOptions(PF pf)
466 {
467   PetscErrorCode ierr;
468   char           type[256];
469   PetscBool      flg;
470 
471   PetscFunctionBegin;
472   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
473 
474   ierr = PetscObjectOptionsBegin((PetscObject)pf);CHKERRQ(ierr);
475   ierr = PetscOptionsList("-pf_type","Type of function","PFSetType",PFunctionList,0,type,256,&flg);CHKERRQ(ierr);
476   if (flg) {
477     ierr = PFSetType(pf,type,NULL);CHKERRQ(ierr);
478   }
479   if (pf->ops->setfromoptions) {
480     ierr = (*pf->ops->setfromoptions)(pf);CHKERRQ(ierr);
481   }
482 
483   /* process any options handlers added with PetscObjectAddOptionsHandler() */
484   ierr = PetscObjectProcessOptionsHandlers((PetscObject)pf);CHKERRQ(ierr);
485   ierr = PetscOptionsEnd();CHKERRQ(ierr);
486   PetscFunctionReturn(0);
487 }
488 
489 static PetscBool PFPackageInitialized = PETSC_FALSE;
490 #undef __FUNCT__
491 #define __FUNCT__ "PFFinalizePackage"
492 /*@C
493   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
494   called from PetscFinalize().
495 
496   Level: developer
497 
498 .keywords: Petsc, destroy, package, mathematica
499 .seealso: PetscFinalize()
500 @*/
501 PetscErrorCode  PFFinalizePackage(void)
502 {
503   PetscFunctionBegin;
504   PFPackageInitialized = PETSC_FALSE;
505   PFunctionList        = NULL;
506   PFRegisterAllCalled  = PETSC_FALSE;
507   PetscFunctionReturn(0);
508 }
509 
510 #undef __FUNCT__
511 #define __FUNCT__ "PFInitializePackage"
512 /*@C
513   PFInitializePackage - This function initializes everything in the PF package. It is called
514   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
515   when using static libraries.
516 
517   Input Parameter:
518 . path - The dynamic library path, or NULL
519 
520   Level: developer
521 
522 .keywords: Vec, initialize, package
523 .seealso: PetscInitialize()
524 @*/
525 PetscErrorCode  PFInitializePackage(const char path[])
526 {
527   char           logList[256];
528   char           *className;
529   PetscBool      opt;
530   PetscErrorCode ierr;
531 
532   PetscFunctionBegin;
533   if (PFPackageInitialized) PetscFunctionReturn(0);
534   PFPackageInitialized = PETSC_TRUE;
535   /* Register Classes */
536   ierr = PetscClassIdRegister("PointFunction",&PF_CLASSID);CHKERRQ(ierr);
537   /* Register Constructors */
538   ierr = PFRegisterAll(path);CHKERRQ(ierr);
539   /* Process info exclusions */
540   ierr = PetscOptionsGetString(NULL, "-info_exclude", logList, 256, &opt);CHKERRQ(ierr);
541   if (opt) {
542     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
543     if (className) {
544       ierr = PetscInfoDeactivateClass(PF_CLASSID);CHKERRQ(ierr);
545     }
546   }
547   /* Process summary exclusions */
548   ierr = PetscOptionsGetString(NULL, "-log_summary_exclude", logList, 256, &opt);CHKERRQ(ierr);
549   if (opt) {
550     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
551     if (className) {
552       ierr = PetscLogEventDeactivateClass(PF_CLASSID);CHKERRQ(ierr);
553     }
554   }
555   ierr = PetscRegisterFinalize(PFFinalizePackage);CHKERRQ(ierr);
556   PetscFunctionReturn(0);
557 }
558 
559 
560 
561 
562 
563 
564 
565 
566 
567