xref: /petsc/src/vec/pf/interface/pf.c (revision 92f119d60f7d2a2cf41595d5d0552580c733cbde)
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 @*/
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 @*/
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 @*/
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          = 0;
98   newpf->ops->destroy  = 0;
99   newpf->ops->apply    = 0;
100   newpf->ops->applyvec = 0;
101   newpf->ops->view     = 0;
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 @*/
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 @*/
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 /*@
217    PFView - Prints information about a mathematical function
218 
219    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
220 
221    Input Parameters:
222 +  PF - the PF context
223 -  viewer - optional visualization context
224 
225    Note:
226    The available visualization contexts include
227 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
228 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
229          output where only the first processor opens
230          the file.  All other processors send their
231          data to the first processor to print.
232 
233    The user can open an alternative visualization contexts with
234    PetscViewerASCIIOpen() (output to a specified file).
235 
236    Level: developer
237 
238 .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
239 @*/
240 PetscErrorCode  PFView(PF pf,PetscViewer viewer)
241 {
242   PetscErrorCode    ierr;
243   PetscBool         iascii;
244   PetscViewerFormat format;
245 
246   PetscFunctionBegin;
247   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
248   if (!viewer) {
249     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf),&viewer);CHKERRQ(ierr);
250   }
251   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
252   PetscCheckSameComm(pf,1,viewer,2);
253 
254   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
255   if (iascii) {
256     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
257     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer);CHKERRQ(ierr);
258     if (pf->ops->view) {
259       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
260       ierr = (*pf->ops->view)(pf->data,viewer);CHKERRQ(ierr);
261       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
262     }
263   }
264   PetscFunctionReturn(0);
265 }
266 
267 
268 /*@C
269    PFRegister - Adds a method to the mathematical function package.
270 
271    Not collective
272 
273    Input Parameters:
274 +  name_solver - name of a new user-defined solver
275 -  routine_create - routine to create method context
276 
277    Notes:
278    PFRegister() may be called multiple times to add several user-defined functions
279 
280    Sample usage:
281 .vb
282    PFRegister("my_function",MyFunctionSetCreate);
283 .ve
284 
285    Then, your solver can be chosen with the procedural interface via
286 $     PFSetType(pf,"my_function")
287    or at runtime via the option
288 $     -pf_type my_function
289 
290    Level: advanced
291 
292 .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
293 @*/
294 PetscErrorCode  PFRegister(const char sname[],PetscErrorCode (*function)(PF,void*))
295 {
296   PetscErrorCode ierr;
297 
298   PetscFunctionBegin;
299   ierr = PFInitializePackage();CHKERRQ(ierr);
300   ierr = PetscFunctionListAdd(&PFList,sname,function);CHKERRQ(ierr);
301   PetscFunctionReturn(0);
302 }
303 
304 /*@C
305    PFGetType - Gets the PF method type and name (as a string) from the PF
306    context.
307 
308    Not Collective
309 
310    Input Parameter:
311 .  pf - the function context
312 
313    Output Parameter:
314 .  type - name of function
315 
316    Level: intermediate
317 
318 .seealso: PFSetType()
319 
320 @*/
321 PetscErrorCode  PFGetType(PF pf,PFType *type)
322 {
323   PetscFunctionBegin;
324   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
325   PetscValidPointer(type,2);
326   *type = ((PetscObject)pf)->type_name;
327   PetscFunctionReturn(0);
328 }
329 
330 
331 /*@C
332    PFSetType - Builds PF for a particular function
333 
334    Collective on PF
335 
336    Input Parameter:
337 +  pf - the function context.
338 .  type - a known method
339 -  ctx - optional type dependent context
340 
341    Options Database Key:
342 .  -pf_type <type> - Sets PF type
343 
344 
345   Notes:
346   See "petsc/include/petscpf.h" for available methods (for instance,
347   PFCONSTANT)
348 
349   Level: intermediate
350 
351 .seealso: PFSet(), PFRegister(), PFCreate(), DMDACreatePF()
352 
353 @*/
354 PetscErrorCode  PFSetType(PF pf,PFType type,void *ctx)
355 {
356   PetscErrorCode ierr,(*r)(PF,void*);
357   PetscBool      match;
358 
359   PetscFunctionBegin;
360   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
361   PetscValidCharPointer(type,2);
362 
363   ierr = PetscObjectTypeCompare((PetscObject)pf,type,&match);CHKERRQ(ierr);
364   if (match) PetscFunctionReturn(0);
365 
366   if (pf->ops->destroy) {ierr =  (*pf->ops->destroy)(pf);CHKERRQ(ierr);}
367   pf->data = 0;
368 
369   /* Determine the PFCreateXXX routine for a particular function */
370   ierr = PetscFunctionListFind(PFList,type,&r);CHKERRQ(ierr);
371   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
372   pf->ops->destroy  = 0;
373   pf->ops->view     = 0;
374   pf->ops->apply    = 0;
375   pf->ops->applyvec = 0;
376 
377   /* Call the PFCreateXXX routine for this particular function */
378   ierr = (*r)(pf,ctx);CHKERRQ(ierr);
379 
380   ierr = PetscObjectChangeTypeName((PetscObject)pf,type);CHKERRQ(ierr);
381   PetscFunctionReturn(0);
382 }
383 
384 /*@
385    PFSetFromOptions - Sets PF options from the options database.
386 
387    Collective on PF
388 
389    Input Parameters:
390 .  pf - the mathematical function context
391 
392    Options Database Keys:
393 
394    Notes:
395    To see all options, run your program with the -help option
396    or consult the users manual.
397 
398    Level: intermediate
399 
400 .seealso:
401 @*/
402 PetscErrorCode  PFSetFromOptions(PF pf)
403 {
404   PetscErrorCode ierr;
405   char           type[256];
406   PetscBool      flg;
407 
408   PetscFunctionBegin;
409   PetscValidHeaderSpecific(pf,PF_CLASSID,1);
410 
411   ierr = PetscObjectOptionsBegin((PetscObject)pf);CHKERRQ(ierr);
412   ierr = PetscOptionsFList("-pf_type","Type of function","PFSetType",PFList,0,type,256,&flg);CHKERRQ(ierr);
413   if (flg) {
414     ierr = PFSetType(pf,type,NULL);CHKERRQ(ierr);
415   }
416   if (pf->ops->setfromoptions) {
417     ierr = (*pf->ops->setfromoptions)(PetscOptionsObject,pf);CHKERRQ(ierr);
418   }
419 
420   /* process any options handlers added with PetscObjectAddOptionsHandler() */
421   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pf);CHKERRQ(ierr);
422   ierr = PetscOptionsEnd();CHKERRQ(ierr);
423   PetscFunctionReturn(0);
424 }
425 
426 static PetscBool PFPackageInitialized = PETSC_FALSE;
427 /*@C
428   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
429   called from PetscFinalize().
430 
431   Level: developer
432 
433 .seealso: PetscFinalize()
434 @*/
435 PetscErrorCode  PFFinalizePackage(void)
436 {
437   PetscErrorCode ierr;
438 
439   PetscFunctionBegin;
440   ierr = PetscFunctionListDestroy(&PFList);CHKERRQ(ierr);
441   PFPackageInitialized = PETSC_FALSE;
442   PFRegisterAllCalled  = PETSC_FALSE;
443   PetscFunctionReturn(0);
444 }
445 
446 /*@C
447   PFInitializePackage - This function initializes everything in the PF package. It is called
448   from PetscDLLibraryRegister_petscvec() when using dynamic libraries, and on the first call to PFCreate()
449   when using shared or static libraries.
450 
451   Level: developer
452 
453 .seealso: PetscInitialize()
454 @*/
455 PetscErrorCode  PFInitializePackage(void)
456 {
457   char           logList[256];
458   PetscBool      opt,pkg;
459   PetscErrorCode ierr;
460 
461   PetscFunctionBegin;
462   if (PFPackageInitialized) PetscFunctionReturn(0);
463   PFPackageInitialized = PETSC_TRUE;
464   /* Register Classes */
465   ierr = PetscClassIdRegister("PointFunction",&PF_CLASSID);CHKERRQ(ierr);
466   /* Register Constructors */
467   ierr = PFRegisterAll();CHKERRQ(ierr);
468   /* Process info exclusions */
469   ierr = PetscOptionsGetString(NULL,NULL,"-info_exclude",logList,sizeof(logList),&opt);CHKERRQ(ierr);
470   if (opt) {
471     ierr = PetscStrInList("pf",logList,',',&pkg);CHKERRQ(ierr);
472     if (pkg) {ierr = PetscInfoDeactivateClass(PF_CLASSID);CHKERRQ(ierr);}
473   }
474   /* Process summary exclusions */
475   ierr = PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt);CHKERRQ(ierr);
476   if (opt) {
477     ierr = PetscStrInList("pf",logList,',',&pkg);CHKERRQ(ierr);
478     if (pkg) {ierr = PetscLogEventExcludeClass(PF_CLASSID);CHKERRQ(ierr);}
479   }
480   /* Register package finalizer */
481   ierr = PetscRegisterFinalize(PFFinalizePackage);CHKERRQ(ierr);
482   PetscFunctionReturn(0);
483 }
484 
485 
486 
487 
488 
489 
490 
491 
492 
493