xref: /petsc/src/vec/pf/impls/string/cstring.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
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));
16*3ba16761SJacob 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));
23*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24292f8084SBarry Smith }
25292f8084SBarry Smith 
26292f8084SBarry Smith /*
27292f8084SBarry Smith     PFStringCreateFunction - Creates a function from a string
28292f8084SBarry Smith 
29292f8084SBarry Smith    Collective over PF
30292f8084SBarry Smith 
31292f8084SBarry Smith   Input Parameters:
32292f8084SBarry Smith +    pf - the function object
33292f8084SBarry Smith -    string - the string that defines the function
34292f8084SBarry Smith 
35292f8084SBarry Smith   Output Parameter:
36292f8084SBarry Smith .    f - the function pointer.
37292f8084SBarry Smith 
38db781477SPatrick Sanan .seealso: `PFSetFromOptions()`
39292f8084SBarry Smith 
40292f8084SBarry Smith */
41d71ae5a4SJacob Faibussowitsch PetscErrorCode PFStringCreateFunction(PF pf, char *string, void **f)
42d71ae5a4SJacob Faibussowitsch {
430598bfebSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
44a364092eSJacob Faibussowitsch   char      task[1024], tmp[PETSC_MAX_PATH_LEN], lib[PETSC_MAX_PATH_LEN], username[64];
45292f8084SBarry Smith   FILE     *fd;
46ace3abfcSBarry Smith   PetscBool tmpshared, wdshared, keeptmpfiles = PETSC_FALSE;
47292f8084SBarry Smith   MPI_Comm  comm;
48292f8084SBarry Smith #endif
49292f8084SBarry Smith 
50292f8084SBarry Smith   PetscFunctionBegin;
510598bfebSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
529566063dSJacob Faibussowitsch   PetscCall(PetscFree(pf->data));
539566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(string, (char **)&pf->data));
54292f8084SBarry Smith 
55292f8084SBarry Smith   /* create the new C function and compile it */
569566063dSJacob Faibussowitsch   PetscCall(PetscSharedTmp(PetscObjectComm((PetscObject)pf), &tmpshared));
579566063dSJacob Faibussowitsch   PetscCall(PetscSharedWorkingDirectory(PetscObjectComm((PetscObject)pf), &wdshared));
58292f8084SBarry Smith   if (tmpshared) { /* do it in /tmp since everyone has one */
59a364092eSJacob Faibussowitsch     PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf), tmp, PETSC_STATIC_ARRAY_LENGTH(tmp)));
609566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)pf, &comm));
61292f8084SBarry Smith   } else if (!wdshared) { /* each one does in private /tmp */
62a364092eSJacob Faibussowitsch     PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf), tmp, PETSC_STATIC_ARRAY_LENGTH(tmp)));
63292f8084SBarry Smith     comm = PETSC_COMM_SELF;
64292f8084SBarry Smith   } else { /* do it in current directory */
659566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(tmp, "."));
669566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)pf, &comm));
67292f8084SBarry Smith   }
689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)pf)->options, ((PetscObject)pf)->prefix, "-pf_string_keep_files", &keeptmpfiles, NULL));
69a364092eSJacob Faibussowitsch   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" : ""));
70f6e5521dSKarl Rupp 
717cfd0b05SBarry Smith   #if defined(PETSC_HAVE_POPEN)
729566063dSJacob Faibussowitsch   PetscCall(PetscPOpen(comm, NULL, task, "r", &fd));
739566063dSJacob Faibussowitsch   PetscCall(PetscPClose(comm, fd));
747cfd0b05SBarry Smith   #else
75e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
767cfd0b05SBarry Smith   #endif
77292f8084SBarry Smith 
789566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Barrier(comm));
79292f8084SBarry Smith 
80292f8084SBarry Smith   /* load the apply function from the dynamic library */
81a364092eSJacob Faibussowitsch   PetscCall(PetscGetUserName(username, PETSC_STATIC_ARRAY_LENGTH(username)));
82a364092eSJacob Faibussowitsch   PetscCall(PetscSNPrintf(lib, PETSC_STATIC_ARRAY_LENGTH(lib), "%s/%s/libpetscdlib", tmp, username));
839566063dSJacob Faibussowitsch   PetscCall(PetscDLLibrarySym(comm, NULL, lib, "PFApply_String", f));
8428b400f6SJacob Faibussowitsch   PetscCheck(f, PetscObjectComm((PetscObject)pf), PETSC_ERR_ARG_WRONGSTATE, "Cannot find function %s", lib);
85292f8084SBarry Smith #endif
86*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
87292f8084SBarry Smith }
88292f8084SBarry Smith 
89d71ae5a4SJacob Faibussowitsch static PetscErrorCode PFSetFromOptions_String(PF pf, PetscOptionItems *PetscOptionsObject)
90d71ae5a4SJacob Faibussowitsch {
91ace3abfcSBarry Smith   PetscBool flag;
92292f8084SBarry Smith   char      value[PETSC_MAX_PATH_LEN];
934c8fdceaSLisandro Dalcin   PetscErrorCode (*f)(void *, PetscInt, const PetscScalar *, PetscScalar *) = NULL;
94292f8084SBarry Smith 
95292f8084SBarry Smith   PetscFunctionBegin;
96d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "String function options");
979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-pf_string", "Enter the function", "PFStringCreateFunction", "", value, sizeof(value), &flag));
98292f8084SBarry Smith   if (flag) {
999566063dSJacob Faibussowitsch     PetscCall(PFStringCreateFunction(pf, value, (void **)&f));
100292f8084SBarry Smith     pf->ops->apply = f;
101292f8084SBarry Smith   }
102d0609cedSBarry Smith   PetscOptionsHeadEnd();
103*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
104292f8084SBarry Smith }
105292f8084SBarry Smith 
10626e7fa26SJed Brown typedef PetscErrorCode (*FCN)(void *, PetscInt, const PetscScalar *, PetscScalar *); /* force argument to next function to not be extern C*/
1076ac5842eSBarry Smith 
108d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PFCreate_String(PF pf, void *value)
109d71ae5a4SJacob Faibussowitsch {
1104c8fdceaSLisandro Dalcin   FCN f = NULL;
111292f8084SBarry Smith 
112292f8084SBarry Smith   PetscFunctionBegin;
11348a46eb9SPierre Jolivet   if (value) PetscCall(PFStringCreateFunction(pf, (char *)value, (void **)&f));
1149566063dSJacob Faibussowitsch   PetscCall(PFSet(pf, f, NULL, PFView_String, PFDestroy_String, NULL));
115292f8084SBarry Smith   pf->ops->setfromoptions = PFSetFromOptions_String;
116*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
117292f8084SBarry Smith }
118