Actual source code: pf.c
1: /*$Id: pf.c,v 1.25 2001/08/07 03:05:06 balay Exp $*/
2: /*
3: The PF mathematical functions interface routines, callable by users.
4: */
5: #include src/pf/pfimpl.h
7: /* Logging support */
8: int PF_COOKIE;
10: PetscFList PPetscFList = PETSC_NULL; /* list of all registered PD functions */
11: PetscTruth PFRegisterAllCalled = PETSC_FALSE;
13: /*@C
14: PFSet - Sets the C/C++/Fortran functions to be used by the PF function
16: Collective on PF
18: Input Parameter:
19: + pf - the function context
20: . apply - function to apply to an array
21: . applyvec - function to apply to a Vec
22: . view - function that prints information about the PF
23: . destroy - function to free the private function context
24: - ctx - private function context
26: Level: beginner
28: .keywords: PF, setting
30: .seealso: PFCreate(), PFDestroy(), PFSetType(), PFApply(), PFApplyVec()
31: @*/
32: int PFSet(PF pf,int(*apply)(void*,int,PetscScalar*,PetscScalar*),int(*applyvec)(void*,Vec,Vec),int(*view)(void*,PetscViewer),int(*destroy)(void*),void*ctx)
33: {
36: pf->data = ctx;
38: pf->ops->destroy = destroy;
39: pf->ops->apply = apply;
40: pf->ops->applyvec = applyvec;
41: pf->ops->view = view;
43: return(0);
44: }
46: /*@C
47: PFDestroy - Destroys PF context that was created with PFCreate().
49: Collective on PF
51: Input Parameter:
52: . pf - the function context
54: Level: beginner
56: .keywords: PF, destroy
58: .seealso: PFCreate(), PFSet(), PFSetType()
59: @*/
60: int PFDestroy(PF pf)
61: {
62: int ierr;
63: PetscTruth flg;
67: if (--pf->refct > 0) return(0);
69: PetscOptionsHasName(pf->prefix,"-pf_view",&flg);
70: if (flg) {
71: PFView(pf,PETSC_VIEWER_STDOUT_(pf->comm));
72: }
74: /* if memory was published with AMS then destroy it */
75: PetscObjectDepublish(pf);
77: if (pf->ops->destroy) { (*pf->ops->destroy)(pf->data);}
78: PetscLogObjectDestroy(pf);
79: PetscHeaderDestroy(pf);
80: return(0);
81: }
83: static int PFPublish_Petsc(PetscObject obj)
84: {
85: #if defined(PETSC_HAVE_AMS)
86: PF v = (PF) obj;
87: int ierr;
88: #endif
92: #if defined(PETSC_HAVE_AMS)
93: /* if it is already published then return */
94: if (v->amem >=0) return(0);
96: PetscObjectPublishBaseBegin(obj);
97: PetscObjectPublishBaseEnd(obj);
98: #endif
100: return(0);
101: }
103: /*@C
104: PFCreate - Creates a mathematical function context.
106: Collective on MPI_Comm
108: Input Parameter:
109: + comm - MPI communicator
110: . dimin - dimension of the space you are mapping from
111: - dimout - dimension of the space you are mapping to
113: Output Parameter:
114: . pf - the function context
116: Level: developer
118: .keywords: PF, create, context
120: .seealso: PFSetUp(), PFApply(), PFDestroy(), PFApplyVec()
121: @*/
122: int PFCreate(MPI_Comm comm,int dimin,int dimout,PF *pf)
123: {
124: PF newpf;
129: *pf = PETSC_NULL;
130: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
131: VecInitializePackage(PETSC_NULL);
132: #endif
134: PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_COOKIE,-1,"PF",comm,PFDestroy,PFView);
135: PetscLogObjectCreate(newpf);
136: newpf->bops->publish = PFPublish_Petsc;
137: newpf->data = 0;
139: newpf->ops->destroy = 0;
140: newpf->ops->apply = 0;
141: newpf->ops->applyvec = 0;
142: newpf->ops->view = 0;
143: newpf->dimin = dimin;
144: newpf->dimout = dimout;
146: *pf = newpf;
147: PetscPublishAll(pf);
148: return(0);
150: }
152: /* -------------------------------------------------------------------------------*/
154: /*@
155: PFApplyVec - Applies the mathematical function to a vector
157: Collective on PF
159: Input Parameters:
160: + pf - the function context
161: - x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)
163: Output Parameter:
164: . y - output vector
166: Level: beginner
168: .keywords: PF, apply
170: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
171: @*/
172: int PFApplyVec(PF pf,Vec x,Vec y)
173: {
174: int ierr,i,rstart,rend,n,p;
175: PetscTruth nox = PETSC_FALSE;
180: if (x) {
182: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
183: } else {
184: PetscScalar *xx;
186: VecDuplicate(y,&x);
187: nox = PETSC_TRUE;
188: VecGetOwnershipRange(x,&rstart,&rend);
189: VecGetArray(x,&xx);
190: for (i=rstart; i<rend; i++) {
191: xx[i-rstart] = (PetscScalar)i;
192: }
193: VecRestoreArray(x,&xx);
194: }
196: VecGetLocalSize(x,&n);
197: VecGetLocalSize(y,&p);
198: 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);
199: 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);
200: 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);
202: if (pf->ops->applyvec) {
203: (*pf->ops->applyvec)(pf->data,x,y);
204: } else {
205: PetscScalar *xx,*yy;
207: VecGetLocalSize(x,&n);
208: n = n/pf->dimin;
209: VecGetArray(x,&xx);
210: VecGetArray(y,&yy);
211: if (!pf->ops->apply) SETERRQ(1,"No function has been provided for this PF");
212: (*pf->ops->apply)(pf->data,n,xx,yy);
213: VecRestoreArray(x,&xx);
214: VecRestoreArray(y,&yy);
215: }
216: if (nox) {
217: VecDestroy(x);
218: }
219: return(0);
220: }
222: /*@
223: PFApply - Applies the mathematical function to an array of values.
225: Collective on PF
227: Input Parameters:
228: + pf - the function context
229: . n - number of pointwise function evaluations to perform, each pointwise function evaluation
230: is a function of dimin variables and computes dimout variables where dimin and dimout are defined
231: in the call to PFCreate()
232: - x - input array
234: Output Parameter:
235: . y - output array
237: Level: beginner
239: Notes:
241: .keywords: PF, apply
243: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
244: @*/
245: int PFApply(PF pf,int n,PetscScalar* x,PetscScalar* y)
246: {
247: int ierr;
251: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different arrays");
252: if (!pf->ops->apply) SETERRQ(1,"No function has been provided for this PF");
254: (*pf->ops->apply)(pf->data,n,x,y);
255: return(0);
256: }
258: /*@
259: PFView - Prints information about a mathematical function
261: Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
263: Input Parameters:
264: + PF - the PF context
265: - viewer - optional visualization context
267: Note:
268: The available visualization contexts include
269: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
270: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
271: output where only the first processor opens
272: the file. All other processors send their
273: data to the first processor to print.
275: The user can open an alternative visualization contexts with
276: PetscViewerASCIIOpen() (output to a specified file).
278: Level: developer
280: .keywords: PF, view
282: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
283: @*/
284: int PFView(PF pf,PetscViewer viewer)
285: {
286: PFType cstr;
287: int ierr;
288: PetscTruth isascii;
289: PetscViewerFormat format;
293: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pf->comm);
297: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
298: if (isascii) {
299: PetscViewerGetFormat(viewer,&format);
300: PetscViewerASCIIPrintf(viewer,"PF Object:n");
301: PFGetType(pf,&cstr);
302: if (cstr) {
303: PetscViewerASCIIPrintf(viewer," type: %sn",cstr);
304: } else {
305: PetscViewerASCIIPrintf(viewer," type: not yet setn");
306: }
307: if (pf->ops->view) {
308: PetscViewerASCIIPushTab(viewer);
309: (*pf->ops->view)(pf->data,viewer);
310: PetscViewerASCIIPopTab(viewer);
311: }
312: } else {
313: SETERRQ1(1,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
314: }
315: return(0);
316: }
318: /*MC
319: PFRegisterDynamic - Adds a method to the mathematical function package.
321: Synopsis:
322: int PFRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(PF))
324: Not collective
326: Input Parameters:
327: + name_solver - name of a new user-defined solver
328: . path - path (either absolute or relative) the library containing this solver
329: . name_create - name of routine to create method context
330: - routine_create - routine to create method context
332: Notes:
333: PFRegisterDynamic() may be called multiple times to add several user-defined functions
335: If dynamic libraries are used, then the fourth input argument (routine_create)
336: is ignored.
338: Sample usage:
339: .vb
340: PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
341: "MyFunctionCreate",MyFunctionSetCreate);
342: .ve
344: Then, your solver can be chosen with the procedural interface via
345: $ PFSetType(pf,"my_function")
346: or at runtime via the option
347: $ -pf_type my_function
349: Level: advanced
351: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
352: occuring in pathname will be replaced with appropriate values.
354: .keywords: PF, register
356: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
357: M*/
359: int PFRegister(char *sname,char *path,char *name,int (*function)(PF,void*))
360: {
361: int ierr;
362: char fullname[256];
365: PetscFListConcat(path,name,fullname);
366: PetscFListAdd(&PPetscFList,sname,fullname,(void (*)(void))function);
367: return(0);
368: }
372: /*@C
373: PFGetType - Gets the PF method type and name (as a string) from the PF
374: context.
376: Not Collective
378: Input Parameter:
379: . pf - the function context
381: Output Parameter:
382: . name - name of function
384: Level: intermediate
386: .keywords: PF, get, method, name, type
388: .seealso: PFSetType()
390: @*/
391: int PFGetType(PF pf,PFType *meth)
392: {
394: *meth = (PFType) pf->type_name;
395: return(0);
396: }
399: /*@C
400: PFSetType - Builds PF for a particular function
402: Collective on PF
404: Input Parameter:
405: + pf - the function context.
406: . type - a known method
407: - ctx - optional type dependent context
409: Options Database Key:
410: . -pf_type <type> - Sets PF type
413: Notes:
414: See "petsc/include/petscpf.h" for available methods (for instance,
415: PFCONSTANT)
417: Level: intermediate
419: .keywords: PF, set, method, type
421: .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DACreatePF()
423: @*/
424: int PFSetType(PF pf,PFType type,void *ctx)
425: {
426: int ierr,(*r)(PF,void*);
427: PetscTruth match;
433: PetscTypeCompare((PetscObject)pf,type,&match);
434: if (match) return(0);
436: if (pf->ops->destroy) { (*pf->ops->destroy)(pf);}
437: pf->data = 0;
439: /* Get the function pointers for the method requested */
440: if (!PFRegisterAllCalled) {PFRegisterAll(0);}
442: /* Determine the PFCreateXXX routine for a particular function */
443: PetscFListFind(pf->comm,PPetscFList,type,(void (**)(void)) &r);
444: if (!r) SETERRQ1(1,"Unable to find requested PF type %s",type);
446: pf->ops->destroy = 0;
447: pf->ops->view = 0;
448: pf->ops->apply = 0;
449: pf->ops->applyvec = 0;
451: /* Call the PFCreateXXX routine for this particular function */
452: (*r)(pf,ctx);
454: PetscObjectChangeTypeName((PetscObject)pf,type);
455: return(0);
456: }
458: /*@
459: PFSetFromOptions - Sets PF options from the options database.
461: Collective on PF
463: Input Parameters:
464: . pf - the mathematical function context
466: Options Database Keys:
468: Notes:
469: To see all options, run your program with the -help option
470: or consult the users manual.
472: Level: intermediate
474: .keywords: PF, set, from, options, database
476: .seealso:
477: @*/
478: int PFSetFromOptions(PF pf)
479: {
480: int ierr;
481: char type[256];
482: PetscTruth flg;
487: if (!PFRegisterAllCalled) {PFRegisterAll(0);}
488: PetscOptionsBegin(pf->comm,pf->prefix,"Mathematical functions options","Vec");
489: PetscOptionsList("-pf_type","Type of function","PFSetType",PPetscFList,0,type,256,&flg);
490: if (flg) {
491: PFSetType(pf,type,PETSC_NULL);
492: }
493: if (pf->ops->setfromoptions) {
494: (*pf->ops->setfromoptions)(pf);
495: }
496: PetscOptionsEnd();
498: return(0);
499: }