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