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