Actual source code: pf.c
petsc-3.3-p7 2013-05-11
1: /*
2: The PF mathematical functions interface routines, callable by users.
3: */
4: #include <../src/vec/pf/pfimpl.h> /*I "petscpf.h" I*/
6: /* Logging support */
7: PetscClassId PF_CLASSID = 0;
9: PetscFList PFList = PETSC_NULL; /* list of all registered PD functions */
10: PetscBool PFRegisterAllCalled = PETSC_FALSE;
14: /*@C
15: PFSet - Sets the C/C++/Fortran functions to be used by the PF function
17: Collective on PF
19: Input Parameter:
20: + pf - the function context
21: . apply - function to apply to an array
22: . applyvec - function to apply to a Vec
23: . view - function that prints information about the PF
24: . destroy - function to free the private function context
25: - ctx - private function context
27: Level: beginner
29: .keywords: PF, setting
31: .seealso: PFCreate(), PFDestroy(), PFSetType(), PFApply(), PFApplyVec()
32: @*/
33: 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)
34: {
37: pf->data = ctx;
39: pf->ops->destroy = destroy;
40: pf->ops->apply = apply;
41: pf->ops->applyvec = applyvec;
42: pf->ops->view = view;
44: return(0);
45: }
49: /*@C
50: PFDestroy - Destroys PF context that was created with PFCreate().
52: Collective on PF
54: Input Parameter:
55: . pf - the function context
57: Level: beginner
59: .keywords: PF, destroy
61: .seealso: PFCreate(), PFSet(), PFSetType()
62: @*/
63: PetscErrorCode PFDestroy(PF *pf)
64: {
66: PetscBool flg = PETSC_FALSE;
69: if (!*pf) return(0);
71: if (--((PetscObject)(*pf))->refct > 0) return(0);
73: PetscOptionsGetBool(((PetscObject)(*pf))->prefix,"-pf_view",&flg,PETSC_NULL);
74: if (flg) {
75: PetscViewer viewer;
76: PetscViewerASCIIGetStdout(((PetscObject)(*pf))->comm,&viewer);
77: PFView((*pf),viewer);
78: }
80: /* if memory was published with AMS then destroy it */
81: PetscObjectDepublish((*pf));
83: if ((*pf)->ops->destroy) { (*(*pf)->ops->destroy)((*pf)->data);}
84: PetscHeaderDestroy(pf);
85: return(0);
86: }
90: /*@C
91: PFCreate - Creates a mathematical function context.
93: Collective on MPI_Comm
95: Input Parameter:
96: + comm - MPI communicator
97: . dimin - dimension of the space you are mapping from
98: - dimout - dimension of the space you are mapping to
100: Output Parameter:
101: . pf - the function context
103: Level: developer
105: .keywords: PF, create, context
107: .seealso: PFSet(), PFApply(), PFDestroy(), PFApplyVec()
108: @*/
109: PetscErrorCode PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
110: {
111: PF newpf;
116: *pf = PETSC_NULL;
117: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
118: PFInitializePackage(PETSC_NULL);
119: #endif
121: PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_CLASSID,-1,"PF","Mathematical functions","Vec",comm,PFDestroy,PFView);
122: newpf->data = 0;
124: newpf->ops->destroy = 0;
125: newpf->ops->apply = 0;
126: newpf->ops->applyvec = 0;
127: newpf->ops->view = 0;
128: newpf->dimin = dimin;
129: newpf->dimout = dimout;
131: *pf = newpf;
132: return(0);
134: }
136: /* -------------------------------------------------------------------------------*/
140: /*@
141: PFApplyVec - Applies the mathematical function to a vector
143: Collective on PF
145: Input Parameters:
146: + pf - the function context
147: - x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)
149: Output Parameter:
150: . y - output vector
152: Level: beginner
154: .keywords: PF, apply
156: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
157: @*/
158: PetscErrorCode PFApplyVec(PF pf,Vec x,Vec y)
159: {
161: PetscInt i,rstart,rend,n,p;
162: PetscBool nox = PETSC_FALSE;
167: if (x) {
169: if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors");
170: } else {
171: PetscScalar *xx;
172: PetscInt lsize;
174: VecGetLocalSize(y,&lsize);
175: lsize = pf->dimin*lsize/pf->dimout;
176: VecCreateMPI(((PetscObject)y)->comm,lsize,PETSC_DETERMINE,&x);
177: nox = PETSC_TRUE;
178: VecGetOwnershipRange(x,&rstart,&rend);
179: VecGetArray(x,&xx);
180: for (i=rstart; i<rend; i++) {
181: xx[i-rstart] = (PetscScalar)i;
182: }
183: VecRestoreArray(x,&xx);
184: }
186: VecGetLocalSize(x,&n);
187: VecGetLocalSize(y,&p);
188: 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);
189: 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);
190: 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);
192: if (pf->ops->applyvec) {
193: (*pf->ops->applyvec)(pf->data,x,y);
194: } else {
195: PetscScalar *xx,*yy;
197: VecGetLocalSize(x,&n);
198: n = n/pf->dimin;
199: VecGetArray(x,&xx);
200: VecGetArray(y,&yy);
201: if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
202: (*pf->ops->apply)(pf->data,n,xx,yy);
203: VecRestoreArray(x,&xx);
204: VecRestoreArray(y,&yy);
205: }
206: if (nox) {
207: VecDestroy(&x);
208: }
209: return(0);
210: }
214: /*@
215: PFApply - Applies the mathematical function to an array of values.
217: Collective on PF
219: Input Parameters:
220: + pf - the function context
221: . n - number of pointwise function evaluations to perform, each pointwise function evaluation
222: is a function of dimin variables and computes dimout variables where dimin and dimout are defined
223: in the call to PFCreate()
224: - x - input array
226: Output Parameter:
227: . y - output array
229: Level: beginner
231: Notes:
233: .keywords: PF, apply
235: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
236: @*/
237: PetscErrorCode PFApply(PF pf,PetscInt n,const PetscScalar* x,PetscScalar* y)
238: {
245: if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different arrays");
246: if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
248: (*pf->ops->apply)(pf->data,n,x,y);
249: return(0);
250: }
254: /*@
255: PFView - Prints information about a mathematical function
257: Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
259: Input Parameters:
260: + PF - the PF context
261: - viewer - optional visualization context
263: Note:
264: The available visualization contexts include
265: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
266: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
267: output where only the first processor opens
268: the file. All other processors send their
269: data to the first processor to print.
271: The user can open an alternative visualization contexts with
272: PetscViewerASCIIOpen() (output to a specified file).
274: Level: developer
276: .keywords: PF, view
278: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
279: @*/
280: PetscErrorCode PFView(PF pf,PetscViewer viewer)
281: {
282: PetscErrorCode ierr;
283: PetscBool iascii;
284: PetscViewerFormat format;
288: if (!viewer) {
289: PetscViewerASCIIGetStdout(((PetscObject)pf)->comm,&viewer);
290: }
294: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
295: if (iascii) {
296: PetscViewerGetFormat(viewer,&format);
297: PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer,"PF Object");
298: if (pf->ops->view) {
299: PetscViewerASCIIPushTab(viewer);
300: (*pf->ops->view)(pf->data,viewer);
301: PetscViewerASCIIPopTab(viewer);
302: }
303: } else {
304: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
305: }
306: return(0);
307: }
309: /*MC
310: PFRegisterDynamic - Adds a method to the mathematical function package.
312: Synopsis:
313: PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))
315: Not collective
317: Input Parameters:
318: + name_solver - name of a new user-defined solver
319: . path - path (either absolute or relative) the library containing this solver
320: . name_create - name of routine to create method context
321: - routine_create - routine to create method context
323: Notes:
324: PFRegisterDynamic() may be called multiple times to add several user-defined functions
326: If dynamic libraries are used, then the fourth input argument (routine_create)
327: is ignored.
329: Sample usage:
330: .vb
331: PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
332: "MyFunctionCreate",MyFunctionSetCreate);
333: .ve
335: Then, your solver can be chosen with the procedural interface via
336: $ PFSetType(pf,"my_function")
337: or at runtime via the option
338: $ -pf_type my_function
340: Level: advanced
342: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
343: occuring in pathname will be replaced with appropriate values.
345: .keywords: PF, register
347: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
348: M*/
352: PetscErrorCode PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
353: {
355: char fullname[PETSC_MAX_PATH_LEN];
358: PetscFListConcat(path,name,fullname);
359: PetscFListAdd(&PFList,sname,fullname,(void (*)(void))function);
360: return(0);
361: }
365: /*@C
366: PFGetType - Gets the PF method type and name (as a string) from the PF
367: context.
369: Not Collective
371: Input Parameter:
372: . pf - the function context
374: Output Parameter:
375: . type - name of function
377: Level: intermediate
379: .keywords: PF, get, method, name, type
381: .seealso: PFSetType()
383: @*/
384: PetscErrorCode PFGetType(PF pf,const PFType *type)
385: {
389: *type = ((PetscObject)pf)->type_name;
390: return(0);
391: }
396: /*@C
397: PFSetType - Builds PF for a particular function
399: Collective on PF
401: Input Parameter:
402: + pf - the function context.
403: . type - a known method
404: - ctx - optional type dependent context
406: Options Database Key:
407: . -pf_type <type> - Sets PF type
410: Notes:
411: See "petsc/include/petscpf.h" for available methods (for instance,
412: PFCONSTANT)
414: Level: intermediate
416: .keywords: PF, set, method, type
418: .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DMDACreatePF()
420: @*/
421: PetscErrorCode PFSetType(PF pf,const PFType type,void *ctx)
422: {
423: PetscErrorCode ierr,(*r)(PF,void*);
424: PetscBool match;
430: PetscObjectTypeCompare((PetscObject)pf,type,&match);
431: if (match) return(0);
433: if (pf->ops->destroy) { (*pf->ops->destroy)(pf);}
434: pf->data = 0;
436: /* Determine the PFCreateXXX routine for a particular function */
437: PetscFListFind(PFList,((PetscObject)pf)->comm,type,PETSC_TRUE,(void (**)(void)) &r);
438: if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
439: pf->ops->destroy = 0;
440: pf->ops->view = 0;
441: pf->ops->apply = 0;
442: pf->ops->applyvec = 0;
444: /* Call the PFCreateXXX routine for this particular function */
445: (*r)(pf,ctx);
447: PetscObjectChangeTypeName((PetscObject)pf,type);
448: return(0);
449: }
453: /*@
454: PFSetFromOptions - Sets PF options from the options database.
456: Collective on PF
458: Input Parameters:
459: . pf - the mathematical function context
461: Options Database Keys:
463: Notes:
464: To see all options, run your program with the -help option
465: or consult the users manual.
467: Level: intermediate
469: .keywords: PF, set, from, options, database
471: .seealso:
472: @*/
473: PetscErrorCode PFSetFromOptions(PF pf)
474: {
476: char type[256];
477: PetscBool flg;
482: PetscObjectOptionsBegin((PetscObject)pf);
483: PetscOptionsList("-pf_type","Type of function","PFSetType",PFList,0,type,256,&flg);
484: if (flg) {
485: PFSetType(pf,type,PETSC_NULL);
486: }
487: if (pf->ops->setfromoptions) {
488: (*pf->ops->setfromoptions)(pf);
489: }
491: /* process any options handlers added with PetscObjectAddOptionsHandler() */
492: PetscObjectProcessOptionsHandlers((PetscObject)pf);
493: PetscOptionsEnd();
495: return(0);
496: }
498: static PetscBool PFPackageInitialized = PETSC_FALSE;
501: /*@C
502: PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
503: called from PetscFinalize().
505: Level: developer
507: .keywords: Petsc, destroy, package, mathematica
508: .seealso: PetscFinalize()
509: @*/
510: PetscErrorCode PFFinalizePackage(void)
511: {
513: PFPackageInitialized = PETSC_FALSE;
514: PFList = PETSC_NULL;
515: PFRegisterAllCalled = PETSC_FALSE;
516: return(0);
517: }
521: /*@C
522: PFInitializePackage - This function initializes everything in the PF package. It is called
523: from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
524: when using static libraries.
526: Input Parameter:
527: . path - The dynamic library path, or PETSC_NULL
529: Level: developer
531: .keywords: Vec, initialize, package
532: .seealso: PetscInitialize()
533: @*/
534: PetscErrorCode PFInitializePackage(const char path[])
535: {
536: char logList[256];
537: char *className;
538: PetscBool opt;
539: PetscErrorCode ierr;
542: if (PFPackageInitialized) return(0);
543: PFPackageInitialized = PETSC_TRUE;
544: /* Register Classes */
545: PetscClassIdRegister("PointFunction",&PF_CLASSID);
546: /* Register Constructors */
547: PFRegisterAll(path);
548: /* Process info exclusions */
549: PetscOptionsGetString(PETSC_NULL, "-info_exclude", logList, 256, &opt);
550: if (opt) {
551: PetscStrstr(logList, "pf", &className);
552: if (className) {
553: PetscInfoDeactivateClass(PF_CLASSID);
554: }
555: }
556: /* Process summary exclusions */
557: PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);
558: if (opt) {
559: PetscStrstr(logList, "pf", &className);
560: if (className) {
561: PetscLogEventDeactivateClass(PF_CLASSID);
562: }
563: }
564: PetscRegisterFinalize(PFFinalizePackage);
565: return(0);
566: }