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