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