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 PETSCVEC_DLLEXPORT 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 PETSCVEC_DLLEXPORT 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: PFView(pf,PETSC_VIEWER_STDOUT_(pf->comm));
76: }
78: /* if memory was published with AMS then destroy it */
79: PetscObjectDepublish(pf);
81: if (pf->ops->destroy) { (*pf->ops->destroy)(pf->data);}
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 PETSCVEC_DLLEXPORT 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: newpf->bops->publish = PFPublish_Petsc;
143: newpf->data = 0;
145: newpf->ops->destroy = 0;
146: newpf->ops->apply = 0;
147: newpf->ops->applyvec = 0;
148: newpf->ops->view = 0;
149: newpf->dimin = dimin;
150: newpf->dimout = dimout;
152: *pf = newpf;
153: PetscPublishAll(pf);
154: return(0);
156: }
158: /* -------------------------------------------------------------------------------*/
162: /*@
163: PFApplyVec - Applies the mathematical function to a vector
165: Collective on PF
167: Input Parameters:
168: + pf - the function context
169: - x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)
171: Output Parameter:
172: . y - output vector
174: Level: beginner
176: .keywords: PF, apply
178: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
179: @*/
180: PetscErrorCode PETSCVEC_DLLEXPORT PFApplyVec(PF pf,Vec x,Vec y)
181: {
183: PetscInt i,rstart,rend,n,p;
184: PetscTruth nox = PETSC_FALSE;
189: if (x) {
191: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
192: } else {
193: PetscScalar *xx;
195: VecDuplicate(y,&x);
196: nox = PETSC_TRUE;
197: VecGetOwnershipRange(x,&rstart,&rend);
198: VecGetArray(x,&xx);
199: for (i=rstart; i<rend; i++) {
200: xx[i-rstart] = (PetscScalar)i;
201: }
202: VecRestoreArray(x,&xx);
203: }
205: VecGetLocalSize(x,&n);
206: VecGetLocalSize(y,&p);
207: 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);
208: 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);
209: 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);
211: if (pf->ops->applyvec) {
212: (*pf->ops->applyvec)(pf->data,x,y);
213: } else {
214: PetscScalar *xx,*yy;
216: VecGetLocalSize(x,&n);
217: n = n/pf->dimin;
218: VecGetArray(x,&xx);
219: VecGetArray(y,&yy);
220: if (!pf->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
221: (*pf->ops->apply)(pf->data,n,xx,yy);
222: VecRestoreArray(x,&xx);
223: VecRestoreArray(y,&yy);
224: }
225: if (nox) {
226: VecDestroy(x);
227: }
228: return(0);
229: }
233: /*@
234: PFApply - Applies the mathematical function to an array of values.
236: Collective on PF
238: Input Parameters:
239: + pf - the function context
240: . n - number of pointwise function evaluations to perform, each pointwise function evaluation
241: is a function of dimin variables and computes dimout variables where dimin and dimout are defined
242: in the call to PFCreate()
243: - x - input array
245: Output Parameter:
246: . y - output array
248: Level: beginner
250: Notes:
252: .keywords: PF, apply
254: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
255: @*/
256: PetscErrorCode PETSCVEC_DLLEXPORT PFApply(PF pf,PetscInt n,PetscScalar* x,PetscScalar* y)
257: {
264: if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different arrays");
265: if (!pf->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
267: (*pf->ops->apply)(pf->data,n,x,y);
268: return(0);
269: }
273: /*@
274: PFView - Prints information about a mathematical function
276: Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
278: Input Parameters:
279: + PF - the PF context
280: - viewer - optional visualization context
282: Note:
283: The available visualization contexts include
284: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
285: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
286: output where only the first processor opens
287: the file. All other processors send their
288: data to the first processor to print.
290: The user can open an alternative visualization contexts with
291: PetscViewerASCIIOpen() (output to a specified file).
293: Level: developer
295: .keywords: PF, view
297: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
298: @*/
299: PetscErrorCode PETSCVEC_DLLEXPORT PFView(PF pf,PetscViewer viewer)
300: {
301: PFType cstr;
303: PetscTruth iascii;
304: PetscViewerFormat format;
308: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pf->comm);
312: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
313: if (iascii) {
314: PetscViewerGetFormat(viewer,&format);
315: PetscViewerASCIIPrintf(viewer,"PF Object:\n");
316: PFGetType(pf,&cstr);
317: if (cstr) {
318: PetscViewerASCIIPrintf(viewer," type: %s\n",cstr);
319: } else {
320: PetscViewerASCIIPrintf(viewer," type: not yet set\n");
321: }
322: if (pf->ops->view) {
323: PetscViewerASCIIPushTab(viewer);
324: (*pf->ops->view)(pf->data,viewer);
325: PetscViewerASCIIPopTab(viewer);
326: }
327: } else {
328: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
329: }
330: return(0);
331: }
333: /*MC
334: PFRegisterDynamic - Adds a method to the mathematical function package.
336: Synopsis:
337: PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))
339: Not collective
341: Input Parameters:
342: + name_solver - name of a new user-defined solver
343: . path - path (either absolute or relative) the library containing this solver
344: . name_create - name of routine to create method context
345: - routine_create - routine to create method context
347: Notes:
348: PFRegisterDynamic() may be called multiple times to add several user-defined functions
350: If dynamic libraries are used, then the fourth input argument (routine_create)
351: is ignored.
353: Sample usage:
354: .vb
355: PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
356: "MyFunctionCreate",MyFunctionSetCreate);
357: .ve
359: Then, your solver can be chosen with the procedural interface via
360: $ PFSetType(pf,"my_function")
361: or at runtime via the option
362: $ -pf_type my_function
364: Level: advanced
366: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
367: occuring in pathname will be replaced with appropriate values.
369: .keywords: PF, register
371: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
372: M*/
376: PetscErrorCode PETSCVEC_DLLEXPORT PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
377: {
379: char fullname[PETSC_MAX_PATH_LEN];
382: PetscFListConcat(path,name,fullname);
383: PetscFListAdd(&PPetscFList,sname,fullname,(void (*)(void))function);
384: return(0);
385: }
391: /*@C
392: PFGetType - Gets the PF method type and name (as a string) from the PF
393: context.
395: Not Collective
397: Input Parameter:
398: . pf - the function context
400: Output Parameter:
401: . name - name of function
403: Level: intermediate
405: .keywords: PF, get, method, name, type
407: .seealso: PFSetType()
409: @*/
410: PetscErrorCode PETSCVEC_DLLEXPORT PFGetType(PF pf,PFType *meth)
411: {
413: *meth = (PFType) pf->type_name;
414: return(0);
415: }
420: /*@C
421: PFSetType - Builds PF for a particular function
423: Collective on PF
425: Input Parameter:
426: + pf - the function context.
427: . type - a known method
428: - ctx - optional type dependent context
430: Options Database Key:
431: . -pf_type <type> - Sets PF type
434: Notes:
435: See "petsc/include/petscpf.h" for available methods (for instance,
436: PFCONSTANT)
438: Level: intermediate
440: .keywords: PF, set, method, type
442: .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DACreatePF()
444: @*/
445: PetscErrorCode PETSCVEC_DLLEXPORT PFSetType(PF pf,const PFType type,void *ctx)
446: {
447: PetscErrorCode ierr,(*r)(PF,void*);
448: PetscTruth match;
454: PetscTypeCompare((PetscObject)pf,type,&match);
455: if (match) return(0);
457: if (pf->ops->destroy) { (*pf->ops->destroy)(pf);}
458: pf->data = 0;
460: /* Get the function pointers for the method requested */
461: if (!PFRegisterAllCalled) {PFRegisterAll(0);}
462: /* Determine the PFCreateXXX routine for a particular function */
463: PetscFListFind(pf->comm,PPetscFList,type,(void (**)(void)) &r);
464: if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
465: pf->ops->destroy = 0;
466: pf->ops->view = 0;
467: pf->ops->apply = 0;
468: pf->ops->applyvec = 0;
470: /* Call the PFCreateXXX routine for this particular function */
471: (*r)(pf,ctx);
473: PetscObjectChangeTypeName((PetscObject)pf,type);
474: return(0);
475: }
479: /*@
480: PFSetFromOptions - Sets PF options from the options database.
482: Collective on PF
484: Input Parameters:
485: . pf - the mathematical function context
487: Options Database Keys:
489: Notes:
490: To see all options, run your program with the -help option
491: or consult the users manual.
493: Level: intermediate
495: .keywords: PF, set, from, options, database
497: .seealso:
498: @*/
499: PetscErrorCode PETSCVEC_DLLEXPORT PFSetFromOptions(PF pf)
500: {
502: char type[256];
503: PetscTruth flg;
508: if (!PFRegisterAllCalled) {PFRegisterAll(0);}
509: PetscOptionsBegin(pf->comm,pf->prefix,"Mathematical functions options","Vec");
510: PetscOptionsList("-pf_type","Type of function","PFSetType",PPetscFList,0,type,256,&flg);
511: if (flg) {
512: PFSetType(pf,type,PETSC_NULL);
513: }
514: if (pf->ops->setfromoptions) {
515: (*pf->ops->setfromoptions)(pf);
516: }
517: PetscOptionsEnd();
519: return(0);
520: }