xref: /petsc/src/vec/pf/interface/pf.c (revision d4349b43d0d4ff02ef13c3807514f83c985fc1e9)
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 PetscClassId      PF_CLASSID          = 0;
7 PetscFunctionList PFunctionList       = NULL;   /* list of all registered PD functions */
8 PetscBool         PFRegisterAllCalled = PETSC_FALSE;
9 
10 #undef __FUNCT__
11 #define __FUNCT__ "PFSet"
12 /*@C
13    PFSet - Sets the C/C++/Fortran functions to be used by the PF function
14 
15    Collective on PF
16 
17    Input Parameter:
18 +  pf - the function context
19 .  apply - function to apply to an array
20 .  applyvec - function to apply to a Vec
21 .  view - function that prints information about the PF
22 .  destroy - function to free the private function context
23 -  ctx - private function context
24 
25    Level: beginner
26 
27 .keywords: PF, setting
28 
29 .seealso: PFCreate(), PFDestroy(), PFSetType(), PFApply(), PFApplyVec()
30 @*/
31 PetscErrorCode  PFSet(PF pf,PetscErrorCode (*apply)(void*,PetscInt,const PetscScalar*,PetscScalar*),PetscErrorCode (*applyvec)(void*,Vec,Vec),PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*destroy)(void*),void*ctx)
32 {
33   PetscFunctionBegin;
34   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
35   pf->data          = ctx;
36   pf->ops->destroy  = destroy;
37   pf->ops->apply    = apply;
38   pf->ops->applyvec = applyvec;
39   pf->ops->view     = view;
40   PetscFunctionReturn(0);
41 }
42 
43 #undef __FUNCT__
44 #define __FUNCT__ "PFDestroy"
45 /*@C
46    PFDestroy - Destroys PF context that was created with PFCreate().
47 
48    Collective on PF
49 
50    Input Parameter:
51 .  pf - the function context
52 
53    Level: beginner
54 
55 .keywords: PF, destroy
56 
57 .seealso: PFCreate(), PFSet(), PFSetType()
58 @*/
59 PetscErrorCode  PFDestroy(PF *pf)
60 {
61   PetscErrorCode ierr;
62   PetscBool      flg = PETSC_FALSE;
63 
64   PetscFunctionBegin;
65   if (!*pf) PetscFunctionReturn(0);
66   PetscValidHeaderSpecific((*pf),PF_CLASSID,1);
67   if (--((PetscObject)(*pf))->refct > 0) PetscFunctionReturn(0);
68 
69   ierr = PetscOptionsGetBool(((PetscObject)(*pf))->prefix,"-pf_view",&flg,NULL);CHKERRQ(ierr);
70   if (flg) {
71     PetscViewer viewer;
72     ierr = PetscViewerASCIIGetStdout(((PetscObject)(*pf))->comm,&viewer);CHKERRQ(ierr);
73     ierr = PFView((*pf),viewer);CHKERRQ(ierr);
74   }
75 
76   /* if memory was published with AMS then destroy it */
77   ierr = PetscObjectAMSViewOff((PetscObject)*pf);CHKERRQ(ierr);
78 
79   if ((*pf)->ops->destroy) {ierr =  (*(*pf)->ops->destroy)((*pf)->data);CHKERRQ(ierr);}
80   ierr = PetscHeaderDestroy(pf);CHKERRQ(ierr);
81   PetscFunctionReturn(0);
82 }
83 
84 #undef __FUNCT__
85 #define __FUNCT__ "PFCreate"
86 /*@C
87    PFCreate - Creates a mathematical function context.
88 
89    Collective on MPI_Comm
90 
91    Input Parameter:
92 +  comm - MPI communicator
93 .  dimin - dimension of the space you are mapping from
94 -  dimout - dimension of the space you are mapping to
95 
96    Output Parameter:
97 .  pf - the function context
98 
99    Level: developer
100 
101 .keywords: PF, create, context
102 
103 .seealso: PFSet(), PFApply(), PFDestroy(), PFApplyVec()
104 @*/
105 PetscErrorCode  PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
106 {
107   PF             newpf;
108   PetscErrorCode ierr;
109 
110   PetscFunctionBegin;
111   PetscValidPointer(pf,1);
112   *pf = NULL;
113 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
114   ierr = PFInitializePackage();CHKERRQ(ierr);
115 #endif
116 
117   ierr = PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_CLASSID,"PF","Mathematical functions","Vec",comm,PFDestroy,PFView);CHKERRQ(ierr);
118   newpf->data          = 0;
119   newpf->ops->destroy  = 0;
120   newpf->ops->apply    = 0;
121   newpf->ops->applyvec = 0;
122   newpf->ops->view     = 0;
123   newpf->dimin         = dimin;
124   newpf->dimout        = dimout;
125 
126   *pf                  = newpf;
127   PetscFunctionReturn(0);
128 
129 }
130 
131 /* -------------------------------------------------------------------------------*/
132 
133 #undef __FUNCT__
134 #define __FUNCT__ "PFApplyVec"
135 /*@
136    PFApplyVec - Applies the mathematical function to a vector
137 
138    Collective on PF
139 
140    Input Parameters:
141 +  pf - the function context
142 -  x - input vector (or NULL for the vector (0,1, .... N-1)
143 
144    Output Parameter:
145 .  y - output vector
146 
147    Level: beginner
148 
149 .keywords: PF, apply
150 
151 .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
152 @*/
153 PetscErrorCode  PFApplyVec(PF pf,Vec x,Vec y)
154 {
155   PetscErrorCode ierr;
156   PetscInt       i,rstart,rend,n,p;
157   PetscBool      nox = PETSC_FALSE;
158 
159   PetscFunctionBegin;
160   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
161   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
162   if (x) {
163     PetscValidHeaderSpecific(x,VEC_CLASSID,2);
164     if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors");
165   } else {
166     PetscScalar *xx;
167     PetscInt    lsize;
168 
169     ierr  = VecGetLocalSize(y,&lsize);CHKERRQ(ierr);
170     lsize = pf->dimin*lsize/pf->dimout;
171     ierr  = VecCreateMPI(PetscObjectComm((PetscObject)y),lsize,PETSC_DETERMINE,&x);CHKERRQ(ierr);
172     nox   = PETSC_TRUE;
173     ierr  = VecGetOwnershipRange(x,&rstart,&rend);CHKERRQ(ierr);
174     ierr  = VecGetArray(x,&xx);CHKERRQ(ierr);
175     for (i=rstart; i<rend; i++) xx[i-rstart] = (PetscScalar)i;
176     ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
177   }
178 
179   ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr);
180   ierr = VecGetLocalSize(y,&p);CHKERRQ(ierr);
181   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);
182   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);
183   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);
184 
185   if (pf->ops->applyvec) {
186     ierr = (*pf->ops->applyvec)(pf->data,x,y);CHKERRQ(ierr);
187   } else {
188     PetscScalar *xx,*yy;
189 
190     ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr);
191     n    = n/pf->dimin;
192     ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
193     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
194     if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
195     ierr = (*pf->ops->apply)(pf->data,n,xx,yy);CHKERRQ(ierr);
196     ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
197     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
198   }
199   if (nox) {
200     ierr = VecDestroy(&x);CHKERRQ(ierr);
201   }
202   PetscFunctionReturn(0);
203 }
204 
205 #undef __FUNCT__
206 #define __FUNCT__ "PFApply"
207 /*@
208    PFApply - Applies the mathematical function to an array of values.
209 
210    Collective on PF
211 
212    Input Parameters:
213 +  pf - the function context
214 .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
215        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
216        in the call to PFCreate()
217 -  x - input array
218 
219    Output Parameter:
220 .  y - output array
221 
222    Level: beginner
223 
224    Notes:
225 
226 .keywords: PF, apply
227 
228 .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
229 @*/
230 PetscErrorCode  PFApply(PF pf,PetscInt n,const PetscScalar *x,PetscScalar *y)
231 {
232   PetscErrorCode ierr;
233 
234   PetscFunctionBegin;
235   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
236   PetscValidScalarPointer(x,2);
237   PetscValidScalarPointer(y,3);
238   if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different arrays");
239   if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
240 
241   ierr = (*pf->ops->apply)(pf->data,n,x,y);CHKERRQ(ierr);
242   PetscFunctionReturn(0);
243 }
244 
245 #undef __FUNCT__
246 #define __FUNCT__ "PFView"
247 /*@
248    PFView - Prints information about a mathematical function
249 
250    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
251 
252    Input Parameters:
253 +  PF - the PF context
254 -  viewer - optional visualization context
255 
256    Note:
257    The available visualization contexts include
258 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
259 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
260          output where only the first processor opens
261          the file.  All other processors send their
262          data to the first processor to print.
263 
264    The user can open an alternative visualization contexts with
265    PetscViewerASCIIOpen() (output to a specified file).
266 
267    Level: developer
268 
269 .keywords: PF, view
270 
271 .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
272 @*/
273 PetscErrorCode  PFView(PF pf,PetscViewer viewer)
274 {
275   PetscErrorCode    ierr;
276   PetscBool         iascii;
277   PetscViewerFormat format;
278 
279   PetscFunctionBegin;
280   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
281   if (!viewer) {
282     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf),&viewer);CHKERRQ(ierr);
283   }
284   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
285   PetscCheckSameComm(pf,1,viewer,2);
286 
287   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
288   if (iascii) {
289     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
290     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer,"PF Object");CHKERRQ(ierr);
291     if (pf->ops->view) {
292       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
293       ierr = (*pf->ops->view)(pf->data,viewer);CHKERRQ(ierr);
294       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
295     }
296   }
297   PetscFunctionReturn(0);
298 }
299 
300 /*MC
301    PFRegisterDynamic - Adds a method to the mathematical function package.
302 
303    Synopsis:
304    #include "petscpf.h"
305    PetscErrorCode PFRegister(char *name_solver,char *name_create,PetscErrorCode (*routine_create)(PF))
306 
307    Not collective
308 
309    Input Parameters:
310 +  name_solver - name of a new user-defined solver
311 .  path - path (either absolute or relative) the library containing this solver
312 .  name_create - name of routine to create method context
313 -  routine_create - routine to create method context
314 
315    Notes:
316    PFRegister() may be called multiple times to add several user-defined functions
317 
318    Sample usage:
319 .vb
320    PFRegister("my_function","MyFunctionCreate",MyFunctionSetCreate);
321 .ve
322 
323    Then, your solver can be chosen with the procedural interface via
324 $     PFSetType(pf,"my_function")
325    or at runtime via the option
326 $     -pf_type my_function
327 
328    Level: advanced
329 
330 .keywords: PF, register
331 
332 .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
333 M*/
334 
335 #undef __FUNCT__
336 #define __FUNCT__ "PFRegister"
337 PetscErrorCode  PFRegister(const char sname[],const char name[],PetscErrorCode (*function)(PF,void*))
338 {
339   PetscErrorCode ierr;
340 
341   PetscFunctionBegin;
342   ierr = PetscFunctionListAdd(&PFunctionList,sname,name,(void (*)(void))function);CHKERRQ(ierr);
343   PetscFunctionReturn(0);
344 }
345 
346 #undef __FUNCT__
347 #define __FUNCT__ "PFGetType"
348 /*@C
349    PFGetType - Gets the PF method type and name (as a string) from the PF
350    context.
351 
352    Not Collective
353 
354    Input Parameter:
355 .  pf - the function context
356 
357    Output Parameter:
358 .  type - name of function
359 
360    Level: intermediate
361 
362 .keywords: PF, get, method, name, type
363 
364 .seealso: PFSetType()
365 
366 @*/
367 PetscErrorCode  PFGetType(PF pf,PFType *type)
368 {
369   PetscFunctionBegin;
370   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
371   PetscValidPointer(type,2);
372   *type = ((PetscObject)pf)->type_name;
373   PetscFunctionReturn(0);
374 }
375 
376 
377 #undef __FUNCT__
378 #define __FUNCT__ "PFSetType"
379 /*@C
380    PFSetType - Builds PF for a particular function
381 
382    Collective on PF
383 
384    Input Parameter:
385 +  pf - the function context.
386 .  type - a known method
387 -  ctx - optional type dependent context
388 
389    Options Database Key:
390 .  -pf_type <type> - Sets PF type
391 
392 
393   Notes:
394   See "petsc/include/petscpf.h" for available methods (for instance,
395   PFCONSTANT)
396 
397   Level: intermediate
398 
399 .keywords: PF, set, method, type
400 
401 .seealso: PFSet(), PFRegister(), PFCreate(), DMDACreatePF()
402 
403 @*/
404 PetscErrorCode  PFSetType(PF pf,PFType type,void *ctx)
405 {
406   PetscErrorCode ierr,(*r)(PF,void*);
407   PetscBool      match;
408 
409   PetscFunctionBegin;
410   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
411   PetscValidCharPointer(type,2);
412 
413   ierr = PetscObjectTypeCompare((PetscObject)pf,type,&match);CHKERRQ(ierr);
414   if (match) PetscFunctionReturn(0);
415 
416   if (pf->ops->destroy) {ierr =  (*pf->ops->destroy)(pf);CHKERRQ(ierr);}
417   pf->data = 0;
418 
419   /* Determine the PFCreateXXX routine for a particular function */
420   ierr = PetscFunctionListFind(PFunctionList,type,(void (**)(void)) &r);CHKERRQ(ierr);
421   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
422   pf->ops->destroy  = 0;
423   pf->ops->view     = 0;
424   pf->ops->apply    = 0;
425   pf->ops->applyvec = 0;
426 
427   /* Call the PFCreateXXX routine for this particular function */
428   ierr = (*r)(pf,ctx);CHKERRQ(ierr);
429 
430   ierr = PetscObjectChangeTypeName((PetscObject)pf,type);CHKERRQ(ierr);
431   PetscFunctionReturn(0);
432 }
433 
434 #undef __FUNCT__
435 #define __FUNCT__ "PFSetFromOptions"
436 /*@
437    PFSetFromOptions - Sets PF options from the options database.
438 
439    Collective on PF
440 
441    Input Parameters:
442 .  pf - the mathematical function context
443 
444    Options Database Keys:
445 
446    Notes:
447    To see all options, run your program with the -help option
448    or consult the users manual.
449 
450    Level: intermediate
451 
452 .keywords: PF, set, from, options, database
453 
454 .seealso:
455 @*/
456 PetscErrorCode  PFSetFromOptions(PF pf)
457 {
458   PetscErrorCode ierr;
459   char           type[256];
460   PetscBool      flg;
461 
462   PetscFunctionBegin;
463   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
464 
465   ierr = PetscObjectOptionsBegin((PetscObject)pf);CHKERRQ(ierr);
466   ierr = PetscOptionsList("-pf_type","Type of function","PFSetType",PFunctionList,0,type,256,&flg);CHKERRQ(ierr);
467   if (flg) {
468     ierr = PFSetType(pf,type,NULL);CHKERRQ(ierr);
469   }
470   if (pf->ops->setfromoptions) {
471     ierr = (*pf->ops->setfromoptions)(pf);CHKERRQ(ierr);
472   }
473 
474   /* process any options handlers added with PetscObjectAddOptionsHandler() */
475   ierr = PetscObjectProcessOptionsHandlers((PetscObject)pf);CHKERRQ(ierr);
476   ierr = PetscOptionsEnd();CHKERRQ(ierr);
477   PetscFunctionReturn(0);
478 }
479 
480 static PetscBool PFPackageInitialized = PETSC_FALSE;
481 #undef __FUNCT__
482 #define __FUNCT__ "PFFinalizePackage"
483 /*@C
484   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
485   called from PetscFinalize().
486 
487   Level: developer
488 
489 .keywords: Petsc, destroy, package, mathematica
490 .seealso: PetscFinalize()
491 @*/
492 PetscErrorCode  PFFinalizePackage(void)
493 {
494   PetscFunctionBegin;
495   PFPackageInitialized = PETSC_FALSE;
496   PFunctionList        = NULL;
497   PFRegisterAllCalled  = PETSC_FALSE;
498   PetscFunctionReturn(0);
499 }
500 
501 #undef __FUNCT__
502 #define __FUNCT__ "PFInitializePackage"
503 /*@C
504   PFInitializePackage - This function initializes everything in the PF package. It is called
505   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
506   when using static libraries.
507 
508   Level: developer
509 
510 .keywords: Vec, initialize, package
511 .seealso: PetscInitialize()
512 @*/
513 PetscErrorCode  PFInitializePackage(void)
514 {
515   char           logList[256];
516   char           *className;
517   PetscBool      opt;
518   PetscErrorCode ierr;
519 
520   PetscFunctionBegin;
521   if (PFPackageInitialized) PetscFunctionReturn(0);
522   PFPackageInitialized = PETSC_TRUE;
523   /* Register Classes */
524   ierr = PetscClassIdRegister("PointFunction",&PF_CLASSID);CHKERRQ(ierr);
525   /* Register Constructors */
526   ierr = PFRegisterAll();CHKERRQ(ierr);
527   /* Process info exclusions */
528   ierr = PetscOptionsGetString(NULL, "-info_exclude", logList, 256, &opt);CHKERRQ(ierr);
529   if (opt) {
530     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
531     if (className) {
532       ierr = PetscInfoDeactivateClass(PF_CLASSID);CHKERRQ(ierr);
533     }
534   }
535   /* Process summary exclusions */
536   ierr = PetscOptionsGetString(NULL, "-log_summary_exclude", logList, 256, &opt);CHKERRQ(ierr);
537   if (opt) {
538     ierr = PetscStrstr(logList, "pf", &className);CHKERRQ(ierr);
539     if (className) {
540       ierr = PetscLogEventDeactivateClass(PF_CLASSID);CHKERRQ(ierr);
541     }
542   }
543   ierr = PetscRegisterFinalize(PFFinalizePackage);CHKERRQ(ierr);
544   PetscFunctionReturn(0);
545 }
546 
547 
548 
549 
550 
551 
552 
553 
554 
555