xref: /petsc/src/vec/pf/interface/pf.c (revision f2ba6396f7b83edb93500ef33fbc29109fc954a4)
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    #include "petscpf.h"
314    PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))
315 
316    Not collective
317 
318    Input Parameters:
319 +  name_solver - name of a new user-defined solver
320 .  path - path (either absolute or relative) the library containing this solver
321 .  name_create - name of routine to create method context
322 -  routine_create - routine to create method context
323 
324    Notes:
325    PFRegisterDynamic() may be called multiple times to add several user-defined functions
326 
327    If dynamic libraries are used, then the fourth input argument (routine_create)
328    is ignored.
329 
330    Sample usage:
331 .vb
332    PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
333               "MyFunctionCreate",MyFunctionSetCreate);
334 .ve
335 
336    Then, your solver can be chosen with the procedural interface via
337 $     PFSetType(pf,"my_function")
338    or at runtime via the option
339 $     -pf_type my_function
340 
341    Level: advanced
342 
343    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
344  occuring in pathname will be replaced with appropriate values.
345 
346 .keywords: PF, register
347 
348 .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
349 M*/
350 
351 #undef __FUNCT__
352 #define __FUNCT__ "PFRegister"
353 PetscErrorCode  PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
354 {
355   PetscErrorCode ierr;
356   char           fullname[PETSC_MAX_PATH_LEN];
357 
358   PetscFunctionBegin;
359   ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr);
360   ierr = PetscFListAdd(&PFList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr);
361   PetscFunctionReturn(0);
362 }
363 
364 #undef __FUNCT__
365 #define __FUNCT__ "PFGetType"
366 /*@C
367    PFGetType - Gets the PF method type and name (as a string) from the PF
368    context.
369 
370    Not Collective
371 
372    Input Parameter:
373 .  pf - the function context
374 
375    Output Parameter:
376 .  type - name of function
377 
378    Level: intermediate
379 
380 .keywords: PF, get, method, name, type
381 
382 .seealso: PFSetType()
383 
384 @*/
385 PetscErrorCode  PFGetType(PF pf,PFType *type)
386 {
387   PetscFunctionBegin;
388   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
389   PetscValidPointer(type,2);
390   *type = ((PetscObject)pf)->type_name;
391   PetscFunctionReturn(0);
392 }
393 
394 
395 #undef __FUNCT__
396 #define __FUNCT__ "PFSetType"
397 /*@C
398    PFSetType - Builds PF for a particular function
399 
400    Collective on PF
401 
402    Input Parameter:
403 +  pf - the function context.
404 .  type - a known method
405 -  ctx - optional type dependent context
406 
407    Options Database Key:
408 .  -pf_type <type> - Sets PF type
409 
410 
411   Notes:
412   See "petsc/include/petscpf.h" for available methods (for instance,
413   PFCONSTANT)
414 
415   Level: intermediate
416 
417 .keywords: PF, set, method, type
418 
419 .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DMDACreatePF()
420 
421 @*/
422 PetscErrorCode  PFSetType(PF pf,PFType type,void *ctx)
423 {
424   PetscErrorCode ierr,(*r)(PF,void*);
425   PetscBool      match;
426 
427   PetscFunctionBegin;
428   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
429   PetscValidCharPointer(type,2);
430 
431   ierr = PetscObjectTypeCompare((PetscObject)pf,type,&match);CHKERRQ(ierr);
432   if (match) PetscFunctionReturn(0);
433 
434   if (pf->ops->destroy) {ierr =  (*pf->ops->destroy)(pf);CHKERRQ(ierr);}
435   pf->data        = 0;
436 
437   /* Determine the PFCreateXXX routine for a particular function */
438   ierr =  PetscFListFind(PFList,((PetscObject)pf)->comm,type,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr);
439   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
440   pf->ops->destroy             = 0;
441   pf->ops->view                = 0;
442   pf->ops->apply               = 0;
443   pf->ops->applyvec            = 0;
444 
445   /* Call the PFCreateXXX routine for this particular function */
446   ierr = (*r)(pf,ctx);CHKERRQ(ierr);
447 
448   ierr = PetscObjectChangeTypeName((PetscObject)pf,type);CHKERRQ(ierr);
449   PetscFunctionReturn(0);
450 }
451 
452 #undef __FUNCT__
453 #define __FUNCT__ "PFSetFromOptions"
454 /*@
455    PFSetFromOptions - Sets PF options from the options database.
456 
457    Collective on PF
458 
459    Input Parameters:
460 .  pf - the mathematical function context
461 
462    Options Database Keys:
463 
464    Notes:
465    To see all options, run your program with the -help option
466    or consult the users manual.
467 
468    Level: intermediate
469 
470 .keywords: PF, set, from, options, database
471 
472 .seealso:
473 @*/
474 PetscErrorCode  PFSetFromOptions(PF pf)
475 {
476   PetscErrorCode ierr;
477   char           type[256];
478   PetscBool      flg;
479 
480   PetscFunctionBegin;
481   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
482 
483   ierr = PetscObjectOptionsBegin((PetscObject)pf);CHKERRQ(ierr);
484     ierr = PetscOptionsList("-pf_type","Type of function","PFSetType",PFList,0,type,256,&flg);CHKERRQ(ierr);
485     if (flg) {
486       ierr = PFSetType(pf,type,PETSC_NULL);CHKERRQ(ierr);
487     }
488     if (pf->ops->setfromoptions) {
489       ierr = (*pf->ops->setfromoptions)(pf);CHKERRQ(ierr);
490     }
491 
492     /* process any options handlers added with PetscObjectAddOptionsHandler() */
493     ierr = PetscObjectProcessOptionsHandlers((PetscObject)pf);CHKERRQ(ierr);
494   ierr = PetscOptionsEnd();CHKERRQ(ierr);
495 
496   PetscFunctionReturn(0);
497 }
498 
499 static PetscBool  PFPackageInitialized = PETSC_FALSE;
500 #undef __FUNCT__
501 #define __FUNCT__ "PFFinalizePackage"
502 /*@C
503   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
504   called from PetscFinalize().
505 
506   Level: developer
507 
508 .keywords: Petsc, destroy, package, mathematica
509 .seealso: PetscFinalize()
510 @*/
511 PetscErrorCode  PFFinalizePackage(void)
512 {
513   PetscFunctionBegin;
514   PFPackageInitialized = PETSC_FALSE;
515   PFList               = PETSC_NULL;
516   PFRegisterAllCalled  = PETSC_FALSE;
517   PetscFunctionReturn(0);
518 }
519 
520 #undef __FUNCT__
521 #define __FUNCT__ "PFInitializePackage"
522 /*@C
523   PFInitializePackage - This function initializes everything in the PF package. It is called
524   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
525   when using static libraries.
526 
527   Input Parameter:
528 . path - The dynamic library path, or PETSC_NULL
529 
530   Level: developer
531 
532 .keywords: Vec, initialize, package
533 .seealso: PetscInitialize()
534 @*/
535 PetscErrorCode  PFInitializePackage(const char path[])
536 {
537   char              logList[256];
538   char              *className;
539   PetscBool         opt;
540   PetscErrorCode    ierr;
541 
542   PetscFunctionBegin;
543   if (PFPackageInitialized) PetscFunctionReturn(0);
544   PFPackageInitialized = PETSC_TRUE;
545   /* Register Classes */
546   ierr = PetscClassIdRegister("PointFunction",&PF_CLASSID);CHKERRQ(ierr);
547   /* Register Constructors */
548   ierr = PFRegisterAll(path);CHKERRQ(ierr);
549   /* Process info exclusions */
550   ierr = PetscOptionsGetString(PETSC_NULL, "-info_exclude", logList, 256, &opt);CHKERRQ(ierr);
551   if (opt) {
552     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
553     if (className) {
554       ierr = PetscInfoDeactivateClass(PF_CLASSID);CHKERRQ(ierr);
555     }
556   }
557   /* Process summary exclusions */
558   ierr = PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);CHKERRQ(ierr);
559   if (opt) {
560     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
561     if (className) {
562       ierr = PetscLogEventDeactivateClass(PF_CLASSID);CHKERRQ(ierr);
563     }
564   }
565   ierr = PetscRegisterFinalize(PFFinalizePackage);CHKERRQ(ierr);
566   PetscFunctionReturn(0);
567 }
568 
569 
570 
571 
572 
573 
574 
575 
576 
577