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: /*@
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: `PF`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFApply()`, `PFApplyVec()`
26: @*/
27: PetscErrorCode PFSet(PF pf, PetscErrorCode (*apply)(PetscCtx, PetscInt, const PetscScalar *, PetscScalar *), PetscErrorCode (*applyvec)(PetscCtx, Vec, Vec), PetscErrorCode (*view)(PetscCtx, PetscViewer), PetscErrorCode (*destroy)(PetscCtxRt), PetscCtx 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: /*@
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: `PF`, `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: /*@
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: `PF`, `PFSet()`, `PFApply()`, `PFDestroy()`, `PFApplyVec()`
83: @*/
84: PetscErrorCode PFCreate(MPI_Comm comm, PetscInt dimin, PetscInt dimout, PF *pf)
85: {
86: PF newpf;
88: PetscFunctionBegin;
89: PetscAssertPointer(pf, 4);
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: /*@
107: PFApplyVec - Applies the mathematical function to a vector
109: Collective
111: Input Parameters:
112: + pf - the function context
113: - x - input vector (or `NULL` for the vector (0,1, .... N-1)
115: Output Parameter:
116: . y - output vector
118: Level: beginner
120: .seealso: `PF`, `PFApply()`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFSet()`
121: @*/
122: PetscErrorCode PFApplyVec(PF pf, Vec x, Vec y)
123: {
124: PetscInt i, rstart, rend, n, p;
125: PetscBool nox = PETSC_FALSE;
127: PetscFunctionBegin;
130: if (x) {
132: PetscCheck(x != y, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "x and y must be different vectors");
133: } else {
134: PetscScalar *xx;
135: PetscInt lsize;
137: PetscCall(VecGetLocalSize(y, &lsize));
138: lsize = pf->dimin * lsize / pf->dimout;
139: PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)y), lsize, PETSC_DETERMINE, &x));
140: nox = PETSC_TRUE;
141: PetscCall(VecGetOwnershipRange(x, &rstart, &rend));
142: PetscCall(VecGetArray(x, &xx));
143: for (i = rstart; i < rend; i++) xx[i - rstart] = (PetscScalar)i;
144: PetscCall(VecRestoreArray(x, &xx));
145: }
147: PetscCall(VecGetLocalSize(x, &n));
148: PetscCall(VecGetLocalSize(y, &p));
149: 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);
150: 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);
151: 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);
153: if (pf->ops->applyvec) PetscCallBack("PF callback apply to vector", (*pf->ops->applyvec)(pf->data, x, y));
154: else {
155: const PetscScalar *xx;
156: PetscScalar *yy;
158: PetscCall(VecGetLocalSize(x, &n));
159: n = n / pf->dimin;
160: PetscCall(VecGetArrayRead(x, &xx));
161: PetscCall(VecGetArray(y, &yy));
162: PetscCallBack("PF callback apply to array", (*pf->ops->apply)(pf->data, n, xx, yy));
163: PetscCall(VecRestoreArrayRead(x, &xx));
164: PetscCall(VecRestoreArray(y, &yy));
165: }
166: if (nox) PetscCall(VecDestroy(&x));
167: PetscFunctionReturn(PETSC_SUCCESS);
168: }
170: /*@
171: PFApply - Applies the mathematical function to an array of values.
173: Collective
175: Input Parameters:
176: + pf - the function context
177: . n - number of pointwise function evaluations to perform, each pointwise function evaluation
178: is a function of dimin variables and computes dimout variables where dimin and dimout are defined
179: in the call to `PFCreate()`
180: - x - input array
182: Output Parameter:
183: . y - output array
185: Level: beginner
187: .seealso: `PF`, `PFApplyVec()`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFSet()`
188: @*/
189: PetscErrorCode PFApply(PF pf, PetscInt n, const PetscScalar *x, PetscScalar *y)
190: {
191: PetscFunctionBegin;
193: PetscAssertPointer(x, 3);
194: PetscAssertPointer(y, 4);
195: PetscCheck(x != y, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "x and y must be different arrays");
197: PetscCallBack("PF callback apply", (*pf->ops->apply)(pf->data, n, x, y));
198: PetscFunctionReturn(PETSC_SUCCESS);
199: }
201: /*@
202: PFViewFromOptions - View a `PF` based on options set in the options database
204: Collective
206: Input Parameters:
207: + A - the `PF` context
208: . obj - optional object that provides the prefix used to search the options database, pass `NULL` to use the options prefix of `A`
209: - name - command line option
211: Options Database Key:
212: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`
214: Level: intermediate
216: Note:
217: This checks the options database, creates the viewer on-the-fly, uses it and then destroys it. Hence it should not be called in heavily used routines,
218: rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.
220: .seealso: `PF`, `PFView()`, `PetscObjectViewFromOptions()`, `PFCreate()`, `PetscOptionsCreateViewer()`
221: @*/
222: PetscErrorCode PFViewFromOptions(PF A, PetscObject obj, const char name[])
223: {
224: PetscFunctionBegin;
226: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
227: PetscFunctionReturn(PETSC_SUCCESS);
228: }
230: /*@
231: PFView - Prints information about a mathematical function
233: Collective unless `viewer` is `PETSC_VIEWER_STDOUT_SELF`
235: Input Parameters:
236: + pf - the `PF` context
237: - viewer - optional visualization context
239: Level: developer
241: Note:
242: The available visualization contexts include
243: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
244: - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
245: output where only the first processor opens
246: the file. All other processors send their
247: data to the first processor to print.
249: The user can open an alternative visualization contexts with
250: `PetscViewerASCIIOpen()` (output to a specified file).
252: .seealso: `PF`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`
253: @*/
254: PetscErrorCode PFView(PF pf, PetscViewer viewer)
255: {
256: PetscBool isascii;
257: PetscViewerFormat format;
259: PetscFunctionBegin;
261: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf), &viewer));
263: PetscCheckSameComm(pf, 1, viewer, 2);
265: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
266: if (isascii) {
267: PetscCall(PetscViewerGetFormat(viewer, &format));
268: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pf, viewer));
269: if (pf->ops->view) {
270: PetscCall(PetscViewerASCIIPushTab(viewer));
271: PetscCallBack("PF callback view", (*pf->ops->view)(pf->data, viewer));
272: PetscCall(PetscViewerASCIIPopTab(viewer));
273: }
274: }
275: PetscFunctionReturn(PETSC_SUCCESS);
276: }
278: /*@
279: PFRegister - Adds a method to the mathematical function package.
281: Not Collective
283: Input Parameters:
284: + sname - name of a new user-defined solver
285: - function - routine to create method context
287: Example Usage:
288: .vb
289: PFRegister("my_function", MyFunctionSetCreate);
290: .ve
292: Then, your solver can be chosen with the procedural interface via
293: .vb
294: PFSetType(pf, "my_function")
295: .ve
296: or at runtime via the option
297: .vb
298: -pf_type my_function
299: .ve
301: Level: advanced
303: Note:
304: `PFRegister()` may be called multiple times to add several user-defined functions
306: .seealso: `PF`, `PFRegisterAll()`, `PFRegisterDestroy()`
307: @*/
308: PetscErrorCode PFRegister(const char sname[], PetscErrorCode (*function)(PF, PetscCtx))
309: {
310: PetscFunctionBegin;
311: PetscCall(PFInitializePackage());
312: PetscCall(PetscFunctionListAdd(&PFList, sname, function));
313: PetscFunctionReturn(PETSC_SUCCESS);
314: }
316: /*@
317: PFGetType - Gets the `PFType` name (as a string) from the `PF`
318: context.
320: Not Collective
322: Input Parameter:
323: . pf - the function context
325: Output Parameter:
326: . type - name of function
328: Level: intermediate
330: Note:
331: `type` should not be retained for later use as it will be an invalid pointer if the `PFType` of `pf` is changed.
333: .seealso: `PF`, `PFSetType()`, `PFType`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`
334: @*/
335: PetscErrorCode PFGetType(PF pf, PFType *type)
336: {
337: PetscFunctionBegin;
339: PetscAssertPointer(type, 2);
340: *type = ((PetscObject)pf)->type_name;
341: PetscFunctionReturn(PETSC_SUCCESS);
342: }
344: /*@
345: PFSetType - Builds `PF` for a particular function
347: Collective
349: Input Parameters:
350: + pf - the function context.
351: . type - a known type, see `PFType` for available methods (for instance, `PFCONSTANT`)
352: - ctx - optional type dependent context
354: Options Database Key:
355: . -pf_type (constant|mat|string|quick|identity|matlab) - Set the `PFType`
357: Level: intermediate
359: .seealso: `PF`, `PFSet()`, `PFRegister()`, `PFCreate()`, `DMDACreatePF()`, `PFType`, `PFGetType()`
360: @*/
361: PetscErrorCode PFSetType(PF pf, PFType type, PetscCtx ctx)
362: {
363: PetscBool match;
364: PetscErrorCode (*r)(PF, PetscCtx);
366: PetscFunctionBegin;
368: PetscAssertPointer(type, 2);
370: PetscCall(PetscObjectTypeCompare((PetscObject)pf, type, &match));
371: if (match) PetscFunctionReturn(PETSC_SUCCESS);
373: PetscTryTypeMethod(pf, destroy);
374: pf->data = NULL;
376: /* Determine the PFCreateXXX routine for a particular function */
377: PetscCall(PetscFunctionListFind(PFList, type, &r));
378: PetscCheck(r, PetscObjectComm((PetscObject)pf), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PF type %s", type);
379: pf->ops->destroy = NULL;
380: pf->ops->view = NULL;
381: pf->ops->apply = NULL;
382: pf->ops->applyvec = NULL;
384: /* Call the PFCreateXXX routine for this particular function */
385: PetscCall((*r)(pf, ctx));
387: PetscCall(PetscObjectChangeTypeName((PetscObject)pf, type));
388: PetscFunctionReturn(PETSC_SUCCESS);
389: }
391: /*@
392: PFSetFromOptions - Sets `PF` options from the options database.
394: Collective
396: Input Parameters:
397: . pf - the mathematical function context
399: Level: intermediate
401: Notes:
402: To see all options, run your program with the -help option
403: or consult the users manual.
405: .seealso: `PF`
406: @*/
407: PetscErrorCode PFSetFromOptions(PF pf)
408: {
409: char type[256];
410: PetscBool flg;
412: PetscFunctionBegin;
415: PetscObjectOptionsBegin((PetscObject)pf);
416: PetscCall(PetscOptionsFList("-pf_type", "Type of function", "PFSetType", PFList, NULL, type, sizeof(type), &flg));
417: if (flg) PetscCall(PFSetType(pf, type, NULL));
418: PetscTryTypeMethod(pf, setfromoptions, PetscOptionsObject);
420: /* process any options handlers added with PetscObjectAddOptionsHandler() */
421: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pf, PetscOptionsObject));
422: PetscOptionsEnd();
423: PetscFunctionReturn(PETSC_SUCCESS);
424: }
426: static PetscBool PFPackageInitialized = PETSC_FALSE;
428: /*@
429: PFFinalizePackage - This function destroys everything in the PETSc `PF` package. It is
430: called from `PetscFinalize()`.
432: Level: developer
434: .seealso: `PF`, `PetscFinalize()`
435: @*/
436: PetscErrorCode PFFinalizePackage(void)
437: {
438: PetscFunctionBegin;
439: PetscCall(PetscFunctionListDestroy(&PFList));
440: PFPackageInitialized = PETSC_FALSE;
441: PFRegisterAllCalled = PETSC_FALSE;
442: PetscFunctionReturn(PETSC_SUCCESS);
443: }
445: /*@
446: PFInitializePackage - This function initializes everything in the `PF` package. It is called
447: from PetscDLLibraryRegister_petscvec() when using dynamic libraries, and on the first call to `PFCreate()`
448: when using shared or static libraries.
450: Level: developer
452: .seealso: `PF`, `PetscInitialize()`
453: @*/
454: PetscErrorCode PFInitializePackage(void)
455: {
456: char logList[256];
457: PetscBool opt, pkg;
459: PetscFunctionBegin;
460: if (PFPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
461: PFPackageInitialized = PETSC_TRUE;
462: /* Register Classes */
463: PetscCall(PetscClassIdRegister("PointFunction", &PF_CLASSID));
464: /* Register Constructors */
465: PetscCall(PFRegisterAll());
466: /* Process Info */
467: {
468: PetscClassId classids[1];
470: classids[0] = PF_CLASSID;
471: PetscCall(PetscInfoProcessClass("pf", 1, classids));
472: }
473: /* Process summary exclusions */
474: PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt));
475: if (opt) {
476: PetscCall(PetscStrInList("pf", logList, ',', &pkg));
477: if (pkg) PetscCall(PetscLogEventExcludeClass(PF_CLASSID));
478: }
479: /* Register package finalizer */
480: PetscCall(PetscRegisterFinalize(PFFinalizePackage));
481: PetscFunctionReturn(PETSC_SUCCESS);
482: }
484: /*@
485: PFSetOptionsPrefix - Sets the prefix used for searching for all
486: `PF` options in the database.
488: Logically Collective
490: Input Parameters:
491: + pf - the `PF` context
492: - prefix - the prefix string to prepend to all `PF` option requests
494: Level: advanced
496: Note:
497: A hyphen (-) must NOT be given at the beginning of the prefix name.
498: The first character of all runtime options is AUTOMATICALLY the
499: hyphen.
501: .seealso: [](ch_ksp), `PF`, `PFSetFromOptions()`, `PFAppendOptionsPrefix()`, `PFGetOptionsPrefix()`
502: @*/
503: PetscErrorCode PFSetOptionsPrefix(PF pf, const char prefix[])
504: {
505: PetscFunctionBegin;
507: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)pf, prefix));
508: PetscFunctionReturn(PETSC_SUCCESS);
509: }
511: /*@
512: PFAppendOptionsPrefix - Appends to the prefix used for searching for all
513: `PF` options in the database.
515: Logically Collective
517: Input Parameters:
518: + pf - the `PF`
519: - prefix - the prefix string to prepend to all `PF` option requests
521: Level: advanced
523: Note:
524: A hyphen (-) must NOT be given at the beginning of the prefix name.
525: The first character of all runtime options is AUTOMATICALLY the
526: hyphen.
528: .seealso: [](ch_ksp), `PF`, `PFSetFromOptions()`, `PFSetOptionsPrefix()`, `PFGetOptionsPrefix()`
529: @*/
530: PetscErrorCode PFAppendOptionsPrefix(PF pf, const char prefix[])
531: {
532: PetscFunctionBegin;
534: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)pf, prefix));
535: PetscFunctionReturn(PETSC_SUCCESS);
536: }
538: /*@
539: PFGetOptionsPrefix - Gets the prefix used for searching for all
540: `PF` options in the database.
542: Not Collective
544: Input Parameter:
545: . pf - the `PF`
547: Output Parameter:
548: . prefix - pointer to the prefix string used, is returned
550: Level: advanced
552: .seealso: [](ch_ksp), `PF`, `PFSetFromOptions()`, `PFSetOptionsPrefix()`, `PFAppendOptionsPrefix()`
553: @*/
554: PetscErrorCode PFGetOptionsPrefix(PF pf, const char *prefix[])
555: {
556: PetscFunctionBegin;
558: PetscAssertPointer(prefix, 2);
559: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pf, prefix));
560: PetscFunctionReturn(PETSC_SUCCESS);
561: }