1 2 #include <../src/vec/pf/pfimpl.h> /*I "petscpf.h" I*/ 3 4 /* 5 This PF generates a function on the fly and loads it into the running 6 program. 7 */ 8 9 static PetscErrorCode PFView_String(void *value,PetscViewer viewer) 10 { 11 PetscBool iascii; 12 13 PetscFunctionBegin; 14 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 15 if (iascii) { 16 PetscCall(PetscViewerASCIIPrintf(viewer,"String = %s\n",(char*)value)); 17 } 18 PetscFunctionReturn(0); 19 } 20 21 static PetscErrorCode PFDestroy_String(void *value) 22 { 23 PetscFunctionBegin; 24 PetscCall(PetscFree(value)); 25 PetscFunctionReturn(0); 26 } 27 28 /* 29 PFStringCreateFunction - Creates a function from a string 30 31 Collective over PF 32 33 Input Parameters: 34 + pf - the function object 35 - string - the string that defines the function 36 37 Output Parameter: 38 . f - the function pointer. 39 40 .seealso: `PFSetFromOptions()` 41 42 */ 43 PetscErrorCode PFStringCreateFunction(PF pf,char *string,void **f) 44 { 45 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 46 char task[1024],tmp[256],lib[PETSC_MAX_PATH_LEN],username[64]; 47 FILE *fd; 48 PetscBool tmpshared,wdshared,keeptmpfiles = PETSC_FALSE; 49 MPI_Comm comm; 50 #endif 51 52 PetscFunctionBegin; 53 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 54 PetscCall(PetscFree(pf->data)); 55 PetscCall(PetscStrallocpy(string,(char**)&pf->data)); 56 57 /* create the new C function and compile it */ 58 PetscCall(PetscSharedTmp(PetscObjectComm((PetscObject)pf),&tmpshared)); 59 PetscCall(PetscSharedWorkingDirectory(PetscObjectComm((PetscObject)pf),&wdshared)); 60 if (tmpshared) { /* do it in /tmp since everyone has one */ 61 PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf),tmp,PETSC_MAX_PATH_LEN)); 62 PetscCall(PetscObjectGetComm((PetscObject)pf,&comm)); 63 } else if (!wdshared) { /* each one does in private /tmp */ 64 PetscCall(PetscGetTmp(PetscObjectComm((PetscObject)pf),tmp,PETSC_MAX_PATH_LEN)); 65 comm = PETSC_COMM_SELF; 66 } else { /* do it in current directory */ 67 PetscCall(PetscStrcpy(tmp,".")); 68 PetscCall(PetscObjectGetComm((PetscObject)pf,&comm)); 69 } 70 PetscCall(PetscOptionsGetBool(((PetscObject)pf)->options,((PetscObject)pf)->prefix,"-pf_string_keep_files",&keeptmpfiles,NULL)); 71 if (keeptmpfiles) sprintf(task,"cd %s ; mkdir ${USERNAME} ; cd ${USERNAME} ; \\cp -f ${PETSC_DIR}/src/pf/impls/string/makefile ./makefile ; ke MIN=%d NOUT=%d petscdlib STRINGFUNCTION=\"%s\" ; sync\n",tmp,(int)pf->dimin,(int)pf->dimout,string); 72 else sprintf(task,"cd %s ; mkdir ${USERNAME} ; cd ${USERNAME} ; \\cp -f ${PETSC_DIR}/src/pf/impls/string/makefile ./makefile ; make MIN=%d NOUT=%d -f makefile petscdlib STRINGFUNCTION=\"%s\" ; \\rm -f makefile petscdlib.c libpetscdlib.a ; sync\n",tmp,(int)pf->dimin,(int)pf->dimout,string); 73 74 #if defined(PETSC_HAVE_POPEN) 75 PetscCall(PetscPOpen(comm,NULL,task,"r",&fd)); 76 PetscCall(PetscPClose(comm,fd)); 77 #else 78 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine"); 79 #endif 80 81 PetscCallMPI(MPI_Barrier(comm)); 82 83 /* load the apply function from the dynamic library */ 84 PetscCall(PetscGetUserName(username,64)); 85 sprintf(lib,"%s/%s/libpetscdlib",tmp,username); 86 PetscCall(PetscDLLibrarySym(comm,NULL,lib,"PFApply_String",f)); 87 PetscCheck(f,PetscObjectComm((PetscObject)pf),PETSC_ERR_ARG_WRONGSTATE,"Cannot find function %s",lib); 88 #endif 89 PetscFunctionReturn(0); 90 } 91 92 static PetscErrorCode PFSetFromOptions_String(PetscOptionItems *PetscOptionsObject,PF pf) 93 { 94 PetscBool flag; 95 char value[PETSC_MAX_PATH_LEN]; 96 PetscErrorCode (*f)(void*,PetscInt,const PetscScalar*,PetscScalar*) = NULL; 97 98 PetscFunctionBegin; 99 PetscOptionsHeadBegin(PetscOptionsObject,"String function options"); 100 PetscCall(PetscOptionsString("-pf_string","Enter the function","PFStringCreateFunction","",value,sizeof(value),&flag)); 101 if (flag) { 102 PetscCall(PFStringCreateFunction(pf,value,(void**)&f)); 103 pf->ops->apply = f; 104 } 105 PetscOptionsHeadEnd(); 106 PetscFunctionReturn(0); 107 } 108 109 typedef PetscErrorCode (*FCN)(void*,PetscInt,const PetscScalar*,PetscScalar*); /* force argument to next function to not be extern C*/ 110 111 PETSC_EXTERN PetscErrorCode PFCreate_String(PF pf,void *value) 112 { 113 FCN f = NULL; 114 115 PetscFunctionBegin; 116 if (value) { 117 PetscCall(PFStringCreateFunction(pf,(char*)value,(void**)&f)); 118 } 119 PetscCall(PFSet(pf,f,NULL,PFView_String,PFDestroy_String,NULL)); 120 pf->ops->setfromoptions = PFSetFromOptions_String; 121 PetscFunctionReturn(0); 122 } 123