Actual source code: pf.c
1: #define PETSCVEC_DLL
2: /*
3: The PF mathematical functions interface routines, callable by users.
4: */
5: #include src/vec/pf/pfimpl.h
7: /* Logging support */
8: PetscCookie PF_COOKIE = 0;
10: PetscFList PPetscFList = PETSC_NULL; /* list of all registered PD functions */
11: PetscTruth PFRegisterAllCalled = PETSC_FALSE;
15: /*@C
16: PFSet - Sets the C/C++/Fortran functions to be used by the PF function
18: Collective on PF
20: Input Parameter:
21: + pf - the function context
22: . apply - function to apply to an array
23: . applyvec - function to apply to a Vec
24: . view - function that prints information about the PF
25: . destroy - function to free the private function context
26: - ctx - private function context
28: Level: beginner
30: .keywords: PF, setting
32: .seealso: PFCreate(), PFDestroy(), PFSetType(), PFApply(), PFApplyVec()
33: @*/
34: PetscErrorCode PFSet(PF pf,PetscErrorCode (*apply)(void*,PetscInt,PetscScalar*,PetscScalar*),PetscErrorCode (*applyvec)(void*,Vec,Vec),PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*destroy)(void*),void*ctx)
35: {
38: pf->data = ctx;
40: pf->ops->destroy = destroy;
41: pf->ops->apply = apply;
42: pf->ops->applyvec = applyvec;
43: pf->ops->view = view;
45: return(0);
46: }
50: /*@C
51: PFDestroy - Destroys PF context that was created with PFCreate().
53: Collective on PF
55: Input Parameter:
56: . pf - the function context
58: Level: beginner
60: .keywords: PF, destroy
62: .seealso: PFCreate(), PFSet(), PFSetType()
63: @*/
64: PetscErrorCode PFDestroy(PF pf)
65: {
67: PetscTruth flg;
71: if (--pf->refct > 0) return(0);
73: PetscOptionsHasName(pf->prefix,"-pf_view",&flg);
74: if (flg) {
75: PetscViewer viewer;
76: PetscViewerASCIIGetStdout(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: static PetscErrorCode PFPublish_Petsc(PetscObject obj)
91: {
92: #if defined(PETSC_HAVE_AMS)
93: PF v = (PF) obj;
95: #endif
99: #if defined(PETSC_HAVE_AMS)
100: /* if it is already published then return */
101: if (v->amem >=0) return(0);
103: PetscObjectPublishBaseBegin(obj);
104: PetscObjectPublishBaseEnd(obj);
105: #endif
107: return(0);
108: }
112: /*@C
113: PFCreate - Creates a mathematical function context.
115: Collective on MPI_Comm
117: Input Parameter:
118: + comm - MPI communicator
119: . dimin - dimension of the space you are mapping from
120: - dimout - dimension of the space you are mapping to
122: Output Parameter:
123: . pf - the function context
125: Level: developer
127: .keywords: PF, create, context
129: .seealso: PFSetUp(), PFApply(), PFDestroy(), PFApplyVec()
130: @*/
131: PetscErrorCode PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
132: {
133: PF newpf;
138: *pf = PETSC_NULL;
139: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
140: VecInitializePackage(PETSC_NULL);
141: #endif
143: PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_COOKIE,-1,"PF",comm,PFDestroy,PFView);
144: newpf->bops->publish = PFPublish_Petsc;
145: newpf->data = 0;
147: newpf->ops->destroy = 0;
148: newpf->ops->apply = 0;
149: newpf->ops->applyvec = 0;
150: newpf->ops->view = 0;
151: newpf->dimin = dimin;
152: newpf->dimout = dimout;
154: *pf = newpf;
155: PetscPublishAll(pf);
156: return(0);
158: }
160: /* -------------------------------------------------------------------------------*/
164: /*@
165: PFApplyVec - Applies the mathematical function to a vector
167: Collective on PF
169: Input Parameters:
170: + pf - the function context
171: - x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)
173: Output Parameter:
174: . y - output vector
176: Level: beginner
178: .keywords: PF, apply
180: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
181: @*/
182: PetscErrorCode PFApplyVec(PF pf,Vec x,Vec y)
183: {
185: PetscInt i,rstart,rend,n,p;
186: PetscTruth nox = PETSC_FALSE;
191: if (x) {
193: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
194: } else {
195: PetscScalar *xx;
197: VecDuplicate(y,&x);
198: nox = PETSC_TRUE;
199: VecGetOwnershipRange(x,&rstart,&rend);
200: VecGetArray(x,&xx);
201: for (i=rstart; i<rend; i++) {
202: xx[i-rstart] = (PetscScalar)i;
203: }
204: VecRestoreArray(x,&xx);
205: }
207: VecGetLocalSize(x,&n);
208: VecGetLocalSize(y,&p);
209: if ((pf->dimin*(n/pf->dimin)) != n) SETERRQ2(PETSC_ERR_ARG_SIZ,"Local input vector length %D not divisible by dimin %D of function",n,pf->dimin);
210: if ((pf->dimout*(p/pf->dimout)) != p) SETERRQ2(PETSC_ERR_ARG_SIZ,"Local output vector length %D not divisible by dimout %D of function",p,pf->dimout);
211: if ((n/pf->dimin) != (p/pf->dimout)) SETERRQ4(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);
213: if (pf->ops->applyvec) {
214: (*pf->ops->applyvec)(pf->data,x,y);
215: } else {
216: PetscScalar *xx,*yy;
218: VecGetLocalSize(x,&n);
219: n = n/pf->dimin;
220: VecGetArray(x,&xx);
221: VecGetArray(y,&yy);
222: if (!pf->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
223: (*pf->ops->apply)(pf->data,n,xx,yy);
224: VecRestoreArray(x,&xx);
225: VecRestoreArray(y,&yy);
226: }
227: if (nox) {
228: VecDestroy(x);
229: }
230: return(0);
231: }
235: /*@
236: PFApply - Applies the mathematical function to an array of values.
238: Collective on PF
240: Input Parameters:
241: + pf - the function context
242: . n - number of pointwise function evaluations to perform, each pointwise function evaluation
243: is a function of dimin variables and computes dimout variables where dimin and dimout are defined
244: in the call to PFCreate()
245: - x - input array
247: Output Parameter:
248: . y - output array
250: Level: beginner
252: Notes:
254: .keywords: PF, apply
256: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
257: @*/
258: PetscErrorCode PFApply(PF pf,PetscInt n,PetscScalar* x,PetscScalar* y)
259: {
266: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different arrays");
267: if (!pf->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
269: (*pf->ops->apply)(pf->data,n,x,y);
270: return(0);
271: }
275: /*@
276: PFView - Prints information about a mathematical function
278: Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
280: Input Parameters:
281: + PF - the PF context
282: - viewer - optional visualization context
284: Note:
285: The available visualization contexts include
286: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
287: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
288: output where only the first processor opens
289: the file. All other processors send their
290: data to the first processor to print.
292: The user can open an alternative visualization contexts with
293: PetscViewerASCIIOpen() (output to a specified file).
295: Level: developer
297: .keywords: PF, view
299: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
300: @*/
301: PetscErrorCode PFView(PF pf,PetscViewer viewer)
302: {
303: PFType cstr;
304: PetscErrorCode ierr;
305: PetscTruth iascii;
306: PetscViewerFormat format;
310: if (!viewer) {
311: PetscViewerASCIIGetStdout(pf->comm,&viewer);
312: }
316: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
317: if (iascii) {
318: PetscViewerGetFormat(viewer,&format);
319: PetscViewerASCIIPrintf(viewer,"PF Object:\n");
320: PFGetType(pf,&cstr);
321: if (cstr) {
322: PetscViewerASCIIPrintf(viewer," type: %s\n",cstr);
323: } else {
324: PetscViewerASCIIPrintf(viewer," type: not yet set\n");
325: }
326: if (pf->ops->view) {
327: PetscViewerASCIIPushTab(viewer);
328: (*pf->ops->view)(pf->data,viewer);
329: PetscViewerASCIIPopTab(viewer);
330: }
331: } else {
332: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
333: }
334: return(0);
335: }
337: /*MC
338: PFRegisterDynamic - Adds a method to the mathematical function package.
340: Synopsis:
341: PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))
343: Not collective
345: Input Parameters:
346: + name_solver - name of a new user-defined solver
347: . path - path (either absolute or relative) the library containing this solver
348: . name_create - name of routine to create method context
349: - routine_create - routine to create method context
351: Notes:
352: PFRegisterDynamic() may be called multiple times to add several user-defined functions
354: If dynamic libraries are used, then the fourth input argument (routine_create)
355: is ignored.
357: Sample usage:
358: .vb
359: PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
360: "MyFunctionCreate",MyFunctionSetCreate);
361: .ve
363: Then, your solver can be chosen with the procedural interface via
364: $ PFSetType(pf,"my_function")
365: or at runtime via the option
366: $ -pf_type my_function
368: Level: advanced
370: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
371: occuring in pathname will be replaced with appropriate values.
373: .keywords: PF, register
375: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
376: M*/
380: PetscErrorCode PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
381: {
383: char fullname[PETSC_MAX_PATH_LEN];
386: PetscFListConcat(path,name,fullname);
387: PetscFListAdd(&PPetscFList,sname,fullname,(void (*)(void))function);
388: return(0);
389: }
395: /*@C
396: PFGetType - Gets the PF method type and name (as a string) from the PF
397: context.
399: Not Collective
401: Input Parameter:
402: . pf - the function context
404: Output Parameter:
405: . name - name of function
407: Level: intermediate
409: .keywords: PF, get, method, name, type
411: .seealso: PFSetType()
413: @*/
414: PetscErrorCode PFGetType(PF pf,PFType *meth)
415: {
417: *meth = (PFType) pf->type_name;
418: return(0);
419: }
424: /*@C
425: PFSetType - Builds PF for a particular function
427: Collective on PF
429: Input Parameter:
430: + pf - the function context.
431: . type - a known method
432: - ctx - optional type dependent context
434: Options Database Key:
435: . -pf_type <type> - Sets PF type
438: Notes:
439: See "petsc/include/petscpf.h" for available methods (for instance,
440: PFCONSTANT)
442: Level: intermediate
444: .keywords: PF, set, method, type
446: .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DACreatePF()
448: @*/
449: PetscErrorCode PFSetType(PF pf,const PFType type,void *ctx)
450: {
451: PetscErrorCode ierr,(*r)(PF,void*);
452: PetscTruth match;
458: PetscTypeCompare((PetscObject)pf,type,&match);
459: if (match) return(0);
461: if (pf->ops->destroy) { (*pf->ops->destroy)(pf);}
462: pf->data = 0;
464: /* Get the function pointers for the method requested */
465: if (!PFRegisterAllCalled) {PFRegisterAll(0);}
466: /* Determine the PFCreateXXX routine for a particular function */
467: PetscFListFind(pf->comm,PPetscFList,type,(void (**)(void)) &r);
468: if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
469: pf->ops->destroy = 0;
470: pf->ops->view = 0;
471: pf->ops->apply = 0;
472: pf->ops->applyvec = 0;
474: /* Call the PFCreateXXX routine for this particular function */
475: (*r)(pf,ctx);
477: PetscObjectChangeTypeName((PetscObject)pf,type);
478: return(0);
479: }
483: /*@
484: PFSetFromOptions - Sets PF options from the options database.
486: Collective on PF
488: Input Parameters:
489: . pf - the mathematical function context
491: Options Database Keys:
493: Notes:
494: To see all options, run your program with the -help option
495: or consult the users manual.
497: Level: intermediate
499: .keywords: PF, set, from, options, database
501: .seealso:
502: @*/
503: PetscErrorCode PFSetFromOptions(PF pf)
504: {
506: char type[256];
507: PetscTruth flg;
512: if (!PFRegisterAllCalled) {PFRegisterAll(0);}
513: PetscOptionsBegin(pf->comm,pf->prefix,"Mathematical functions options","Vec");
514: PetscOptionsList("-pf_type","Type of function","PFSetType",PPetscFList,0,type,256,&flg);
515: if (flg) {
516: PFSetType(pf,type,PETSC_NULL);
517: }
518: if (pf->ops->setfromoptions) {
519: (*pf->ops->setfromoptions)(pf);
520: }
521: PetscOptionsEnd();
523: return(0);
524: }