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