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