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