xref: /petsc/src/vec/pf/interface/pf.c (revision 8738c82190ebad3f707cdf672b6e3396bec82bba)
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 PetscTruth 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,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   PetscTruth     flg = PETSC_FALSE;
68 
69   PetscFunctionBegin;
70   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
71   if (--((PetscObject)pf)->refct > 0) PetscFunctionReturn(0);
72 
73   ierr = PetscOptionsGetTruth(((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   ierr = PetscPublishAll(pf);CHKERRQ(ierr);
133   PetscFunctionReturn(0);
134 
135 }
136 
137 /* -------------------------------------------------------------------------------*/
138 
139 #undef __FUNCT__
140 #define __FUNCT__ "PFApplyVec"
141 /*@
142    PFApplyVec - Applies the mathematical function to a vector
143 
144    Collective on PF
145 
146    Input Parameters:
147 +  pf - the function context
148 -  x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)
149 
150    Output Parameter:
151 .  y - output vector
152 
153    Level: beginner
154 
155 .keywords: PF, apply
156 
157 .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
158 @*/
159 PetscErrorCode PETSCVEC_DLLEXPORT PFApplyVec(PF pf,Vec x,Vec y)
160 {
161   PetscErrorCode ierr;
162   PetscInt       i,rstart,rend,n,p;
163   PetscTruth     nox = PETSC_FALSE;
164 
165   PetscFunctionBegin;
166   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
167   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
168   if (x) {
169     PetscValidHeaderSpecific(x,VEC_CLASSID,2);
170     if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors");
171   } else {
172     PetscScalar *xx;
173 
174     ierr = VecDuplicate(y,&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 PETSCVEC_DLLEXPORT PFApply(PF pf,PetscInt n,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 PETSCVEC_DLLEXPORT PFView(PF pf,PetscViewer viewer)
279 {
280   const PFType      cstr;
281   PetscErrorCode    ierr;
282   PetscTruth        iascii;
283   PetscViewerFormat format;
284 
285   PetscFunctionBegin;
286   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
287   if (!viewer) {
288     ierr = PetscViewerASCIIGetStdout(((PetscObject)pf)->comm,&viewer);CHKERRQ(ierr);
289   }
290   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
291   PetscCheckSameComm(pf,1,viewer,2);
292 
293   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
294   if (iascii) {
295     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
296     ierr = PetscViewerASCIIPrintf(viewer,"PF Object:\n");CHKERRQ(ierr);
297     ierr = PFGetType(pf,&cstr);CHKERRQ(ierr);
298     if (cstr) {
299       ierr = PetscViewerASCIIPrintf(viewer,"  type: %s\n",cstr);CHKERRQ(ierr);
300     } else {
301       ierr = PetscViewerASCIIPrintf(viewer,"  type: not yet set\n");CHKERRQ(ierr);
302     }
303     if (pf->ops->view) {
304       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
305       ierr = (*pf->ops->view)(pf->data,viewer);CHKERRQ(ierr);
306       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
307     }
308   } else {
309     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
310   }
311   PetscFunctionReturn(0);
312 }
313 
314 /*MC
315    PFRegisterDynamic - Adds a method to the mathematical function package.
316 
317    Synopsis:
318    PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))
319 
320    Not collective
321 
322    Input Parameters:
323 +  name_solver - name of a new user-defined solver
324 .  path - path (either absolute or relative) the library containing this solver
325 .  name_create - name of routine to create method context
326 -  routine_create - routine to create method context
327 
328    Notes:
329    PFRegisterDynamic() may be called multiple times to add several user-defined functions
330 
331    If dynamic libraries are used, then the fourth input argument (routine_create)
332    is ignored.
333 
334    Sample usage:
335 .vb
336    PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
337               "MyFunctionCreate",MyFunctionSetCreate);
338 .ve
339 
340    Then, your solver can be chosen with the procedural interface via
341 $     PFSetType(pf,"my_function")
342    or at runtime via the option
343 $     -pf_type my_function
344 
345    Level: advanced
346 
347    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
348  occuring in pathname will be replaced with appropriate values.
349 
350 .keywords: PF, register
351 
352 .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
353 M*/
354 
355 #undef __FUNCT__
356 #define __FUNCT__ "PFRegister"
357 PetscErrorCode PETSCVEC_DLLEXPORT PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
358 {
359   PetscErrorCode ierr;
360   char           fullname[PETSC_MAX_PATH_LEN];
361 
362   PetscFunctionBegin;
363   ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr);
364   ierr = PetscFListAdd(&PFList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr);
365   PetscFunctionReturn(0);
366 }
367 
368 #undef __FUNCT__
369 #define __FUNCT__ "PFGetType"
370 /*@C
371    PFGetType - Gets the PF method type and name (as a string) from the PF
372    context.
373 
374    Not Collective
375 
376    Input Parameter:
377 .  pf - the function context
378 
379    Output Parameter:
380 .  type - name of function
381 
382    Level: intermediate
383 
384 .keywords: PF, get, method, name, type
385 
386 .seealso: PFSetType()
387 
388 @*/
389 PetscErrorCode PETSCVEC_DLLEXPORT PFGetType(PF pf,const PFType *type)
390 {
391   PetscFunctionBegin;
392   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
393   PetscValidPointer(type,2);
394   *type = ((PetscObject)pf)->type_name;
395   PetscFunctionReturn(0);
396 }
397 
398 
399 #undef __FUNCT__
400 #define __FUNCT__ "PFSetType"
401 /*@C
402    PFSetType - Builds PF for a particular function
403 
404    Collective on PF
405 
406    Input Parameter:
407 +  pf - the function context.
408 .  type - a known method
409 -  ctx - optional type dependent context
410 
411    Options Database Key:
412 .  -pf_type <type> - Sets PF type
413 
414 
415   Notes:
416   See "petsc/include/petscpf.h" for available methods (for instance,
417   PFCONSTANT)
418 
419   Level: intermediate
420 
421 .keywords: PF, set, method, type
422 
423 .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DACreatePF()
424 
425 @*/
426 PetscErrorCode PETSCVEC_DLLEXPORT PFSetType(PF pf,const PFType type,void *ctx)
427 {
428   PetscErrorCode ierr,(*r)(PF,void*);
429   PetscTruth     match;
430 
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
433   PetscValidCharPointer(type,2);
434 
435   ierr = PetscTypeCompare((PetscObject)pf,type,&match);CHKERRQ(ierr);
436   if (match) PetscFunctionReturn(0);
437 
438   if (pf->ops->destroy) {ierr =  (*pf->ops->destroy)(pf);CHKERRQ(ierr);}
439   pf->data        = 0;
440 
441   /* Determine the PFCreateXXX routine for a particular function */
442   ierr =  PetscFListFind(PFList,((PetscObject)pf)->comm,type,(void (**)(void)) &r);CHKERRQ(ierr);
443   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
444   pf->ops->destroy             = 0;
445   pf->ops->view                = 0;
446   pf->ops->apply               = 0;
447   pf->ops->applyvec            = 0;
448 
449   /* Call the PFCreateXXX routine for this particular function */
450   ierr = (*r)(pf,ctx);CHKERRQ(ierr);
451 
452   ierr = PetscObjectChangeTypeName((PetscObject)pf,type);CHKERRQ(ierr);
453   PetscFunctionReturn(0);
454 }
455 
456 #undef __FUNCT__
457 #define __FUNCT__ "PFSetFromOptions"
458 /*@
459    PFSetFromOptions - Sets PF options from the options database.
460 
461    Collective on PF
462 
463    Input Parameters:
464 .  pf - the mathematical function context
465 
466    Options Database Keys:
467 
468    Notes:
469    To see all options, run your program with the -help option
470    or consult the users manual.
471 
472    Level: intermediate
473 
474 .keywords: PF, set, from, options, database
475 
476 .seealso:
477 @*/
478 PetscErrorCode PETSCVEC_DLLEXPORT PFSetFromOptions(PF pf)
479 {
480   PetscErrorCode ierr;
481   char           type[256];
482   PetscTruth     flg;
483 
484   PetscFunctionBegin;
485   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
486 
487   ierr = PetscOptionsBegin(((PetscObject)pf)->comm,((PetscObject)pf)->prefix,"Mathematical functions options","Vec");CHKERRQ(ierr);
488     ierr = PetscOptionsList("-pf_type","Type of function","PFSetType",PFList,0,type,256,&flg);CHKERRQ(ierr);
489     if (flg) {
490       ierr = PFSetType(pf,type,PETSC_NULL);CHKERRQ(ierr);
491     }
492     if (pf->ops->setfromoptions) {
493       ierr = (*pf->ops->setfromoptions)(pf);CHKERRQ(ierr);
494     }
495 
496     /* process any options handlers added with PetscObjectAddOptionsHandler() */
497     ierr = PetscObjectProcessOptionsHandlers((PetscObject)pf);CHKERRQ(ierr);
498   ierr = PetscOptionsEnd();CHKERRQ(ierr);
499 
500   PetscFunctionReturn(0);
501 }
502 
503 static PetscTruth PFPackageInitialized = PETSC_FALSE;
504 #undef __FUNCT__
505 #define __FUNCT__ "PFFinalizePackage"
506 /*@C
507   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
508   called from PetscFinalize().
509 
510   Level: developer
511 
512 .keywords: Petsc, destroy, package, mathematica
513 .seealso: PetscFinalize()
514 @*/
515 PetscErrorCode PETSCVEC_DLLEXPORT PFFinalizePackage(void)
516 {
517   PetscFunctionBegin;
518   PFPackageInitialized = PETSC_FALSE;
519   PFList               = PETSC_NULL;
520   PFRegisterAllCalled  = PETSC_FALSE;
521   PetscFunctionReturn(0);
522 }
523 
524 #undef __FUNCT__
525 #define __FUNCT__ "PFInitializePackage"
526 /*@C
527   PFInitializePackage - This function initializes everything in the PF package. It is called
528   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
529   when using static libraries.
530 
531   Input Parameter:
532 . path - The dynamic library path, or PETSC_NULL
533 
534   Level: developer
535 
536 .keywords: Vec, initialize, package
537 .seealso: PetscInitialize()
538 @*/
539 PetscErrorCode PETSCVEC_DLLEXPORT PFInitializePackage(const char path[])
540 {
541   char              logList[256];
542   char              *className;
543   PetscTruth        opt;
544   PetscErrorCode    ierr;
545 
546   PetscFunctionBegin;
547   if (PFPackageInitialized) PetscFunctionReturn(0);
548   PFPackageInitialized = PETSC_TRUE;
549   /* Register Classes */
550   ierr = PetscClassIdRegister("PointFunction",&PF_CLASSID);CHKERRQ(ierr);
551   /* Register Constructors */
552   ierr = PFRegisterAll(path);CHKERRQ(ierr);
553   /* Process info exclusions */
554   ierr = PetscOptionsGetString(PETSC_NULL, "-info_exclude", logList, 256, &opt);CHKERRQ(ierr);
555   if (opt) {
556     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
557     if (className) {
558       ierr = PetscInfoDeactivateClass(PF_CLASSID);CHKERRQ(ierr);
559     }
560   }
561   /* Process summary exclusions */
562   ierr = PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);CHKERRQ(ierr);
563   if (opt) {
564     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
565     if (className) {
566       ierr = PetscLogEventDeactivateClass(PF_CLASSID);CHKERRQ(ierr);
567     }
568   }
569   ierr = PetscRegisterFinalize(PFFinalizePackage);CHKERRQ(ierr);
570   PetscFunctionReturn(0);
571 }
572 
573 
574 
575 
576 
577 
578 
579 
580 
581