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