xref: /petsc/src/vec/pf/interface/pf.c (revision f98cea2c07897992b5b1217b65e95b08e1a8f673)
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 = VecInitializePackage(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 
392 
393 #undef __FUNCT__
394 #define __FUNCT__ "PFGetType"
395 /*@C
396    PFGetType - Gets the PF method type and name (as a string) from the PF
397    context.
398 
399    Not Collective
400 
401    Input Parameter:
402 .  pf - the function context
403 
404    Output Parameter:
405 .  name - name of function
406 
407    Level: intermediate
408 
409 .keywords: PF, get, method, name, type
410 
411 .seealso: PFSetType()
412 
413 @*/
414 PetscErrorCode PETSCVEC_DLLEXPORT PFGetType(PF pf,PFType *meth)
415 {
416   PetscFunctionBegin;
417   *meth = (PFType) pf->type_name;
418   PetscFunctionReturn(0);
419 }
420 
421 
422 #undef __FUNCT__
423 #define __FUNCT__ "PFSetType"
424 /*@C
425    PFSetType - Builds PF for a particular function
426 
427    Collective on PF
428 
429    Input Parameter:
430 +  pf - the function context.
431 .  type - a known method
432 -  ctx - optional type dependent context
433 
434    Options Database Key:
435 .  -pf_type <type> - Sets PF type
436 
437 
438   Notes:
439   See "petsc/include/petscpf.h" for available methods (for instance,
440   PFCONSTANT)
441 
442   Level: intermediate
443 
444 .keywords: PF, set, method, type
445 
446 .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DACreatePF()
447 
448 @*/
449 PetscErrorCode PETSCVEC_DLLEXPORT PFSetType(PF pf,PFType type,void *ctx)
450 {
451   PetscErrorCode ierr,(*r)(PF,void*);
452   PetscTruth match;
453 
454   PetscFunctionBegin;
455   PetscValidHeaderSpecific(pf,PF_COOKIE,1);
456   PetscValidCharPointer(type,2);
457 
458   ierr = PetscTypeCompare((PetscObject)pf,type,&match);CHKERRQ(ierr);
459   if (match) PetscFunctionReturn(0);
460 
461   if (pf->ops->destroy) {ierr =  (*pf->ops->destroy)(pf);CHKERRQ(ierr);}
462   pf->data        = 0;
463 
464   /* Get the function pointers for the method requested */
465   if (!PFRegisterAllCalled) {ierr = PFRegisterAll(0);CHKERRQ(ierr);}
466   /* Determine the PFCreateXXX routine for a particular function */
467   ierr =  PetscFListFind(pf->comm,PPetscFList,type,(void (**)(void)) &r);CHKERRQ(ierr);
468   if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
469   pf->ops->destroy             = 0;
470   pf->ops->view                = 0;
471   pf->ops->apply               = 0;
472   pf->ops->applyvec            = 0;
473 
474   /* Call the PFCreateXXX routine for this particular function */
475   ierr = (*r)(pf,ctx);CHKERRQ(ierr);
476 
477   ierr = PetscObjectChangeTypeName((PetscObject)pf,type);CHKERRQ(ierr);
478   PetscFunctionReturn(0);
479 }
480 
481 #undef __FUNCT__
482 #define __FUNCT__ "PFSetFromOptions"
483 /*@
484    PFSetFromOptions - Sets PF options from the options database.
485 
486    Collective on PF
487 
488    Input Parameters:
489 .  pf - the mathematical function context
490 
491    Options Database Keys:
492 
493    Notes:
494    To see all options, run your program with the -help option
495    or consult the users manual.
496 
497    Level: intermediate
498 
499 .keywords: PF, set, from, options, database
500 
501 .seealso:
502 @*/
503 PetscErrorCode PETSCVEC_DLLEXPORT PFSetFromOptions(PF pf)
504 {
505   PetscErrorCode ierr;
506   char       type[256];
507   PetscTruth flg;
508 
509   PetscFunctionBegin;
510   PetscValidHeaderSpecific(pf,PF_COOKIE,1);
511 
512   if (!PFRegisterAllCalled) {ierr = PFRegisterAll(0);CHKERRQ(ierr);}
513   ierr = PetscOptionsBegin(pf->comm,pf->prefix,"Mathematical functions options","Vec");CHKERRQ(ierr);
514     ierr = PetscOptionsList("-pf_type","Type of function","PFSetType",PPetscFList,0,type,256,&flg);CHKERRQ(ierr);
515     if (flg) {
516       ierr = PFSetType(pf,type,PETSC_NULL);CHKERRQ(ierr);
517     }
518     if (pf->ops->setfromoptions) {
519       ierr = (*pf->ops->setfromoptions)(pf);CHKERRQ(ierr);
520     }
521   ierr = PetscOptionsEnd();CHKERRQ(ierr);
522 
523   PetscFunctionReturn(0);
524 }
525 
526 
527 
528 
529 
530 
531 
532 
533 
534 
535