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