xref: /petsc/src/vec/pf/interface/pf.c (revision 277b19d07ec08e548e5816b82c213278d45c3326)
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   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
70   if (--((PetscObject)pf)->refct > 0) PetscFunctionReturn(0);
71 
72   ierr = PetscOptionsGetBool(((PetscObject)pf)->prefix,"-pf_view",&flg,PETSC_NULL);CHKERRQ(ierr);
73   if (flg) {
74     PetscViewer viewer;
75     ierr = PetscViewerASCIIGetStdout(((PetscObject)pf)->comm,&viewer);CHKERRQ(ierr);
76     ierr = PFView(pf,viewer);CHKERRQ(ierr);
77   }
78 
79   /* if memory was published with AMS then destroy it */
80   ierr = PetscObjectDepublish(pf);CHKERRQ(ierr);
81 
82   if (pf->ops->destroy) {ierr =  (*pf->ops->destroy)(pf->data);CHKERRQ(ierr);}
83   ierr = PetscHeaderDestroy(pf);CHKERRQ(ierr);
84   PetscFunctionReturn(0);
85 }
86 
87 #undef __FUNCT__
88 #define __FUNCT__ "PFCreate"
89 /*@C
90    PFCreate - Creates a mathematical function context.
91 
92    Collective on MPI_Comm
93 
94    Input Parameter:
95 +  comm - MPI communicator
96 .  dimin - dimension of the space you are mapping from
97 -  dimout - dimension of the space you are mapping to
98 
99    Output Parameter:
100 .  pf - the function context
101 
102    Level: developer
103 
104 .keywords: PF, create, context
105 
106 .seealso: PFSetUp(), PFApply(), PFDestroy(), PFApplyVec()
107 @*/
108 PetscErrorCode  PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
109 {
110   PF             newpf;
111   PetscErrorCode ierr;
112 
113   PetscFunctionBegin;
114   PetscValidPointer(pf,1);
115   *pf = PETSC_NULL;
116 #ifndef PETSC_USE_DYNAMIC_LIBRARIES
117   ierr = PFInitializePackage(PETSC_NULL);CHKERRQ(ierr);
118 #endif
119 
120   ierr = PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_CLASSID,-1,"PF",comm,PFDestroy,PFView);CHKERRQ(ierr);
121   newpf->data             = 0;
122 
123   newpf->ops->destroy     = 0;
124   newpf->ops->apply       = 0;
125   newpf->ops->applyvec    = 0;
126   newpf->ops->view        = 0;
127   newpf->dimin            = dimin;
128   newpf->dimout           = dimout;
129 
130   *pf                     = newpf;
131   PetscFunctionReturn(0);
132 
133 }
134 
135 /* -------------------------------------------------------------------------------*/
136 
137 #undef __FUNCT__
138 #define __FUNCT__ "PFApplyVec"
139 /*@
140    PFApplyVec - Applies the mathematical function to a vector
141 
142    Collective on PF
143 
144    Input Parameters:
145 +  pf - the function context
146 -  x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)
147 
148    Output Parameter:
149 .  y - output vector
150 
151    Level: beginner
152 
153 .keywords: PF, apply
154 
155 .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
156 @*/
157 PetscErrorCode  PFApplyVec(PF pf,Vec x,Vec y)
158 {
159   PetscErrorCode ierr;
160   PetscInt       i,rstart,rend,n,p;
161   PetscBool      nox = PETSC_FALSE;
162 
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
165   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
166   if (x) {
167     PetscValidHeaderSpecific(x,VEC_CLASSID,2);
168     if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors");
169   } else {
170     PetscScalar *xx;
171 
172     ierr = VecDuplicate(y,&x);CHKERRQ(ierr);
173     nox  = PETSC_TRUE;
174     ierr = VecGetOwnershipRange(x,&rstart,&rend);CHKERRQ(ierr);
175     ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
176     for (i=rstart; i<rend; i++) {
177       xx[i-rstart] = (PetscScalar)i;
178     }
179     ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
180   }
181 
182   ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr);
183   ierr = VecGetLocalSize(y,&p);CHKERRQ(ierr);
184   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);
185   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);
186   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);
187 
188   if (pf->ops->applyvec) {
189     ierr = (*pf->ops->applyvec)(pf->data,x,y);CHKERRQ(ierr);
190   } else {
191     PetscScalar *xx,*yy;
192 
193     ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr);
194     n    = n/pf->dimin;
195     ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
196     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
197     if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
198     ierr = (*pf->ops->apply)(pf->data,n,xx,yy);CHKERRQ(ierr);
199     ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
200     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
201   }
202   if (nox) {
203     ierr = VecDestroy(x);CHKERRQ(ierr);
204   }
205   PetscFunctionReturn(0);
206 }
207 
208 #undef __FUNCT__
209 #define __FUNCT__ "PFApply"
210 /*@
211    PFApply - Applies the mathematical function to an array of values.
212 
213    Collective on PF
214 
215    Input Parameters:
216 +  pf - the function context
217 .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
218        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
219        in the call to PFCreate()
220 -  x - input array
221 
222    Output Parameter:
223 .  y - output array
224 
225    Level: beginner
226 
227    Notes:
228 
229 .keywords: PF, apply
230 
231 .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
232 @*/
233 PetscErrorCode  PFApply(PF pf,PetscInt n,const PetscScalar* x,PetscScalar* y)
234 {
235   PetscErrorCode ierr;
236 
237   PetscFunctionBegin;
238   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
239   PetscValidScalarPointer(x,2);
240   PetscValidScalarPointer(y,3);
241   if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different arrays");
242   if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
243 
244   ierr = (*pf->ops->apply)(pf->data,n,x,y);CHKERRQ(ierr);
245   PetscFunctionReturn(0);
246 }
247 
248 #undef __FUNCT__
249 #define __FUNCT__ "PFView"
250 /*@
251    PFView - Prints information about a mathematical function
252 
253    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
254 
255    Input Parameters:
256 +  PF - the PF context
257 -  viewer - optional visualization context
258 
259    Note:
260    The available visualization contexts include
261 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
262 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
263          output where only the first processor opens
264          the file.  All other processors send their
265          data to the first processor to print.
266 
267    The user can open an alternative visualization contexts with
268    PetscViewerASCIIOpen() (output to a specified file).
269 
270    Level: developer
271 
272 .keywords: PF, view
273 
274 .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
275 @*/
276 PetscErrorCode  PFView(PF pf,PetscViewer viewer)
277 {
278   PetscErrorCode    ierr;
279   PetscBool         iascii;
280   PetscViewerFormat format;
281 
282   PetscFunctionBegin;
283   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
284   if (!viewer) {
285     ierr = PetscViewerASCIIGetStdout(((PetscObject)pf)->comm,&viewer);CHKERRQ(ierr);
286   }
287   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
288   PetscCheckSameComm(pf,1,viewer,2);
289 
290   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
291   if (iascii) {
292     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
293     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer,"PF Object");CHKERRQ(ierr);
294     if (pf->ops->view) {
295       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
296       ierr = (*pf->ops->view)(pf->data,viewer);CHKERRQ(ierr);
297       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
298     }
299   } else {
300     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
301   }
302   PetscFunctionReturn(0);
303 }
304 
305 /*MC
306    PFRegisterDynamic - Adds a method to the mathematical function package.
307 
308    Synopsis:
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 = PetscFListConcat(path,name,fullname);CHKERRQ(ierr);
355   ierr = PetscFListAdd(&PFList,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,const 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,const 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 = PetscTypeCompare((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 =  PetscFListFind(PFList,((PetscObject)pf)->comm,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 = PetscOptionsBegin(((PetscObject)pf)->comm,((PetscObject)pf)->prefix,"Mathematical functions options","Vec");CHKERRQ(ierr);
479     ierr = PetscOptionsList("-pf_type","Type of function","PFSetType",PFList,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 
491   PetscFunctionReturn(0);
492 }
493 
494 static PetscBool  PFPackageInitialized = PETSC_FALSE;
495 #undef __FUNCT__
496 #define __FUNCT__ "PFFinalizePackage"
497 /*@C
498   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
499   called from PetscFinalize().
500 
501   Level: developer
502 
503 .keywords: Petsc, destroy, package, mathematica
504 .seealso: PetscFinalize()
505 @*/
506 PetscErrorCode  PFFinalizePackage(void)
507 {
508   PetscFunctionBegin;
509   PFPackageInitialized = PETSC_FALSE;
510   PFList               = PETSC_NULL;
511   PFRegisterAllCalled  = PETSC_FALSE;
512   PetscFunctionReturn(0);
513 }
514 
515 #undef __FUNCT__
516 #define __FUNCT__ "PFInitializePackage"
517 /*@C
518   PFInitializePackage - This function initializes everything in the PF package. It is called
519   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
520   when using static libraries.
521 
522   Input Parameter:
523 . path - The dynamic library path, or PETSC_NULL
524 
525   Level: developer
526 
527 .keywords: Vec, initialize, package
528 .seealso: PetscInitialize()
529 @*/
530 PetscErrorCode  PFInitializePackage(const char path[])
531 {
532   char              logList[256];
533   char              *className;
534   PetscBool         opt;
535   PetscErrorCode    ierr;
536 
537   PetscFunctionBegin;
538   if (PFPackageInitialized) PetscFunctionReturn(0);
539   PFPackageInitialized = PETSC_TRUE;
540   /* Register Classes */
541   ierr = PetscClassIdRegister("PointFunction",&PF_CLASSID);CHKERRQ(ierr);
542   /* Register Constructors */
543   ierr = PFRegisterAll(path);CHKERRQ(ierr);
544   /* Process info exclusions */
545   ierr = PetscOptionsGetString(PETSC_NULL, "-info_exclude", logList, 256, &opt);CHKERRQ(ierr);
546   if (opt) {
547     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
548     if (className) {
549       ierr = PetscInfoDeactivateClass(PF_CLASSID);CHKERRQ(ierr);
550     }
551   }
552   /* Process summary exclusions */
553   ierr = PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);CHKERRQ(ierr);
554   if (opt) {
555     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
556     if (className) {
557       ierr = PetscLogEventDeactivateClass(PF_CLASSID);CHKERRQ(ierr);
558     }
559   }
560   ierr = PetscRegisterFinalize(PFFinalizePackage);CHKERRQ(ierr);
561   PetscFunctionReturn(0);
562 }
563 
564 
565 
566 
567 
568 
569 
570 
571 
572