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