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