Actual source code: cstring.c
2: #include <../src/vec/pf/pfimpl.h>
4: /*
5: This PF generates a function on the fly and loads it into the running
6: program.
7: */
9: static PetscErrorCode PFView_String(void *value, PetscViewer viewer)
10: {
11: PetscBool iascii;
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: }
19: static PetscErrorCode PFDestroy_String(void *value)
20: {
21: PetscFunctionBegin;
22: PetscCall(PetscFree(value));
23: PetscFunctionReturn(PETSC_SUCCESS);
24: }
26: static PetscErrorCode PFSetFromOptions_String(PF pf, PetscOptionItems *PetscOptionsObject)
27: {
28: PetscBool flag;
29: char value[PETSC_MAX_PATH_LEN];
31: PetscFunctionBegin;
32: PetscOptionsHeadBegin(PetscOptionsObject, "String function options");
33: PetscCall(PetscOptionsString("-pf_string", "Enter the function", "PFStringCreateFunction", "", value, sizeof(value), &flag));
34: if (flag) PetscCall(PFStringSetFunction(pf, value));
35: PetscOptionsHeadEnd();
36: PetscFunctionReturn(PETSC_SUCCESS);
37: }
39: /*
40: PFStringSetFunction - Creates a function from a string
42: Collective
44: Input Parameters:
45: + pf - the function object
46: - string - the string that defines the function
48: Developer Notes:
49: Currently this can be used only ONCE in a running code. It needs to be fixed to generate a new library name for each new function added.
51: Requires `PETSC_HAVE_POPEN` `PETSC_USE_SHARED_LIBRARIES` `PETSC_HAVE_DYNAMIC_LIBRARIES` to use
53: .seealso: `PFSetFromOptions()`
54: */
55: PetscErrorCode PFStringSetFunction(PF pf, const char *string)
56: {
57: char task[1024], tmp[PETSC_MAX_PATH_LEN], lib[PETSC_MAX_PATH_LEN];
58: PetscBool tmpshared, wdshared, keeptmpfiles = PETSC_FALSE;
59: MPI_Comm comm;
60: FILE *fd;
61: char *data;
62: PetscErrorCode (*f)(void *, PetscInt, const PetscScalar *, PetscScalar *);
64: PetscFunctionBegin;
65: PetscCall(PetscObjectChangeTypeName((PetscObject)pf, PFSTRING));
66: /* create the new C function and compile it */
67: PetscCall(PetscSharedTmp(PetscObjectComm((PetscObject)pf), &tmpshared));
68: PetscCall(PetscSharedWorkingDirectory(PetscObjectComm((PetscObject)pf), &wdshared));
69: if (tmpshared) { /* do it in /tmp since everyone has one */
70: PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf), tmp, PETSC_STATIC_ARRAY_LENGTH(tmp)));
71: PetscCall(PetscObjectGetComm((PetscObject)pf, &comm));
72: } else if (!wdshared) { /* each one does in private /tmp */
73: PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf), tmp, PETSC_STATIC_ARRAY_LENGTH(tmp)));
74: comm = PETSC_COMM_SELF;
75: } else { /* do it in current directory */
76: PetscCall(PetscStrncpy(tmp, ".", sizeof(tmp)));
77: PetscCall(PetscObjectGetComm((PetscObject)pf, &comm));
78: }
79: PetscCall(PetscOptionsGetBool(((PetscObject)pf)->options, ((PetscObject)pf)->prefix, "-pf_string_keep_files", &keeptmpfiles, NULL));
80: 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" : ""));
82: PetscCall(PetscPOpen(comm, NULL, task, "r", &fd));
83: PetscCall(PetscPClose(comm, fd));
84: PetscCallMPI(MPI_Barrier(comm));
86: /* load the apply function from the dynamic library */
87: PetscCall(PetscSNPrintf(lib, PETSC_STATIC_ARRAY_LENGTH(lib), "%s/${USERNAME}/libpetscdlib", tmp));
88: PetscCall(PetscDLLibrarySym(comm, NULL, lib, "PFApply_String", (void **)&f));
89: PetscCheck(f, PetscObjectComm((PetscObject)pf), PETSC_ERR_ARG_WRONGSTATE, "Cannot find function %s", lib);
91: PetscCall(PetscFree(pf->data));
92: PetscCall(PetscStrallocpy(string, (char **)&data));
93: PetscCall(PFSet(pf, f, NULL, PFView_String, PFDestroy_String, data));
94: pf->ops->setfromoptions = PFSetFromOptions_String;
95: PetscFunctionReturn(PETSC_SUCCESS);
96: }
98: PETSC_EXTERN PetscErrorCode PFCreate_String(PF pf, void *value)
99: {
100: PetscFunctionBegin;
101: PetscCall(PFStringSetFunction(pf, (const char *)value));
102: PetscFunctionReturn(PETSC_SUCCESS);
103: }