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