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, (char **)&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: }