xref: /petsc/src/vec/pf/interface/pf.c (revision 2950f7e747d61362df6d6e1effb073d957ada526)
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 PetscClassId PF_CLASSID = 0;
9 
10 PetscFList PFList         = PETSC_NULL; /* list of all registered PD functions */
11 PetscBool  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,const PetscScalar*,PetscScalar*),PetscErrorCode (*applyvec)(void*,Vec,Vec),PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*destroy)(void*),void*ctx)
35 {
36   PetscFunctionBegin;
37   PetscValidHeaderSpecific(pf,PF_CLASSID,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   PetscBool      flg = PETSC_FALSE;
68 
69   PetscFunctionBegin;
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: 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_CLASSID,-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   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 PETSCVEC_DLLEXPORT 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 
173     ierr = VecDuplicate(y,&x);CHKERRQ(ierr);
174     nox  = PETSC_TRUE;
175     ierr = VecGetOwnershipRange(x,&rstart,&rend);CHKERRQ(ierr);
176     ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
177     for (i=rstart; i<rend; i++) {
178       xx[i-rstart] = (PetscScalar)i;
179     }
180     ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
181   }
182 
183   ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr);
184   ierr = VecGetLocalSize(y,&p);CHKERRQ(ierr);
185   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);
186   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);
187   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);
188 
189   if (pf->ops->applyvec) {
190     ierr = (*pf->ops->applyvec)(pf->data,x,y);CHKERRQ(ierr);
191   } else {
192     PetscScalar *xx,*yy;
193 
194     ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr);
195     n    = n/pf->dimin;
196     ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
197     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
198     if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
199     ierr = (*pf->ops->apply)(pf->data,n,xx,yy);CHKERRQ(ierr);
200     ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
201     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
202   }
203   if (nox) {
204     ierr = VecDestroy(x);CHKERRQ(ierr);
205   }
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "PFApply"
211 /*@
212    PFApply - Applies the mathematical function to an array of values.
213 
214    Collective on PF
215 
216    Input Parameters:
217 +  pf - the function context
218 .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
219        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
220        in the call to PFCreate()
221 -  x - input array
222 
223    Output Parameter:
224 .  y - output array
225 
226    Level: beginner
227 
228    Notes:
229 
230 .keywords: PF, apply
231 
232 .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
233 @*/
234 PetscErrorCode PETSCVEC_DLLEXPORT PFApply(PF pf,PetscInt n,const PetscScalar* x,PetscScalar* y)
235 {
236   PetscErrorCode ierr;
237 
238   PetscFunctionBegin;
239   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
240   PetscValidScalarPointer(x,2);
241   PetscValidScalarPointer(y,3);
242   if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different arrays");
243   if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
244 
245   ierr = (*pf->ops->apply)(pf->data,n,x,y);CHKERRQ(ierr);
246   PetscFunctionReturn(0);
247 }
248 
249 #undef __FUNCT__
250 #define __FUNCT__ "PFView"
251 /*@
252    PFView - Prints information about a mathematical function
253 
254    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
255 
256    Input Parameters:
257 +  PF - the PF context
258 -  viewer - optional visualization context
259 
260    Note:
261    The available visualization contexts include
262 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
263 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
264          output where only the first processor opens
265          the file.  All other processors send their
266          data to the first processor to print.
267 
268    The user can open an alternative visualization contexts with
269    PetscViewerASCIIOpen() (output to a specified file).
270 
271    Level: developer
272 
273 .keywords: PF, view
274 
275 .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
276 @*/
277 PetscErrorCode PETSCVEC_DLLEXPORT PFView(PF pf,PetscViewer viewer)
278 {
279   PetscErrorCode    ierr;
280   PetscBool         iascii;
281   PetscViewerFormat format;
282 
283   PetscFunctionBegin;
284   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
285   if (!viewer) {
286     ierr = PetscViewerASCIIGetStdout(((PetscObject)pf)->comm,&viewer);CHKERRQ(ierr);
287   }
288   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
289   PetscCheckSameComm(pf,1,viewer,2);
290 
291   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
292   if (iascii) {
293     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
294     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer,"PF Object");CHKERRQ(ierr);
295     if (pf->ops->view) {
296       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
297       ierr = (*pf->ops->view)(pf->data,viewer);CHKERRQ(ierr);
298       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
299     }
300   } else {
301     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
302   }
303   PetscFunctionReturn(0);
304 }
305 
306 /*MC
307    PFRegisterDynamic - Adds a method to the mathematical function package.
308 
309    Synopsis:
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 PETSCVEC_DLLEXPORT 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 = PetscFListConcat(path,name,fullname);CHKERRQ(ierr);
356   ierr = PetscFListAdd(&PFList,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 PETSCVEC_DLLEXPORT PFGetType(PF pf,const 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 PETSCVEC_DLLEXPORT PFSetType(PF pf,const 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 = PetscTypeCompare((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 =  PetscFListFind(PFList,((PetscObject)pf)->comm,type,(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 PETSCVEC_DLLEXPORT 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 = PetscOptionsBegin(((PetscObject)pf)->comm,((PetscObject)pf)->prefix,"Mathematical functions options","Vec");CHKERRQ(ierr);
480     ierr = PetscOptionsList("-pf_type","Type of function","PFSetType",PFList,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 PETSCVEC_DLLEXPORT PFFinalizePackage(void)
508 {
509   PetscFunctionBegin;
510   PFPackageInitialized = PETSC_FALSE;
511   PFList               = 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 PETSCVEC_DLLEXPORT 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