xref: /petsc/src/vec/pf/impls/string/cstring.c (revision 74df5e01f481fb3fe90b32c3b4345ef0122eb3ce)
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 
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 
18 static PetscErrorCode PFDestroy_String(void *value)
19 {
20   PetscFunctionBegin;
21   PetscCall(PetscFree(value));
22   PetscFunctionReturn(PETSC_SUCCESS);
23 }
24 
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 @*/
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 
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