1 #include <../src/vec/pf/pfimpl.h> /*I "petscpf.h" I*/
2
3 /*
4 This PF generates a function on the fly and loads it into the running
5 program.
6 */
7
PFView_String(void * value,PetscViewer viewer)8 static PetscErrorCode PFView_String(void *value, PetscViewer viewer)
9 {
10 PetscBool isascii;
11
12 PetscFunctionBegin;
13 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
14 if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "String = %s\n", (char *)value));
15 PetscFunctionReturn(PETSC_SUCCESS);
16 }
17
PFDestroy_String(void * value)18 static PetscErrorCode PFDestroy_String(void *value)
19 {
20 PetscFunctionBegin;
21 PetscCall(PetscFree(value));
22 PetscFunctionReturn(PETSC_SUCCESS);
23 }
24
PFSetFromOptions_String(PF pf,PetscOptionItems PetscOptionsObject)25 static PetscErrorCode PFSetFromOptions_String(PF pf, PetscOptionItems PetscOptionsObject)
26 {
27 PetscBool flag;
28 char value[PETSC_MAX_PATH_LEN];
29
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 }
37
38 /*@C
39 PFStringSetFunction - Creates a function from a string
40
41 Collective
42
43 Input Parameters:
44 + pf - the function object
45 - string - the string that defines the function
46
47 Level: intermediate
48
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.
52
53 Requires `PETSC_HAVE_POPEN` `PETSC_USE_SHARED_LIBRARIES` `PETSC_HAVE_DYNAMIC_LIBRARIES` to use
54
55 .seealso: `PFSetFromOptions()`
56 @*/
PFStringSetFunction(PF pf,const char string[])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 *);
65
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" : ""));
83
84 PetscCall(PetscPOpen(comm, NULL, task, "r", &fd));
85 PetscCall(PetscPClose(comm, fd));
86 PetscCallMPI(MPI_Barrier(comm));
87
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);
92
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 }
99
PFCreate_String(PF pf,void * value)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 }
106