xref: /petsc/src/vec/pf/impls/string/cstring.c (revision 9e4239418eed872949d7fcdc17a391fb6566eaa9)
1 
2 #include <../src/vec/pf/pfimpl.h> /*I "petscpf.h" I*/
3 
4 /*
5         This PF generates a function on the fly and loads it into the running
6    program.
7 */
8 
9 static PetscErrorCode PFView_String(void *value, PetscViewer viewer)
10 {
11   PetscBool iascii;
12 
13   PetscFunctionBegin;
14   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
15   if (iascii) PetscCall(PetscViewerASCIIPrintf(viewer, "String = %s\n", (char *)value));
16   PetscFunctionReturn(PETSC_SUCCESS);
17 }
18 
19 static PetscErrorCode PFDestroy_String(void *value)
20 {
21   PetscFunctionBegin;
22   PetscCall(PetscFree(value));
23   PetscFunctionReturn(PETSC_SUCCESS);
24 }
25 
26 /*
27     PFStringCreateFunction - Creates a function from a string
28 
29    Collective over PF
30 
31   Input Parameters:
32 +    pf - the function object
33 -    string - the string that defines the function
34 
35   Output Parameter:
36 .    f - the function pointer.
37 
38 .seealso: `PFSetFromOptions()`
39 
40 */
41 PetscErrorCode PFStringCreateFunction(PF pf, char *string, void **f)
42 {
43 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
44   char      task[1024], tmp[PETSC_MAX_PATH_LEN], lib[PETSC_MAX_PATH_LEN], username[64];
45   FILE     *fd;
46   PetscBool tmpshared, wdshared, keeptmpfiles = PETSC_FALSE;
47   MPI_Comm  comm;
48 #endif
49 
50   PetscFunctionBegin;
51 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
52   PetscCall(PetscFree(pf->data));
53   PetscCall(PetscStrallocpy(string, (char **)&pf->data));
54 
55   /* create the new C function and compile it */
56   PetscCall(PetscSharedTmp(PetscObjectComm((PetscObject)pf), &tmpshared));
57   PetscCall(PetscSharedWorkingDirectory(PetscObjectComm((PetscObject)pf), &wdshared));
58   if (tmpshared) { /* do it in /tmp since everyone has one */
59     PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf), tmp, PETSC_STATIC_ARRAY_LENGTH(tmp)));
60     PetscCall(PetscObjectGetComm((PetscObject)pf, &comm));
61   } else if (!wdshared) { /* each one does in private /tmp */
62     PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf), tmp, PETSC_STATIC_ARRAY_LENGTH(tmp)));
63     comm = PETSC_COMM_SELF;
64   } else { /* do it in current directory */
65     PetscCall(PetscStrncpy(tmp, ".", sizeof(tmp)));
66     PetscCall(PetscObjectGetComm((PetscObject)pf, &comm));
67   }
68   PetscCall(PetscOptionsGetBool(((PetscObject)pf)->options, ((PetscObject)pf)->prefix, "-pf_string_keep_files", &keeptmpfiles, NULL));
69   PetscCall(PetscSNPrintf(task, PETSC_STATIC_ARRAY_LENGTH(task), "cd %s ; mkdir ${USERNAME} ; cd ${USERNAME} ; \\cp -f ${PETSC_DIR}/src/pf/impls/string/makefile ./makefile ; make  MIN=%" PetscInt_FMT " NOUT=%" PetscInt_FMT " -f makefile petscdlib STRINGFUNCTION=\"%s\" ; %s ;  sync\n", tmp, pf->dimin, pf->dimout, string, keeptmpfiles ? "\\rm -f makefile petscdlib.c libpetscdlib.a" : ""));
70 
71   #if defined(PETSC_HAVE_POPEN)
72   PetscCall(PetscPOpen(comm, NULL, task, "r", &fd));
73   PetscCall(PetscPClose(comm, fd));
74   #else
75   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
76   #endif
77 
78   PetscCallMPI(MPI_Barrier(comm));
79 
80   /* load the apply function from the dynamic library */
81   PetscCall(PetscGetUserName(username, PETSC_STATIC_ARRAY_LENGTH(username)));
82   PetscCall(PetscSNPrintf(lib, PETSC_STATIC_ARRAY_LENGTH(lib), "%s/%s/libpetscdlib", tmp, username));
83   PetscCall(PetscDLLibrarySym(comm, NULL, lib, "PFApply_String", f));
84   PetscCheck(f, PetscObjectComm((PetscObject)pf), PETSC_ERR_ARG_WRONGSTATE, "Cannot find function %s", lib);
85 #endif
86   PetscFunctionReturn(PETSC_SUCCESS);
87 }
88 
89 static PetscErrorCode PFSetFromOptions_String(PF pf, PetscOptionItems *PetscOptionsObject)
90 {
91   PetscBool flag;
92   char      value[PETSC_MAX_PATH_LEN];
93   PetscErrorCode (*f)(void *, PetscInt, const PetscScalar *, PetscScalar *) = NULL;
94 
95   PetscFunctionBegin;
96   PetscOptionsHeadBegin(PetscOptionsObject, "String function options");
97   PetscCall(PetscOptionsString("-pf_string", "Enter the function", "PFStringCreateFunction", "", value, sizeof(value), &flag));
98   if (flag) {
99     PetscCall(PFStringCreateFunction(pf, value, (void **)&f));
100     pf->ops->apply = f;
101   }
102   PetscOptionsHeadEnd();
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 typedef PetscErrorCode (*FCN)(void *, PetscInt, const PetscScalar *, PetscScalar *); /* force argument to next function to not be extern C*/
107 
108 PETSC_EXTERN PetscErrorCode PFCreate_String(PF pf, void *value)
109 {
110   FCN f = NULL;
111 
112   PetscFunctionBegin;
113   if (value) PetscCall(PFStringCreateFunction(pf, (char *)value, (void **)&f));
114   PetscCall(PFSet(pf, f, NULL, PFView_String, PFDestroy_String, NULL));
115   pf->ops->setfromoptions = PFSetFromOptions_String;
116   PetscFunctionReturn(PETSC_SUCCESS);
117 }
118