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