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