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: 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
15: Input Parameters:
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: .seealso: `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFApply()`, `PFApplyVec()`
26: @*/
27: 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)
28: {
29: PetscFunctionBegin;
31: pf->data = ctx;
32: pf->ops->destroy = destroy;
33: pf->ops->apply = apply;
34: pf->ops->applyvec = applyvec;
35: pf->ops->view = view;
36: PetscFunctionReturn(PETSC_SUCCESS);
37: }
39: /*@C
40: PFDestroy - Destroys `PF` context that was created with `PFCreate()`.
42: Collective
44: Input Parameter:
45: . pf - the function context
47: Level: beginner
49: .seealso: `PFCreate()`, `PFSet()`, `PFSetType()`
50: @*/
51: PetscErrorCode PFDestroy(PF *pf)
52: {
53: PetscFunctionBegin;
54: if (!*pf) PetscFunctionReturn(PETSC_SUCCESS);
56: if (--((PetscObject)(*pf))->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
58: PetscCall(PFViewFromOptions(*pf, NULL, "-pf_view"));
59: /* if memory was published with SAWs then destroy it */
60: PetscCall(PetscObjectSAWsViewOff((PetscObject)*pf));
62: if ((*pf)->ops->destroy) PetscCall((*(*pf)->ops->destroy)((*pf)->data));
63: PetscCall(PetscHeaderDestroy(pf));
64: PetscFunctionReturn(PETSC_SUCCESS);
65: }
67: /*@C
68: PFCreate - Creates a mathematical function context.
70: Collective
72: Input Parameters:
73: + comm - MPI communicator
74: . dimin - dimension of the space you are mapping from
75: - dimout - dimension of the space you are mapping to
77: Output Parameter:
78: . pf - the function context
80: Level: developer
82: .seealso: `PFSet()`, `PFApply()`, `PFDestroy()`, `PFApplyVec()`
83: @*/
84: PetscErrorCode PFCreate(MPI_Comm comm, PetscInt dimin, PetscInt dimout, PF *pf)
85: {
86: PF newpf;
88: PetscFunctionBegin;
90: *pf = NULL;
91: PetscCall(PFInitializePackage());
93: PetscCall(PetscHeaderCreate(newpf, PF_CLASSID, "PF", "Mathematical functions", "Vec", comm, PFDestroy, PFView));
94: newpf->data = NULL;
95: newpf->ops->destroy = NULL;
96: newpf->ops->apply = NULL;
97: newpf->ops->applyvec = NULL;
98: newpf->ops->view = NULL;
99: newpf->dimin = dimin;
100: newpf->dimout = dimout;
102: *pf = newpf;
103: PetscFunctionReturn(PETSC_SUCCESS);
104: }
106: /* -------------------------------------------------------------------------------*/
108: /*@
109: PFApplyVec - Applies the mathematical function to a vector
111: Collective
113: Input Parameters:
114: + pf - the function context
115: - x - input vector (or NULL for the vector (0,1, .... N-1)
117: Output Parameter:
118: . y - output vector
120: Level: beginner
122: .seealso: `PFApply()`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFSet()`
123: @*/
124: PetscErrorCode PFApplyVec(PF pf, Vec x, Vec y)
125: {
126: PetscInt i, rstart, rend, n, p;
127: PetscBool nox = PETSC_FALSE;
129: PetscFunctionBegin;
132: if (x) {
134: PetscCheck(x != y, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "x and y must be different vectors");
135: } else {
136: PetscScalar *xx;
137: PetscInt lsize;
139: PetscCall(VecGetLocalSize(y, &lsize));
140: lsize = pf->dimin * lsize / pf->dimout;
141: PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)y), lsize, PETSC_DETERMINE, &x));
142: nox = PETSC_TRUE;
143: PetscCall(VecGetOwnershipRange(x, &rstart, &rend));
144: PetscCall(VecGetArray(x, &xx));
145: for (i = rstart; i < rend; i++) xx[i - rstart] = (PetscScalar)i;
146: PetscCall(VecRestoreArray(x, &xx));
147: }
149: PetscCall(VecGetLocalSize(x, &n));
150: PetscCall(VecGetLocalSize(y, &p));
151: PetscCheck((pf->dimin * (n / pf->dimin)) == n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local input vector length %" PetscInt_FMT " not divisible by dimin %" PetscInt_FMT " of function", n, pf->dimin);
152: PetscCheck((pf->dimout * (p / pf->dimout)) == p, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local output vector length %" PetscInt_FMT " not divisible by dimout %" PetscInt_FMT " of function", p, pf->dimout);
153: PetscCheck((n / pf->dimin) == (p / pf->dimout), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local vector lengths %" PetscInt_FMT " %" PetscInt_FMT " are wrong for dimin and dimout %" PetscInt_FMT " %" PetscInt_FMT " of function", n, p, pf->dimin, pf->dimout);
155: if (pf->ops->applyvec) PetscCall((*pf->ops->applyvec)(pf->data, x, y));
156: else {
157: PetscScalar *xx, *yy;
159: PetscCall(VecGetLocalSize(x, &n));
160: n = n / pf->dimin;
161: PetscCall(VecGetArray(x, &xx));
162: PetscCall(VecGetArray(y, &yy));
163: PetscCall((*pf->ops->apply)(pf->data, n, xx, yy));
164: PetscCall(VecRestoreArray(x, &xx));
165: PetscCall(VecRestoreArray(y, &yy));
166: }
167: if (nox) PetscCall(VecDestroy(&x));
168: PetscFunctionReturn(PETSC_SUCCESS);
169: }
171: /*@
172: PFApply - Applies the mathematical function to an array of values.
174: Collective
176: Input Parameters:
177: + pf - the function context
178: . n - number of pointwise function evaluations to perform, each pointwise function evaluation
179: is a function of dimin variables and computes dimout variables where dimin and dimout are defined
180: in the call to PFCreate()
181: - x - input array
183: Output Parameter:
184: . y - output array
186: Level: beginner
188: Notes:
190: .seealso: `PFApplyVec()`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFSet()`
191: @*/
192: PetscErrorCode PFApply(PF pf, PetscInt n, const PetscScalar *x, PetscScalar *y)
193: {
194: PetscFunctionBegin;
198: PetscCheck(x != y, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "x and y must be different arrays");
200: PetscCall((*pf->ops->apply)(pf->data, n, x, y));
201: PetscFunctionReturn(PETSC_SUCCESS);
202: }
204: /*@C
205: PFViewFromOptions - View from Options
207: Collective
209: Input Parameters:
210: + A - the PF context
211: . obj - Optional object
212: - name - command line option
214: Level: intermediate
215: .seealso: `PF`, `PFView`, `PetscObjectViewFromOptions()`, `PFCreate()`
216: @*/
217: PetscErrorCode PFViewFromOptions(PF A, PetscObject obj, const char name[])
218: {
219: PetscFunctionBegin;
221: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
222: PetscFunctionReturn(PETSC_SUCCESS);
223: }
225: /*@
226: PFView - Prints information about a mathematical function
228: Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF
230: Input Parameters:
231: + PF - the PF context
232: - viewer - optional visualization context
234: Note:
235: The available visualization contexts include
236: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
237: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
238: output where only the first processor opens
239: the file. All other processors send their
240: data to the first processor to print.
242: The user can open an alternative visualization contexts with
243: PetscViewerASCIIOpen() (output to a specified file).
245: Level: developer
247: .seealso: `PetscViewerCreate()`, `PetscViewerASCIIOpen()`
248: @*/
249: PetscErrorCode PFView(PF pf, PetscViewer viewer)
250: {
251: PetscBool iascii;
252: PetscViewerFormat format;
254: PetscFunctionBegin;
256: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf), &viewer));
258: PetscCheckSameComm(pf, 1, viewer, 2);
260: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
261: if (iascii) {
262: PetscCall(PetscViewerGetFormat(viewer, &format));
263: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pf, viewer));
264: if (pf->ops->view) {
265: PetscCall(PetscViewerASCIIPushTab(viewer));
266: PetscCall((*pf->ops->view)(pf->data, viewer));
267: PetscCall(PetscViewerASCIIPopTab(viewer));
268: }
269: }
270: PetscFunctionReturn(PETSC_SUCCESS);
271: }
273: /*@C
274: PFRegister - Adds a method to the mathematical function package.
276: Not collective
278: Input Parameters:
279: + name_solver - name of a new user-defined solver
280: - routine_create - routine to create method context
282: Notes:
283: PFRegister() may be called multiple times to add several user-defined functions
285: Sample usage:
286: .vb
287: PFRegister("my_function",MyFunctionSetCreate);
288: .ve
290: Then, your solver can be chosen with the procedural interface via
291: $ PFSetType(pf,"my_function")
292: or at runtime via the option
293: $ -pf_type my_function
295: Level: advanced
297: .seealso: `PFRegisterAll()`, `PFRegisterDestroy()`, `PFRegister()`
298: @*/
299: PetscErrorCode PFRegister(const char sname[], PetscErrorCode (*function)(PF, void *))
300: {
301: PetscFunctionBegin;
302: PetscCall(PFInitializePackage());
303: PetscCall(PetscFunctionListAdd(&PFList, sname, function));
304: PetscFunctionReturn(PETSC_SUCCESS);
305: }
307: /*@C
308: PFGetType - Gets the PF method type and name (as a string) from the PF
309: context.
311: Not Collective
313: Input Parameter:
314: . pf - the function context
316: Output Parameter:
317: . type - name of function
319: Level: intermediate
321: .seealso: `PFSetType()`
323: @*/
324: PetscErrorCode PFGetType(PF pf, PFType *type)
325: {
326: PetscFunctionBegin;
329: *type = ((PetscObject)pf)->type_name;
330: PetscFunctionReturn(PETSC_SUCCESS);
331: }
333: /*@C
334: PFSetType - Builds PF for a particular function
336: Collective
338: Input Parameters:
339: + pf - the function context.
340: . type - a known method
341: - ctx - optional type dependent context
343: Options Database Key:
344: . -pf_type <type> - Sets PF type
346: Notes:
347: See "petsc/include/petscpf.h" for available methods (for instance,
348: PFCONSTANT)
350: Level: intermediate
352: .seealso: `PFSet()`, `PFRegister()`, `PFCreate()`, `DMDACreatePF()`
354: @*/
355: PetscErrorCode PFSetType(PF pf, PFType type, void *ctx)
356: {
357: PetscBool match;
358: PetscErrorCode (*r)(PF, void *);
360: PetscFunctionBegin;
364: PetscCall(PetscObjectTypeCompare((PetscObject)pf, type, &match));
365: if (match) PetscFunctionReturn(PETSC_SUCCESS);
367: PetscTryTypeMethod(pf, destroy);
368: pf->data = NULL;
370: /* Determine the PFCreateXXX routine for a particular function */
371: PetscCall(PetscFunctionListFind(PFList, type, &r));
372: PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PF type %s", type);
373: pf->ops->destroy = NULL;
374: pf->ops->view = NULL;
375: pf->ops->apply = NULL;
376: pf->ops->applyvec = NULL;
378: /* Call the PFCreateXXX routine for this particular function */
379: PetscCall((*r)(pf, ctx));
381: PetscCall(PetscObjectChangeTypeName((PetscObject)pf, type));
382: PetscFunctionReturn(PETSC_SUCCESS);
383: }
385: /*@
386: PFSetFromOptions - Sets PF options from the options database.
388: Collective
390: Input Parameters:
391: . pf - the mathematical function context
393: Options Database Keys:
395: Notes:
396: To see all options, run your program with the -help option
397: or consult the users manual.
399: Level: intermediate
401: .seealso:
402: @*/
403: PetscErrorCode PFSetFromOptions(PF pf)
404: {
405: char type[256];
406: PetscBool flg;
408: PetscFunctionBegin;
411: PetscObjectOptionsBegin((PetscObject)pf);
412: PetscCall(PetscOptionsFList("-pf_type", "Type of function", "PFSetType", PFList, NULL, type, 256, &flg));
413: if (flg) PetscCall(PFSetType(pf, type, NULL));
414: PetscTryTypeMethod(pf, setfromoptions, PetscOptionsObject);
416: /* process any options handlers added with PetscObjectAddOptionsHandler() */
417: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pf, PetscOptionsObject));
418: PetscOptionsEnd();
419: PetscFunctionReturn(PETSC_SUCCESS);
420: }
422: static PetscBool PFPackageInitialized = PETSC_FALSE;
423: /*@C
424: PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
425: called from PetscFinalize().
427: Level: developer
429: .seealso: `PetscFinalize()`
430: @*/
431: PetscErrorCode PFFinalizePackage(void)
432: {
433: PetscFunctionBegin;
434: PetscCall(PetscFunctionListDestroy(&PFList));
435: PFPackageInitialized = PETSC_FALSE;
436: PFRegisterAllCalled = PETSC_FALSE;
437: PetscFunctionReturn(PETSC_SUCCESS);
438: }
440: /*@C
441: PFInitializePackage - This function initializes everything in the PF package. It is called
442: from PetscDLLibraryRegister_petscvec() when using dynamic libraries, and on the first call to PFCreate()
443: when using shared or static libraries.
445: Level: developer
447: .seealso: `PetscInitialize()`
448: @*/
449: PetscErrorCode PFInitializePackage(void)
450: {
451: char logList[256];
452: PetscBool opt, pkg;
454: PetscFunctionBegin;
455: if (PFPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
456: PFPackageInitialized = PETSC_TRUE;
457: /* Register Classes */
458: PetscCall(PetscClassIdRegister("PointFunction", &PF_CLASSID));
459: /* Register Constructors */
460: PetscCall(PFRegisterAll());
461: /* Process Info */
462: {
463: PetscClassId classids[1];
465: classids[0] = PF_CLASSID;
466: PetscCall(PetscInfoProcessClass("pf", 1, classids));
467: }
468: /* Process summary exclusions */
469: PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt));
470: if (opt) {
471: PetscCall(PetscStrInList("pf", logList, ',', &pkg));
472: if (pkg) PetscCall(PetscLogEventExcludeClass(PF_CLASSID));
473: }
474: /* Register package finalizer */
475: PetscCall(PetscRegisterFinalize(PFFinalizePackage));
476: PetscFunctionReturn(PETSC_SUCCESS);
477: }