Actual source code: cstring.c
1: #include <../src/vec/pf/pfimpl.h>
3: /*
4: This PF generates a function on the fly and loads it into the running
5: program.
6: */
8: static PetscErrorCode PFView_String(void *value, PetscViewer viewer)
9: {
10: PetscBool iascii;
12: PetscFunctionBegin;
13: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
14: if (iascii) PetscCall(PetscViewerASCIIPrintf(viewer, "String = %s\n", (char *)value));
15: PetscFunctionReturn(PETSC_SUCCESS);
16: }
18: static PetscErrorCode PFDestroy_String(void *value)
19: {
20: PetscFunctionBegin;
21: PetscCall(PetscFree(value));
22: PetscFunctionReturn(PETSC_SUCCESS);
23: }
25: static PetscErrorCode PFSetFromOptions_String(PF pf, PetscOptionItems *PetscOptionsObject)
26: {
27: PetscBool flag;
28: char value[PETSC_MAX_PATH_LEN];
30: PetscFunctionBegin;
31: PetscOptionsHeadBegin(PetscOptionsObject, "String function options");
32: PetscCall(PetscOptionsString("-pf_string", "Enter the function", "PFStringCreateFunction", "", value, sizeof(value), &flag));
33: if (flag) PetscCall(PFStringSetFunction(pf, value));
34: PetscOptionsHeadEnd();
35: PetscFunctionReturn(PETSC_SUCCESS);
36: }
38: /*@C
39: PFStringSetFunction - Creates a function from a string
41: Collective
43: Input Parameters:
44: + pf - the function object
45: - string - the string that defines the function
47: Level: intermediate
49: Developer Notes:
50: Currently this can be used only ONCE in a running code. It needs to be fixed to generate a
51: new library name for each new function added.
53: Requires `PETSC_HAVE_POPEN` `PETSC_USE_SHARED_LIBRARIES` `PETSC_HAVE_DYNAMIC_LIBRARIES` to use
55: .seealso: `PFSetFromOptions()`
56: @*/
57: PetscErrorCode PFStringSetFunction(PF pf, const char string[])
58: {
59: char task[1024], tmp[PETSC_MAX_PATH_LEN], lib[PETSC_MAX_PATH_LEN];
60: PetscBool tmpshared, wdshared, keeptmpfiles = PETSC_FALSE;
61: MPI_Comm comm;
62: FILE *fd;
63: char *data;
64: PetscErrorCode (*f)(void *, PetscInt, const PetscScalar *, PetscScalar *);
66: PetscFunctionBegin;
67: PetscCall(PetscObjectChangeTypeName((PetscObject)pf, PFSTRING));
68: /* create the new C function and compile it */
69: PetscCall(PetscSharedTmp(PetscObjectComm((PetscObject)pf), &tmpshared));
70: PetscCall(PetscSharedWorkingDirectory(PetscObjectComm((PetscObject)pf), &wdshared));
71: if (tmpshared) { /* do it in /tmp since everyone has one */
72: PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf), tmp, PETSC_STATIC_ARRAY_LENGTH(tmp)));
73: PetscCall(PetscObjectGetComm((PetscObject)pf, &comm));
74: } else if (!wdshared) { /* each one does in private /tmp */
75: PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf), tmp, PETSC_STATIC_ARRAY_LENGTH(tmp)));
76: comm = PETSC_COMM_SELF;
77: } else { /* do it in current directory */
78: PetscCall(PetscStrncpy(tmp, ".", sizeof(tmp)));
79: PetscCall(PetscObjectGetComm((PetscObject)pf, &comm));
80: }
81: PetscCall(PetscOptionsGetBool(((PetscObject)pf)->options, ((PetscObject)pf)->prefix, "-pf_string_keep_files", &keeptmpfiles, NULL));
82: PetscCall(PetscSNPrintf(task, PETSC_STATIC_ARRAY_LENGTH(task), "cd %s ; if [ ! -d ${USERNAME} ]; then mkdir ${USERNAME}; fi ; cd ${USERNAME} ; rm -f makefile petscdlib.* ; cp -f ${PETSC_DIR}/src/vec/pf/impls/string/makefile ./makefile ; ${PETSC_MAKE} NIN=%" PetscInt_FMT " NOUT=%" PetscInt_FMT " -f makefile libpetscdlib STRINGFUNCTION=\"%s\" %s ; sync\n", tmp, pf->dimin, pf->dimout, string, !keeptmpfiles ? "; rm -f makefile petscdlib.c" : ""));
84: PetscCall(PetscPOpen(comm, NULL, task, "r", &fd));
85: PetscCall(PetscPClose(comm, fd));
86: PetscCallMPI(MPI_Barrier(comm));
88: /* load the apply function from the dynamic library */
89: PetscCall(PetscSNPrintf(lib, PETSC_STATIC_ARRAY_LENGTH(lib), "%s/${USERNAME}/libpetscdlib", tmp));
90: PetscCall(PetscDLLibrarySym(comm, NULL, lib, "PFApply_String", (void **)&f));
91: PetscCheck(f, PetscObjectComm((PetscObject)pf), PETSC_ERR_ARG_WRONGSTATE, "Cannot find function %s", lib);
93: PetscCall(PetscFree(pf->data));
94: PetscCall(PetscStrallocpy(string, &data));
95: PetscCall(PFSet(pf, f, NULL, PFView_String, PFDestroy_String, data));
96: pf->ops->setfromoptions = PFSetFromOptions_String;
97: PetscFunctionReturn(PETSC_SUCCESS);
98: }
100: PETSC_INTERN PetscErrorCode PFCreate_String(PF pf, void *value)
101: {
102: PetscFunctionBegin;
103: PetscCall(PFStringSetFunction(pf, (const char *)value));
104: PetscFunctionReturn(PETSC_SUCCESS);
105: }