Actual source code: cstring.c

  1: #include <../src/vec/pf/pfimpl.h>

  3: /*
  4:         This PF generates a function on the fly and loads it into the running
  5:    program.
  6: */

  8: static PetscErrorCode PFView_String(void *value, PetscViewer viewer)
  9: {
 10:   PetscBool iascii;

 12:   PetscFunctionBegin;
 13:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
 14:   if (iascii) PetscCall(PetscViewerASCIIPrintf(viewer, "String = %s\n", (char *)value));
 15:   PetscFunctionReturn(PETSC_SUCCESS);
 16: }

 18: static PetscErrorCode PFDestroy_String(void *value)
 19: {
 20:   PetscFunctionBegin;
 21:   PetscCall(PetscFree(value));
 22:   PetscFunctionReturn(PETSC_SUCCESS);
 23: }

 25: static PetscErrorCode PFSetFromOptions_String(PF pf, PetscOptionItems *PetscOptionsObject)
 26: {
 27:   PetscBool flag;
 28:   char      value[PETSC_MAX_PATH_LEN];

 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: }

 38: /*@C
 39:   PFStringSetFunction - Creates a function from a string

 41:   Collective

 43:   Input Parameters:
 44: + pf     - the function object
 45: - string - the string that defines the function

 47:   Level: intermediate

 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.

 53:   Requires `PETSC_HAVE_POPEN` `PETSC_USE_SHARED_LIBRARIES` `PETSC_HAVE_DYNAMIC_LIBRARIES` to use

 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 *);

 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" : ""));

 84:   PetscCall(PetscPOpen(comm, NULL, task, "r", &fd));
 85:   PetscCall(PetscPClose(comm, fd));
 86:   PetscCallMPI(MPI_Barrier(comm));

 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);

 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: }

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: }