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