Actual source code: pf.c
1: /*
2: The PF mathematical functions interface routines, callable by users.
3: */
4: #include src/vec/pf/pfimpl.h
6: /* Logging support */
7: PetscCookie PF_COOKIE = 0;
9: PetscFList PPetscFList = PETSC_NULL; /* list of all registered PD functions */
10: PetscTruth 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,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: PetscTruth flg;
70: if (--pf->refct > 0) return(0);
72: PetscOptionsHasName(pf->prefix,"-pf_view",&flg);
73: if (flg) {
74: PFView(pf,PETSC_VIEWER_STDOUT_(pf->comm));
75: }
77: /* if memory was published with AMS then destroy it */
78: PetscObjectDepublish(pf);
80: if (pf->ops->destroy) { (*pf->ops->destroy)(pf->data);}
81: PetscLogObjectDestroy(pf);
82: PetscHeaderDestroy(pf);
83: return(0);
84: }
88: static PetscErrorCode PFPublish_Petsc(PetscObject obj)
89: {
90: #if defined(PETSC_HAVE_AMS)
91: PF v = (PF) obj;
93: #endif
97: #if defined(PETSC_HAVE_AMS)
98: /* if it is already published then return */
99: if (v->amem >=0) return(0);
101: PetscObjectPublishBaseBegin(obj);
102: PetscObjectPublishBaseEnd(obj);
103: #endif
105: return(0);
106: }
110: /*@C
111: PFCreate - Creates a mathematical function context.
113: Collective on MPI_Comm
115: Input Parameter:
116: + comm - MPI communicator
117: . dimin - dimension of the space you are mapping from
118: - dimout - dimension of the space you are mapping to
120: Output Parameter:
121: . pf - the function context
123: Level: developer
125: .keywords: PF, create, context
127: .seealso: PFSetUp(), PFApply(), PFDestroy(), PFApplyVec()
128: @*/
129: PetscErrorCode PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
130: {
131: PF newpf;
136: *pf = PETSC_NULL;
137: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
138: VecInitializePackage(PETSC_NULL);
139: #endif
141: PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_COOKIE,-1,"PF",comm,PFDestroy,PFView);
142: PetscLogObjectCreate(newpf);
143: newpf->bops->publish = PFPublish_Petsc;
144: newpf->data = 0;
146: newpf->ops->destroy = 0;
147: newpf->ops->apply = 0;
148: newpf->ops->applyvec = 0;
149: newpf->ops->view = 0;
150: newpf->dimin = dimin;
151: newpf->dimout = dimout;
153: *pf = newpf;
154: PetscPublishAll(pf);
155: return(0);
157: }
159: /* -------------------------------------------------------------------------------*/
163: /*@
164: PFApplyVec - Applies the mathematical function to a vector
166: Collective on PF
168: Input Parameters:
169: + pf - the function context
170: - x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)
172: Output Parameter:
173: . y - output vector
175: Level: beginner
177: .keywords: PF, apply
179: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
180: @*/
181: PetscErrorCode PFApplyVec(PF pf,Vec x,Vec y)
182: {
184: PetscInt i,rstart,rend,n,p;
185: PetscTruth nox = PETSC_FALSE;
190: if (x) {
192: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
193: } else {
194: PetscScalar *xx;
196: VecDuplicate(y,&x);
197: nox = PETSC_TRUE;
198: VecGetOwnershipRange(x,&rstart,&rend);
199: VecGetArray(x,&xx);
200: for (i=rstart; i<rend; i++) {
201: xx[i-rstart] = (PetscScalar)i;
202: }
203: VecRestoreArray(x,&xx);
204: }
206: VecGetLocalSize(x,&n);
207: VecGetLocalSize(y,&p);
208: if (pf->dimin*(n/pf->dimin) != n) SETERRQ2(PETSC_ERR_ARG_IDN,"Local input vector length %D not divisible by dimin %D of function",n,pf->dimin);
209: if (pf->dimout*(p/pf->dimout) != p) SETERRQ2(PETSC_ERR_ARG_IDN,"Local output vector length %D not divisible by dimout %D of function",p,pf->dimout);
210: if (n/pf->dimin != p/pf->dimout) SETERRQ4(PETSC_ERR_ARG_IDN,"Local vector lengths %D %D are wrong for dimin and dimout %D %D of function",n,p,pf->dimin,pf->dimout);
212: if (pf->ops->applyvec) {
213: (*pf->ops->applyvec)(pf->data,x,y);
214: } else {
215: PetscScalar *xx,*yy;
217: VecGetLocalSize(x,&n);
218: n = n/pf->dimin;
219: VecGetArray(x,&xx);
220: VecGetArray(y,&yy);
221: if (!pf->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
222: (*pf->ops->apply)(pf->data,n,xx,yy);
223: VecRestoreArray(x,&xx);
224: VecRestoreArray(y,&yy);
225: }
226: if (nox) {
227: VecDestroy(x);
228: }
229: return(0);
230: }
234: /*@
235: PFApply - Applies the mathematical function to an array of values.
237: Collective on PF
239: Input Parameters:
240: + pf - the function context
241: . n - number of pointwise function evaluations to perform, each pointwise function evaluation
242: is a function of dimin variables and computes dimout variables where dimin and dimout are defined
243: in the call to PFCreate()
244: - x - input array
246: Output Parameter:
247: . y - output array
249: Level: beginner
251: Notes:
253: .keywords: PF, apply
255: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
256: @*/
257: PetscErrorCode PFApply(PF pf,PetscInt n,PetscScalar* x,PetscScalar* y)
258: {
265: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different arrays");
266: if (!pf->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
268: (*pf->ops->apply)(pf->data,n,x,y);
269: return(0);
270: }
274: /*@
275: PFView - Prints information about a mathematical function
277: Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
279: Input Parameters:
280: + PF - the PF context
281: - viewer - optional visualization context
283: Note:
284: The available visualization contexts include
285: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
286: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
287: output where only the first processor opens
288: the file. All other processors send their
289: data to the first processor to print.
291: The user can open an alternative visualization contexts with
292: PetscViewerASCIIOpen() (output to a specified file).
294: Level: developer
296: .keywords: PF, view
298: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
299: @*/
300: PetscErrorCode PFView(PF pf,PetscViewer viewer)
301: {
302: PFType cstr;
304: PetscTruth iascii;
305: PetscViewerFormat format;
309: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pf->comm);
313: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
314: if (iascii) {
315: PetscViewerGetFormat(viewer,&format);
316: PetscViewerASCIIPrintf(viewer,"PF Object:\n");
317: PFGetType(pf,&cstr);
318: if (cstr) {
319: PetscViewerASCIIPrintf(viewer," type: %s\n",cstr);
320: } else {
321: PetscViewerASCIIPrintf(viewer," type: not yet set\n");
322: }
323: if (pf->ops->view) {
324: PetscViewerASCIIPushTab(viewer);
325: (*pf->ops->view)(pf->data,viewer);
326: PetscViewerASCIIPopTab(viewer);
327: }
328: } else {
329: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
330: }
331: return(0);
332: }
334: /*MC
335: PFRegisterDynamic - Adds a method to the mathematical function package.
337: Synopsis:
338: PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))
340: Not collective
342: Input Parameters:
343: + name_solver - name of a new user-defined solver
344: . path - path (either absolute or relative) the library containing this solver
345: . name_create - name of routine to create method context
346: - routine_create - routine to create method context
348: Notes:
349: PFRegisterDynamic() may be called multiple times to add several user-defined functions
351: If dynamic libraries are used, then the fourth input argument (routine_create)
352: is ignored.
354: Sample usage:
355: .vb
356: PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
357: "MyFunctionCreate",MyFunctionSetCreate);
358: .ve
360: Then, your solver can be chosen with the procedural interface via
361: $ PFSetType(pf,"my_function")
362: or at runtime via the option
363: $ -pf_type my_function
365: Level: advanced
367: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
368: occuring in pathname will be replaced with appropriate values.
370: .keywords: PF, register
372: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
373: M*/
377: PetscErrorCode PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
378: {
380: char fullname[PETSC_MAX_PATH_LEN];
383: PetscFListConcat(path,name,fullname);
384: PetscFListAdd(&PPetscFList,sname,fullname,(void (*)(void))function);
385: return(0);
386: }
392: /*@C
393: PFGetType - Gets the PF method type and name (as a string) from the PF
394: context.
396: Not Collective
398: Input Parameter:
399: . pf - the function context
401: Output Parameter:
402: . name - name of function
404: Level: intermediate
406: .keywords: PF, get, method, name, type
408: .seealso: PFSetType()
410: @*/
411: PetscErrorCode PFGetType(PF pf,PFType *meth)
412: {
414: *meth = (PFType) pf->type_name;
415: return(0);
416: }
421: /*@C
422: PFSetType - Builds PF for a particular function
424: Collective on PF
426: Input Parameter:
427: + pf - the function context.
428: . type - a known method
429: - ctx - optional type dependent context
431: Options Database Key:
432: . -pf_type <type> - Sets PF type
435: Notes:
436: See "petsc/include/petscpf.h" for available methods (for instance,
437: PFCONSTANT)
439: Level: intermediate
441: .keywords: PF, set, method, type
443: .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DACreatePF()
445: @*/
446: PetscErrorCode PFSetType(PF pf,const PFType type,void *ctx)
447: {
448: PetscErrorCode ierr,(*r)(PF,void*);
449: PetscTruth match;
455: PetscTypeCompare((PetscObject)pf,type,&match);
456: if (match) return(0);
458: if (pf->ops->destroy) { (*pf->ops->destroy)(pf);}
459: pf->data = 0;
461: /* Get the function pointers for the method requested */
462: if (!PFRegisterAllCalled) {PFRegisterAll(0);}
463: /* Determine the PFCreateXXX routine for a particular function */
464: PetscFListFind(pf->comm,PPetscFList,type,(void (**)(void)) &r);
465: if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
466: pf->ops->destroy = 0;
467: pf->ops->view = 0;
468: pf->ops->apply = 0;
469: pf->ops->applyvec = 0;
471: /* Call the PFCreateXXX routine for this particular function */
472: (*r)(pf,ctx);
474: PetscObjectChangeTypeName((PetscObject)pf,type);
475: return(0);
476: }
480: /*@
481: PFSetFromOptions - Sets PF options from the options database.
483: Collective on PF
485: Input Parameters:
486: . pf - the mathematical function context
488: Options Database Keys:
490: Notes:
491: To see all options, run your program with the -help option
492: or consult the users manual.
494: Level: intermediate
496: .keywords: PF, set, from, options, database
498: .seealso:
499: @*/
500: PetscErrorCode PFSetFromOptions(PF pf)
501: {
503: char type[256];
504: PetscTruth flg;
509: if (!PFRegisterAllCalled) {PFRegisterAll(0);}
510: PetscOptionsBegin(pf->comm,pf->prefix,"Mathematical functions options","Vec");
511: PetscOptionsList("-pf_type","Type of function","PFSetType",PPetscFList,0,type,256,&flg);
512: if (flg) {
513: PFSetType(pf,type,PETSC_NULL);
514: }
515: if (pf->ops->setfromoptions) {
516: (*pf->ops->setfromoptions)(pf);
517: }
518: PetscOptionsEnd();
520: return(0);
521: }