xref: /petsc/src/vec/pf/interface/pf.c (revision feff33ee0b5b037fa8f9f294dede656a2f85cc47)
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 = PetscFunctionListAdd(&PFList,sname,function);CHKERRQ(ierr);
314   PetscFunctionReturn(0);
315 }
316 
317 /*@C
318    PFGetType - Gets the PF method type and name (as a string) from the PF
319    context.
320 
321    Not Collective
322 
323    Input Parameter:
324 .  pf - the function context
325 
326    Output Parameter:
327 .  type - name of function
328 
329    Level: intermediate
330 
331 .keywords: PF, get, method, name, type
332 
333 .seealso: PFSetType()
334 
335 @*/
336 PetscErrorCode  PFGetType(PF pf,PFType *type)
337 {
338   PetscFunctionBegin;
339   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
340   PetscValidPointer(type,2);
341   *type = ((PetscObject)pf)->type_name;
342   PetscFunctionReturn(0);
343 }
344 
345 
346 /*@C
347    PFSetType - Builds PF for a particular function
348 
349    Collective on PF
350 
351    Input Parameter:
352 +  pf - the function context.
353 .  type - a known method
354 -  ctx - optional type dependent context
355 
356    Options Database Key:
357 .  -pf_type <type> - Sets PF type
358 
359 
360   Notes:
361   See "petsc/include/petscpf.h" for available methods (for instance,
362   PFCONSTANT)
363 
364   Level: intermediate
365 
366 .keywords: PF, set, method, type
367 
368 .seealso: PFSet(), PFRegister(), PFCreate(), DMDACreatePF()
369 
370 @*/
371 PetscErrorCode  PFSetType(PF pf,PFType type,void *ctx)
372 {
373   PetscErrorCode ierr,(*r)(PF,void*);
374   PetscBool      match;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
378   PetscValidCharPointer(type,2);
379 
380   ierr = PetscObjectTypeCompare((PetscObject)pf,type,&match);CHKERRQ(ierr);
381   if (match) PetscFunctionReturn(0);
382 
383   if (pf->ops->destroy) {ierr =  (*pf->ops->destroy)(pf);CHKERRQ(ierr);}
384   pf->data = 0;
385 
386   /* Determine the PFCreateXXX routine for a particular function */
387   ierr = PetscFunctionListFind(PFList,type,&r);CHKERRQ(ierr);
388   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
389   pf->ops->destroy  = 0;
390   pf->ops->view     = 0;
391   pf->ops->apply    = 0;
392   pf->ops->applyvec = 0;
393 
394   /* Call the PFCreateXXX routine for this particular function */
395   ierr = (*r)(pf,ctx);CHKERRQ(ierr);
396 
397   ierr = PetscObjectChangeTypeName((PetscObject)pf,type);CHKERRQ(ierr);
398   PetscFunctionReturn(0);
399 }
400 
401 /*@
402    PFSetFromOptions - Sets PF options from the options database.
403 
404    Collective on PF
405 
406    Input Parameters:
407 .  pf - the mathematical function context
408 
409    Options Database Keys:
410 
411    Notes:
412    To see all options, run your program with the -help option
413    or consult the users manual.
414 
415    Level: intermediate
416 
417 .keywords: PF, set, from, options, database
418 
419 .seealso:
420 @*/
421 PetscErrorCode  PFSetFromOptions(PF pf)
422 {
423   PetscErrorCode ierr;
424   char           type[256];
425   PetscBool      flg;
426 
427   PetscFunctionBegin;
428   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
429 
430   ierr = PetscObjectOptionsBegin((PetscObject)pf);CHKERRQ(ierr);
431   ierr = PetscOptionsFList("-pf_type","Type of function","PFSetType",PFList,0,type,256,&flg);CHKERRQ(ierr);
432   if (flg) {
433     ierr = PFSetType(pf,type,NULL);CHKERRQ(ierr);
434   }
435   if (pf->ops->setfromoptions) {
436     ierr = (*pf->ops->setfromoptions)(PetscOptionsObject,pf);CHKERRQ(ierr);
437   }
438 
439   /* process any options handlers added with PetscObjectAddOptionsHandler() */
440   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pf);CHKERRQ(ierr);
441   ierr = PetscOptionsEnd();CHKERRQ(ierr);
442   PetscFunctionReturn(0);
443 }
444 
445 static PetscBool PFPackageInitialized = PETSC_FALSE;
446 /*@C
447   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
448   called from PetscFinalize().
449 
450   Level: developer
451 
452 .keywords: Petsc, destroy, package, mathematica
453 .seealso: PetscFinalize()
454 @*/
455 PetscErrorCode  PFFinalizePackage(void)
456 {
457   PetscErrorCode ierr;
458 
459   PetscFunctionBegin;
460   ierr = PetscFunctionListDestroy(&PFList);CHKERRQ(ierr);
461   PFPackageInitialized = PETSC_FALSE;
462   PFRegisterAllCalled  = PETSC_FALSE;
463   PetscFunctionReturn(0);
464 }
465 
466 /*@C
467   PFInitializePackage - This function initializes everything in the PF package. It is called
468   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
469   when using static libraries.
470 
471   Level: developer
472 
473 .keywords: Vec, initialize, package
474 .seealso: PetscInitialize()
475 @*/
476 PetscErrorCode  PFInitializePackage(void)
477 {
478   char           logList[256];
479   PetscBool      opt,pkg;
480   PetscErrorCode ierr;
481 
482   PetscFunctionBegin;
483   if (PFPackageInitialized) PetscFunctionReturn(0);
484   PFPackageInitialized = PETSC_TRUE;
485   /* Register Classes */
486   ierr = PetscClassIdRegister("PointFunction",&PF_CLASSID);CHKERRQ(ierr);
487   /* Register Constructors */
488   ierr = PFRegisterAll();CHKERRQ(ierr);
489   /* Process info exclusions */
490   ierr = PetscOptionsGetString(NULL,NULL,"-info_exclude",logList,sizeof(logList),&opt);CHKERRQ(ierr);
491   if (opt) {
492     ierr = PetscStrInList("pf",logList,',',&pkg);CHKERRQ(ierr);
493     if (pkg) {ierr = PetscInfoDeactivateClass(PF_CLASSID);CHKERRQ(ierr);}
494   }
495   /* Process summary exclusions */
496   ierr = PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt);CHKERRQ(ierr);
497   if (opt) {
498     ierr = PetscStrInList("pf",logList,',',&pkg);CHKERRQ(ierr);
499     if (pkg) {ierr = PetscLogEventDeactivateClass(PF_CLASSID);CHKERRQ(ierr);}
500   }
501   /* Register package finalizer */
502   ierr = PetscRegisterFinalize(PFFinalizePackage);CHKERRQ(ierr);
503   PetscFunctionReturn(0);
504 }
505 
506 
507 
508 
509 
510 
511 
512 
513 
514