Actual source code: pf.c
petsc-3.10.5 2019-03-28
1: /*
2: The PF mathematical functions interface routines, callable by users.
3: */
4: #include <../src/vec/pf/pfimpl.h>
6: PetscClassId PF_CLASSID = 0;
7: PetscFunctionList PFList = NULL; /* list of all registered PD functions */
8: PetscBool PFRegisterAllCalled = PETSC_FALSE;
10: /*@C
11: PFSet - Sets the C/C++/Fortran functions to be used by the PF function
13: Collective on PF
15: Input Parameter:
16: + pf - the function context
17: . apply - function to apply to an array
18: . applyvec - function to apply to a Vec
19: . view - function that prints information about the PF
20: . destroy - function to free the private function context
21: - ctx - private function context
23: Level: beginner
25: .keywords: PF, setting
27: .seealso: PFCreate(), PFDestroy(), PFSetType(), PFApply(), PFApplyVec()
28: @*/
29: 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)
30: {
33: pf->data = ctx;
34: pf->ops->destroy = destroy;
35: pf->ops->apply = apply;
36: pf->ops->applyvec = applyvec;
37: pf->ops->view = view;
38: return(0);
39: }
41: /*@C
42: PFDestroy - Destroys PF context that was created with PFCreate().
44: Collective on PF
46: Input Parameter:
47: . pf - the function context
49: Level: beginner
51: .keywords: PF, destroy
53: .seealso: PFCreate(), PFSet(), PFSetType()
54: @*/
55: PetscErrorCode PFDestroy(PF *pf)
56: {
60: if (!*pf) return(0);
62: if (--((PetscObject)(*pf))->refct > 0) return(0);
64: PFViewFromOptions(*pf,NULL,"-pf_view");
65: /* if memory was published with SAWs then destroy it */
66: PetscObjectSAWsViewOff((PetscObject)*pf);
68: if ((*pf)->ops->destroy) { (*(*pf)->ops->destroy)((*pf)->data);}
69: PetscHeaderDestroy(pf);
70: return(0);
71: }
73: /*@C
74: PFCreate - Creates a mathematical function context.
76: Collective on MPI_Comm
78: Input Parameter:
79: + comm - MPI communicator
80: . dimin - dimension of the space you are mapping from
81: - dimout - dimension of the space you are mapping to
83: Output Parameter:
84: . pf - the function context
86: Level: developer
88: .keywords: PF, create, context
90: .seealso: PFSet(), PFApply(), PFDestroy(), PFApplyVec()
91: @*/
92: PetscErrorCode PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
93: {
94: PF newpf;
99: *pf = NULL;
100: PFInitializePackage();
102: PetscHeaderCreate(newpf,PF_CLASSID,"PF","Mathematical functions","Vec",comm,PFDestroy,PFView);
103: newpf->data = 0;
104: newpf->ops->destroy = 0;
105: newpf->ops->apply = 0;
106: newpf->ops->applyvec = 0;
107: newpf->ops->view = 0;
108: newpf->dimin = dimin;
109: newpf->dimout = dimout;
111: *pf = newpf;
112: return(0);
114: }
116: /* -------------------------------------------------------------------------------*/
118: /*@
119: PFApplyVec - Applies the mathematical function to a vector
121: Collective on PF
123: Input Parameters:
124: + pf - the function context
125: - x - input vector (or NULL for the vector (0,1, .... N-1)
127: Output Parameter:
128: . y - output vector
130: Level: beginner
132: .keywords: PF, apply
134: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
135: @*/
136: PetscErrorCode PFApplyVec(PF pf,Vec x,Vec y)
137: {
139: PetscInt i,rstart,rend,n,p;
140: PetscBool nox = PETSC_FALSE;
145: if (x) {
147: if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors");
148: } else {
149: PetscScalar *xx;
150: PetscInt lsize;
152: VecGetLocalSize(y,&lsize);
153: lsize = pf->dimin*lsize/pf->dimout;
154: VecCreateMPI(PetscObjectComm((PetscObject)y),lsize,PETSC_DETERMINE,&x);
155: nox = PETSC_TRUE;
156: VecGetOwnershipRange(x,&rstart,&rend);
157: VecGetArray(x,&xx);
158: for (i=rstart; i<rend; i++) xx[i-rstart] = (PetscScalar)i;
159: VecRestoreArray(x,&xx);
160: }
162: VecGetLocalSize(x,&n);
163: VecGetLocalSize(y,&p);
164: 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);
165: 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);
166: 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);
168: if (pf->ops->applyvec) {
169: (*pf->ops->applyvec)(pf->data,x,y);
170: } else {
171: PetscScalar *xx,*yy;
173: VecGetLocalSize(x,&n);
174: n = n/pf->dimin;
175: VecGetArray(x,&xx);
176: VecGetArray(y,&yy);
177: if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
178: (*pf->ops->apply)(pf->data,n,xx,yy);
179: VecRestoreArray(x,&xx);
180: VecRestoreArray(y,&yy);
181: }
182: if (nox) {
183: VecDestroy(&x);
184: }
185: return(0);
186: }
188: /*@
189: PFApply - Applies the mathematical function to an array of values.
191: Collective on PF
193: Input Parameters:
194: + pf - the function context
195: . n - number of pointwise function evaluations to perform, each pointwise function evaluation
196: is a function of dimin variables and computes dimout variables where dimin and dimout are defined
197: in the call to PFCreate()
198: - x - input array
200: Output Parameter:
201: . y - output array
203: Level: beginner
205: Notes:
207: .keywords: PF, apply
209: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
210: @*/
211: PetscErrorCode PFApply(PF pf,PetscInt n,const PetscScalar *x,PetscScalar *y)
212: {
219: if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different arrays");
220: if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
222: (*pf->ops->apply)(pf->data,n,x,y);
223: return(0);
224: }
226: /*@
227: PFView - Prints information about a mathematical function
229: Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
231: Input Parameters:
232: + PF - the PF context
233: - viewer - optional visualization context
235: Note:
236: The available visualization contexts include
237: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
238: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
239: output where only the first processor opens
240: the file. All other processors send their
241: data to the first processor to print.
243: The user can open an alternative visualization contexts with
244: PetscViewerASCIIOpen() (output to a specified file).
246: Level: developer
248: .keywords: PF, view
250: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
251: @*/
252: PetscErrorCode PFView(PF pf,PetscViewer viewer)
253: {
254: PetscErrorCode ierr;
255: PetscBool iascii;
256: PetscViewerFormat format;
260: if (!viewer) {
261: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf),&viewer);
262: }
266: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
267: if (iascii) {
268: PetscViewerGetFormat(viewer,&format);
269: PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer);
270: if (pf->ops->view) {
271: PetscViewerASCIIPushTab(viewer);
272: (*pf->ops->view)(pf->data,viewer);
273: PetscViewerASCIIPopTab(viewer);
274: }
275: }
276: return(0);
277: }
280: /*@C
281: PFRegister - Adds a method to the mathematical function package.
283: Not collective
285: Input Parameters:
286: + name_solver - name of a new user-defined solver
287: - routine_create - routine to create method context
289: Notes:
290: PFRegister() may be called multiple times to add several user-defined functions
292: Sample usage:
293: .vb
294: PFRegister("my_function",MyFunctionSetCreate);
295: .ve
297: Then, your solver can be chosen with the procedural interface via
298: $ PFSetType(pf,"my_function")
299: or at runtime via the option
300: $ -pf_type my_function
302: Level: advanced
304: .keywords: PF, register
306: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
307: @*/
308: PetscErrorCode PFRegister(const char sname[],PetscErrorCode (*function)(PF,void*))
309: {
313: PFInitializePackage();
314: PetscFunctionListAdd(&PFList,sname,function);
315: return(0);
316: }
318: /*@C
319: PFGetType - Gets the PF method type and name (as a string) from the PF
320: context.
322: Not Collective
324: Input Parameter:
325: . pf - the function context
327: Output Parameter:
328: . type - name of function
330: Level: intermediate
332: .keywords: PF, get, method, name, type
334: .seealso: PFSetType()
336: @*/
337: PetscErrorCode PFGetType(PF pf,PFType *type)
338: {
342: *type = ((PetscObject)pf)->type_name;
343: return(0);
344: }
347: /*@C
348: PFSetType - Builds PF for a particular function
350: Collective on PF
352: Input Parameter:
353: + pf - the function context.
354: . type - a known method
355: - ctx - optional type dependent context
357: Options Database Key:
358: . -pf_type <type> - Sets PF type
361: Notes:
362: See "petsc/include/petscpf.h" for available methods (for instance,
363: PFCONSTANT)
365: Level: intermediate
367: .keywords: PF, set, method, type
369: .seealso: PFSet(), PFRegister(), PFCreate(), DMDACreatePF()
371: @*/
372: PetscErrorCode PFSetType(PF pf,PFType type,void *ctx)
373: {
374: PetscErrorCode ierr,(*r)(PF,void*);
375: PetscBool match;
381: PetscObjectTypeCompare((PetscObject)pf,type,&match);
382: if (match) return(0);
384: if (pf->ops->destroy) { (*pf->ops->destroy)(pf);}
385: pf->data = 0;
387: /* Determine the PFCreateXXX routine for a particular function */
388: PetscFunctionListFind(PFList,type,&r);
389: if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
390: pf->ops->destroy = 0;
391: pf->ops->view = 0;
392: pf->ops->apply = 0;
393: pf->ops->applyvec = 0;
395: /* Call the PFCreateXXX routine for this particular function */
396: (*r)(pf,ctx);
398: PetscObjectChangeTypeName((PetscObject)pf,type);
399: return(0);
400: }
402: /*@
403: PFSetFromOptions - Sets PF options from the options database.
405: Collective on PF
407: Input Parameters:
408: . pf - the mathematical function context
410: Options Database Keys:
412: Notes:
413: To see all options, run your program with the -help option
414: or consult the users manual.
416: Level: intermediate
418: .keywords: PF, set, from, options, database
420: .seealso:
421: @*/
422: PetscErrorCode PFSetFromOptions(PF pf)
423: {
425: char type[256];
426: PetscBool flg;
431: PetscObjectOptionsBegin((PetscObject)pf);
432: PetscOptionsFList("-pf_type","Type of function","PFSetType",PFList,0,type,256,&flg);
433: if (flg) {
434: PFSetType(pf,type,NULL);
435: }
436: if (pf->ops->setfromoptions) {
437: (*pf->ops->setfromoptions)(PetscOptionsObject,pf);
438: }
440: /* process any options handlers added with PetscObjectAddOptionsHandler() */
441: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pf);
442: PetscOptionsEnd();
443: return(0);
444: }
446: static PetscBool PFPackageInitialized = PETSC_FALSE;
447: /*@C
448: PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
449: called from PetscFinalize().
451: Level: developer
453: .keywords: Petsc, destroy, package, mathematica
454: .seealso: PetscFinalize()
455: @*/
456: PetscErrorCode PFFinalizePackage(void)
457: {
461: PetscFunctionListDestroy(&PFList);
462: PFPackageInitialized = PETSC_FALSE;
463: PFRegisterAllCalled = PETSC_FALSE;
464: return(0);
465: }
467: /*@C
468: PFInitializePackage - This function initializes everything in the PF package. It is called
469: from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
470: when using static libraries.
472: Level: developer
474: .keywords: Vec, initialize, package
475: .seealso: PetscInitialize()
476: @*/
477: PetscErrorCode PFInitializePackage(void)
478: {
479: char logList[256];
480: PetscBool opt,pkg;
484: if (PFPackageInitialized) return(0);
485: PFPackageInitialized = PETSC_TRUE;
486: /* Register Classes */
487: PetscClassIdRegister("PointFunction",&PF_CLASSID);
488: /* Register Constructors */
489: PFRegisterAll();
490: /* Process info exclusions */
491: PetscOptionsGetString(NULL,NULL,"-info_exclude",logList,sizeof(logList),&opt);
492: if (opt) {
493: PetscStrInList("pf",logList,',',&pkg);
494: if (pkg) {PetscInfoDeactivateClass(PF_CLASSID);}
495: }
496: /* Process summary exclusions */
497: PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt);
498: if (opt) {
499: PetscStrInList("pf",logList,',',&pkg);
500: if (pkg) {PetscLogEventExcludeClass(PF_CLASSID);}
501: }
502: /* Register package finalizer */
503: PetscRegisterFinalize(PFFinalizePackage);
504: return(0);
505: }