xref: /petsc/src/vec/pf/impls/string/cstring.c (revision da8c939b118068a1ceac5e4b3ba271c87cfc5bc7)
1292f8084SBarry Smith 
2c6db04a5SJed Brown #include <../src/vec/pf/pfimpl.h> /*I "petscpf.h" I*/
3292f8084SBarry Smith 
4292f8084SBarry Smith /*
5a5b23f4aSJose E. Roman         This PF generates a function on the fly and loads it into the running
6292f8084SBarry Smith    program.
7292f8084SBarry Smith */
8292f8084SBarry Smith 
9d71ae5a4SJacob Faibussowitsch static PetscErrorCode PFView_String(void *value, PetscViewer viewer)
10d71ae5a4SJacob Faibussowitsch {
11ace3abfcSBarry Smith   PetscBool iascii;
12292f8084SBarry Smith 
13292f8084SBarry Smith   PetscFunctionBegin;
149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1548a46eb9SPierre Jolivet   if (iascii) PetscCall(PetscViewerASCIIPrintf(viewer, "String = %s\n", (char *)value));
163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17292f8084SBarry Smith }
18292f8084SBarry Smith 
19d71ae5a4SJacob Faibussowitsch static PetscErrorCode PFDestroy_String(void *value)
20d71ae5a4SJacob Faibussowitsch {
21292f8084SBarry Smith   PetscFunctionBegin;
229566063dSJacob Faibussowitsch   PetscCall(PetscFree(value));
233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24292f8084SBarry Smith }
25292f8084SBarry Smith 
26f236b2adSBarry Smith static PetscErrorCode PFSetFromOptions_String(PF pf, PetscOptionItems *PetscOptionsObject)
27f236b2adSBarry Smith {
28f236b2adSBarry Smith   PetscBool flag;
29f236b2adSBarry Smith   char      value[PETSC_MAX_PATH_LEN];
30292f8084SBarry Smith 
31f236b2adSBarry Smith   PetscFunctionBegin;
32f236b2adSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "String function options");
33f236b2adSBarry Smith   PetscCall(PetscOptionsString("-pf_string", "Enter the function", "PFStringCreateFunction", "", value, sizeof(value), &flag));
34f236b2adSBarry Smith   if (flag) PetscCall(PFStringSetFunction(pf, value));
35f236b2adSBarry Smith   PetscOptionsHeadEnd();
36f236b2adSBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
37f236b2adSBarry Smith }
38f236b2adSBarry Smith 
3938b5cf2dSJacob Faibussowitsch /*@C
40f236b2adSBarry Smith   PFStringSetFunction - Creates a function from a string
41f236b2adSBarry Smith 
42f236b2adSBarry Smith   Collective
43292f8084SBarry Smith 
44292f8084SBarry Smith   Input Parameters:
45292f8084SBarry Smith + pf     - the function object
46292f8084SBarry Smith - string - the string that defines the function
47292f8084SBarry Smith 
48e33f79d8SJacob Faibussowitsch   Level: intermediate
49e33f79d8SJacob Faibussowitsch 
50f236b2adSBarry Smith   Developer Notes:
51e33f79d8SJacob Faibussowitsch   Currently this can be used only ONCE in a running code. It needs to be fixed to generate a
52e33f79d8SJacob Faibussowitsch   new library name for each new function added.
53f236b2adSBarry Smith 
54f236b2adSBarry Smith   Requires `PETSC_HAVE_POPEN` `PETSC_USE_SHARED_LIBRARIES` `PETSC_HAVE_DYNAMIC_LIBRARIES` to use
55292f8084SBarry Smith 
56db781477SPatrick Sanan .seealso: `PFSetFromOptions()`
5738b5cf2dSJacob Faibussowitsch @*/
58f236b2adSBarry Smith PetscErrorCode PFStringSetFunction(PF pf, const char *string)
59d71ae5a4SJacob Faibussowitsch {
60f236b2adSBarry Smith   char      task[1024], tmp[PETSC_MAX_PATH_LEN], lib[PETSC_MAX_PATH_LEN];
61ace3abfcSBarry Smith   PetscBool tmpshared, wdshared, keeptmpfiles = PETSC_FALSE;
62292f8084SBarry Smith   MPI_Comm  comm;
63f236b2adSBarry Smith   FILE     *fd;
64f236b2adSBarry Smith   char     *data;
65f236b2adSBarry Smith   PetscErrorCode (*f)(void *, PetscInt, const PetscScalar *, PetscScalar *);
66292f8084SBarry Smith 
67292f8084SBarry Smith   PetscFunctionBegin;
68f236b2adSBarry Smith   PetscCall(PetscObjectChangeTypeName((PetscObject)pf, PFSTRING));
69292f8084SBarry Smith   /* create the new C function and compile it */
709566063dSJacob Faibussowitsch   PetscCall(PetscSharedTmp(PetscObjectComm((PetscObject)pf), &tmpshared));
719566063dSJacob Faibussowitsch   PetscCall(PetscSharedWorkingDirectory(PetscObjectComm((PetscObject)pf), &wdshared));
72292f8084SBarry Smith   if (tmpshared) { /* do it in /tmp since everyone has one */
73a364092eSJacob Faibussowitsch     PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf), tmp, PETSC_STATIC_ARRAY_LENGTH(tmp)));
749566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)pf, &comm));
75292f8084SBarry Smith   } else if (!wdshared) { /* each one does in private /tmp */
76a364092eSJacob Faibussowitsch     PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf), tmp, PETSC_STATIC_ARRAY_LENGTH(tmp)));
77292f8084SBarry Smith     comm = PETSC_COMM_SELF;
78292f8084SBarry Smith   } else { /* do it in current directory */
79c6a7a370SJeremy L Thompson     PetscCall(PetscStrncpy(tmp, ".", sizeof(tmp)));
809566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)pf, &comm));
81292f8084SBarry Smith   }
829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)pf)->options, ((PetscObject)pf)->prefix, "-pf_string_keep_files", &keeptmpfiles, NULL));
83f236b2adSBarry Smith   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" : ""));
84f6e5521dSKarl Rupp 
859566063dSJacob Faibussowitsch   PetscCall(PetscPOpen(comm, NULL, task, "r", &fd));
869566063dSJacob Faibussowitsch   PetscCall(PetscPClose(comm, fd));
879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Barrier(comm));
88292f8084SBarry Smith 
89292f8084SBarry Smith   /* load the apply function from the dynamic library */
90f236b2adSBarry Smith   PetscCall(PetscSNPrintf(lib, PETSC_STATIC_ARRAY_LENGTH(lib), "%s/${USERNAME}/libpetscdlib", tmp));
91f236b2adSBarry Smith   PetscCall(PetscDLLibrarySym(comm, NULL, lib, "PFApply_String", (void **)&f));
9228b400f6SJacob Faibussowitsch   PetscCheck(f, PetscObjectComm((PetscObject)pf), PETSC_ERR_ARG_WRONGSTATE, "Cannot find function %s", lib);
93f236b2adSBarry Smith 
94f236b2adSBarry Smith   PetscCall(PetscFree(pf->data));
95f236b2adSBarry Smith   PetscCall(PetscStrallocpy(string, (char **)&data));
96f236b2adSBarry Smith   PetscCall(PFSet(pf, f, NULL, PFView_String, PFDestroy_String, data));
97f236b2adSBarry Smith   pf->ops->setfromoptions = PFSetFromOptions_String;
983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99292f8084SBarry Smith }
100292f8084SBarry Smith 
101*da8c939bSJacob Faibussowitsch PETSC_INTERN PetscErrorCode PFCreate_String(PF pf, void *value)
102d71ae5a4SJacob Faibussowitsch {
103292f8084SBarry Smith   PetscFunctionBegin;
104f236b2adSBarry Smith   PetscCall(PFStringSetFunction(pf, (const char *)value));
1053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
106292f8084SBarry Smith }
107