xref: /petsc/src/vec/pf/interface/pf.c (revision a58c3bc3391eee32bc3fd94ac7edeea38fe57aae)
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 PetscCookie PF_COOKIE = 0;
9 
10 PetscFList PPetscFList         = 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_COOKIE,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;
68 
69   PetscFunctionBegin;
70   PetscValidHeaderSpecific(pf,PF_COOKIE,1);
71   if (--pf->refct > 0) PetscFunctionReturn(0);
72 
73   ierr = PetscOptionsHasName(pf->prefix,"-pf_view",&flg);CHKERRQ(ierr);
74   if (flg) {
75     PetscViewer viewer;
76     ierr = PetscViewerASCIIGetStdout(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__ "PFPublish_Petsc"
90 static PetscErrorCode PFPublish_Petsc(PetscObject obj)
91 {
92 #if defined(PETSC_HAVE_AMS)
93   PF              v = (PF) obj;
94   PetscErrorCode ierr;
95 #endif
96 
97   PetscFunctionBegin;
98 
99 #if defined(PETSC_HAVE_AMS)
100   /* if it is already published then return */
101   if (v->amem >=0) PetscFunctionReturn(0);
102 
103   ierr = PetscObjectPublishBaseBegin(obj);CHKERRQ(ierr);
104   ierr = PetscObjectPublishBaseEnd(obj);CHKERRQ(ierr);
105 #endif
106 
107   PetscFunctionReturn(0);
108 }
109 
110 #undef __FUNCT__
111 #define __FUNCT__ "PFCreate"
112 /*@C
113    PFCreate - Creates a mathematical function context.
114 
115    Collective on MPI_Comm
116 
117    Input Parameter:
118 +  comm - MPI communicator
119 .  dimin - dimension of the space you are mapping from
120 -  dimout - dimension of the space you are mapping to
121 
122    Output Parameter:
123 .  pf - the function context
124 
125    Level: developer
126 
127 .keywords: PF, create, context
128 
129 .seealso: PFSetUp(), PFApply(), PFDestroy(), PFApplyVec()
130 @*/
131 PetscErrorCode PETSCVEC_DLLEXPORT PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
132 {
133   PF             newpf;
134   PetscErrorCode ierr;
135 
136   PetscFunctionBegin;
137   PetscValidPointer(pf,1);
138   *pf = PETSC_NULL;
139 #ifndef PETSC_USE_DYNAMIC_LIBRARIES
140   ierr = PFInitializePackage(PETSC_NULL);CHKERRQ(ierr);
141 #endif
142 
143   ierr = PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_COOKIE,-1,"PF",comm,PFDestroy,PFView);CHKERRQ(ierr);
144   newpf->bops->publish    = PFPublish_Petsc;
145   newpf->data             = 0;
146 
147   newpf->ops->destroy     = 0;
148   newpf->ops->apply       = 0;
149   newpf->ops->applyvec    = 0;
150   newpf->ops->view        = 0;
151   newpf->dimin            = dimin;
152   newpf->dimout           = dimout;
153 
154   *pf                     = newpf;
155   ierr = PetscPublishAll(pf);CHKERRQ(ierr);
156   PetscFunctionReturn(0);
157 
158 }
159 
160 /* -------------------------------------------------------------------------------*/
161 
162 #undef __FUNCT__
163 #define __FUNCT__ "PFApplyVec"
164 /*@
165    PFApplyVec - Applies the mathematical function to a vector
166 
167    Collective on PF
168 
169    Input Parameters:
170 +  pf - the function context
171 -  x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)
172 
173    Output Parameter:
174 .  y - output vector
175 
176    Level: beginner
177 
178 .keywords: PF, apply
179 
180 .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
181 @*/
182 PetscErrorCode PETSCVEC_DLLEXPORT PFApplyVec(PF pf,Vec x,Vec y)
183 {
184   PetscErrorCode ierr;
185   PetscInt       i,rstart,rend,n,p;
186   PetscTruth     nox = PETSC_FALSE;
187 
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(pf,PF_COOKIE,1);
190   PetscValidHeaderSpecific(y,VEC_COOKIE,3);
191   if (x) {
192     PetscValidHeaderSpecific(x,VEC_COOKIE,2);
193     if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
194   } else {
195     PetscScalar *xx;
196 
197     ierr = VecDuplicate(y,&x);CHKERRQ(ierr);
198     nox  = PETSC_TRUE;
199     ierr = VecGetOwnershipRange(x,&rstart,&rend);CHKERRQ(ierr);
200     ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
201     for (i=rstart; i<rend; i++) {
202       xx[i-rstart] = (PetscScalar)i;
203     }
204     ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
205   }
206 
207   ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr);
208   ierr = VecGetLocalSize(y,&p);CHKERRQ(ierr);
209   if ((pf->dimin*(n/pf->dimin)) != n) SETERRQ2(PETSC_ERR_ARG_SIZ,"Local input vector length %D not divisible by dimin %D of function",n,pf->dimin);
210   if ((pf->dimout*(p/pf->dimout)) != p) SETERRQ2(PETSC_ERR_ARG_SIZ,"Local output vector length %D not divisible by dimout %D of function",p,pf->dimout);
211   if ((n/pf->dimin) != (p/pf->dimout)) SETERRQ4(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);
212 
213   if (pf->ops->applyvec) {
214     ierr = (*pf->ops->applyvec)(pf->data,x,y);CHKERRQ(ierr);
215   } else {
216     PetscScalar *xx,*yy;
217 
218     ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr);
219     n    = n/pf->dimin;
220     ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
221     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
222     if (!pf->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
223     ierr = (*pf->ops->apply)(pf->data,n,xx,yy);CHKERRQ(ierr);
224     ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
225     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
226   }
227   if (nox) {
228     ierr = VecDestroy(x);CHKERRQ(ierr);
229   }
230   PetscFunctionReturn(0);
231 }
232 
233 #undef __FUNCT__
234 #define __FUNCT__ "PFApply"
235 /*@
236    PFApply - Applies the mathematical function to an array of values.
237 
238    Collective on PF
239 
240    Input Parameters:
241 +  pf - the function context
242 .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
243        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
244        in the call to PFCreate()
245 -  x - input array
246 
247    Output Parameter:
248 .  y - output array
249 
250    Level: beginner
251 
252    Notes:
253 
254 .keywords: PF, apply
255 
256 .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
257 @*/
258 PetscErrorCode PETSCVEC_DLLEXPORT PFApply(PF pf,PetscInt n,PetscScalar* x,PetscScalar* y)
259 {
260   PetscErrorCode ierr;
261 
262   PetscFunctionBegin;
263   PetscValidHeaderSpecific(pf,PF_COOKIE,1);
264   PetscValidScalarPointer(x,2);
265   PetscValidScalarPointer(y,3);
266   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different arrays");
267   if (!pf->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
268 
269   ierr = (*pf->ops->apply)(pf->data,n,x,y);CHKERRQ(ierr);
270   PetscFunctionReturn(0);
271 }
272 
273 #undef __FUNCT__
274 #define __FUNCT__ "PFView"
275 /*@
276    PFView - Prints information about a mathematical function
277 
278    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
279 
280    Input Parameters:
281 +  PF - the PF context
282 -  viewer - optional visualization context
283 
284    Note:
285    The available visualization contexts include
286 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
287 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
288          output where only the first processor opens
289          the file.  All other processors send their
290          data to the first processor to print.
291 
292    The user can open an alternative visualization contexts with
293    PetscViewerASCIIOpen() (output to a specified file).
294 
295    Level: developer
296 
297 .keywords: PF, view
298 
299 .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
300 @*/
301 PetscErrorCode PETSCVEC_DLLEXPORT PFView(PF pf,PetscViewer viewer)
302 {
303   PFType            cstr;
304   PetscErrorCode    ierr;
305   PetscTruth        iascii;
306   PetscViewerFormat format;
307 
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(pf,PF_COOKIE,1);
310   if (!viewer) {
311     ierr = PetscViewerASCIIGetStdout(pf->comm,&viewer);CHKERRQ(ierr);
312   }
313   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2);
314   PetscCheckSameComm(pf,1,viewer,2);
315 
316   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
317   if (iascii) {
318     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
319     ierr = PetscViewerASCIIPrintf(viewer,"PF Object:\n");CHKERRQ(ierr);
320     ierr = PFGetType(pf,&cstr);CHKERRQ(ierr);
321     if (cstr) {
322       ierr = PetscViewerASCIIPrintf(viewer,"  type: %s\n",cstr);CHKERRQ(ierr);
323     } else {
324       ierr = PetscViewerASCIIPrintf(viewer,"  type: not yet set\n");CHKERRQ(ierr);
325     }
326     if (pf->ops->view) {
327       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
328       ierr = (*pf->ops->view)(pf->data,viewer);CHKERRQ(ierr);
329       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
330     }
331   } else {
332     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
333   }
334   PetscFunctionReturn(0);
335 }
336 
337 /*MC
338    PFRegisterDynamic - Adds a method to the mathematical function package.
339 
340    Synopsis:
341    PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))
342 
343    Not collective
344 
345    Input Parameters:
346 +  name_solver - name of a new user-defined solver
347 .  path - path (either absolute or relative) the library containing this solver
348 .  name_create - name of routine to create method context
349 -  routine_create - routine to create method context
350 
351    Notes:
352    PFRegisterDynamic() may be called multiple times to add several user-defined functions
353 
354    If dynamic libraries are used, then the fourth input argument (routine_create)
355    is ignored.
356 
357    Sample usage:
358 .vb
359    PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
360               "MyFunctionCreate",MyFunctionSetCreate);
361 .ve
362 
363    Then, your solver can be chosen with the procedural interface via
364 $     PFSetType(pf,"my_function")
365    or at runtime via the option
366 $     -pf_type my_function
367 
368    Level: advanced
369 
370    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
371  occuring in pathname will be replaced with appropriate values.
372 
373 .keywords: PF, register
374 
375 .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
376 M*/
377 
378 #undef __FUNCT__
379 #define __FUNCT__ "PFRegister"
380 PetscErrorCode PETSCVEC_DLLEXPORT PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
381 {
382   PetscErrorCode ierr;
383   char           fullname[PETSC_MAX_PATH_LEN];
384 
385   PetscFunctionBegin;
386   ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr);
387   ierr = PetscFListAdd(&PPetscFList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr);
388   PetscFunctionReturn(0);
389 }
390 
391 #undef __FUNCT__
392 #define __FUNCT__ "PFGetType"
393 /*@C
394    PFGetType - Gets the PF method type and name (as a string) from the PF
395    context.
396 
397    Not Collective
398 
399    Input Parameter:
400 .  pf - the function context
401 
402    Output Parameter:
403 .  name - name of function
404 
405    Level: intermediate
406 
407 .keywords: PF, get, method, name, type
408 
409 .seealso: PFSetType()
410 
411 @*/
412 PetscErrorCode PETSCVEC_DLLEXPORT PFGetType(PF pf,PFType *meth)
413 {
414   PetscFunctionBegin;
415   *meth = (PFType) pf->type_name;
416   PetscFunctionReturn(0);
417 }
418 
419 
420 #undef __FUNCT__
421 #define __FUNCT__ "PFSetType"
422 /*@C
423    PFSetType - Builds PF for a particular function
424 
425    Collective on PF
426 
427    Input Parameter:
428 +  pf - the function context.
429 .  type - a known method
430 -  ctx - optional type dependent context
431 
432    Options Database Key:
433 .  -pf_type <type> - Sets PF type
434 
435 
436   Notes:
437   See "petsc/include/petscpf.h" for available methods (for instance,
438   PFCONSTANT)
439 
440   Level: intermediate
441 
442 .keywords: PF, set, method, type
443 
444 .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DACreatePF()
445 
446 @*/
447 PetscErrorCode PETSCVEC_DLLEXPORT PFSetType(PF pf,PFType type,void *ctx)
448 {
449   PetscErrorCode ierr,(*r)(PF,void*);
450   PetscTruth     match;
451 
452   PetscFunctionBegin;
453   PetscValidHeaderSpecific(pf,PF_COOKIE,1);
454   PetscValidCharPointer(type,2);
455 
456   ierr = PetscTypeCompare((PetscObject)pf,type,&match);CHKERRQ(ierr);
457   if (match) PetscFunctionReturn(0);
458 
459   if (pf->ops->destroy) {ierr =  (*pf->ops->destroy)(pf);CHKERRQ(ierr);}
460   pf->data        = 0;
461 
462   /* Determine the PFCreateXXX routine for a particular function */
463   ierr =  PetscFListFind(pf->comm,PPetscFList,type,(void (**)(void)) &r);CHKERRQ(ierr);
464   if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
465   pf->ops->destroy             = 0;
466   pf->ops->view                = 0;
467   pf->ops->apply               = 0;
468   pf->ops->applyvec            = 0;
469 
470   /* Call the PFCreateXXX routine for this particular function */
471   ierr = (*r)(pf,ctx);CHKERRQ(ierr);
472 
473   ierr = PetscObjectChangeTypeName((PetscObject)pf,type);CHKERRQ(ierr);
474   PetscFunctionReturn(0);
475 }
476 
477 #undef __FUNCT__
478 #define __FUNCT__ "PFSetFromOptions"
479 /*@
480    PFSetFromOptions - Sets PF options from the options database.
481 
482    Collective on PF
483 
484    Input Parameters:
485 .  pf - the mathematical function context
486 
487    Options Database Keys:
488 
489    Notes:
490    To see all options, run your program with the -help option
491    or consult the users manual.
492 
493    Level: intermediate
494 
495 .keywords: PF, set, from, options, database
496 
497 .seealso:
498 @*/
499 PetscErrorCode PETSCVEC_DLLEXPORT PFSetFromOptions(PF pf)
500 {
501   PetscErrorCode ierr;
502   char           type[256];
503   PetscTruth     flg;
504 
505   PetscFunctionBegin;
506   PetscValidHeaderSpecific(pf,PF_COOKIE,1);
507 
508   ierr = PetscOptionsBegin(pf->comm,pf->prefix,"Mathematical functions options","Vec");CHKERRQ(ierr);
509     ierr = PetscOptionsList("-pf_type","Type of function","PFSetType",PPetscFList,0,type,256,&flg);CHKERRQ(ierr);
510     if (flg) {
511       ierr = PFSetType(pf,type,PETSC_NULL);CHKERRQ(ierr);
512     }
513     if (pf->ops->setfromoptions) {
514       ierr = (*pf->ops->setfromoptions)(pf);CHKERRQ(ierr);
515     }
516   ierr = PetscOptionsEnd();CHKERRQ(ierr);
517 
518   PetscFunctionReturn(0);
519 }
520 
521 #undef __FUNCT__
522 #define __FUNCT__ "PFInitializePackage"
523 /*@C
524   PFInitializePackage - This function initializes everything in the PF package. It is called
525   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
526   when using static libraries.
527 
528   Input Parameter:
529 . path - The dynamic library path, or PETSC_NULL
530 
531   Level: developer
532 
533 .keywords: Vec, initialize, package
534 .seealso: PetscInitialize()
535 @*/
536 PetscErrorCode PETSCVEC_DLLEXPORT PFInitializePackage(const char path[])
537 {
538   static PetscTruth initialized = PETSC_FALSE;
539   char              logList[256];
540   char              *className;
541   PetscTruth        opt;
542   PetscErrorCode    ierr;
543 
544   PetscFunctionBegin;
545   if (initialized) PetscFunctionReturn(0);
546   initialized = PETSC_TRUE;
547   /* Register Classes */
548   ierr = PetscLogClassRegister(&PF_COOKIE,          "PointFunction");CHKERRQ(ierr);
549   /* Register Constructors */
550   ierr = PFRegisterAll(path);CHKERRQ(ierr);
551   /* Process info exclusions */
552   ierr = PetscOptionsGetString(PETSC_NULL, "-info_exclude", logList, 256, &opt);CHKERRQ(ierr);
553   if (opt) {
554     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
555     if (className) {
556       ierr = PetscInfoDeactivateClass(PF_COOKIE);CHKERRQ(ierr);
557     }
558   }
559   /* Process summary exclusions */
560   ierr = PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);CHKERRQ(ierr);
561   if (opt) {
562     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
563     if (className) {
564       ierr = PetscLogEventDeactivateClass(PF_COOKIE);CHKERRQ(ierr);
565     }
566   }
567   PetscFunctionReturn(0);
568 }
569 
570 
571 
572 
573 
574 
575 
576 
577 
578