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