Package PyFoam :: Package Execution :: Module BasicRunner
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Execution.BasicRunner

  1  #  ICE Revision: $Id: BasicRunner.py 8608 2008-03-25 09:19:35Z bgschaid $  
  2  """Run a OpenFOAM command""" 
  3   
  4  import sys 
  5  import string 
  6  from os import path 
  7  from threading import Timer 
  8   
  9  if not 'curdir' in dir(path) or not 'sep' in dir(path): 
 10      print "Warning: Inserting symbols into os.path (Python-Version<2.3)" 
 11      path.curdir='.' 
 12      path.sep   ='/' 
 13       
 14  from FoamThread import FoamThread 
 15  from PyFoam.Infrastructure.FoamServer import FoamServer 
 16  from PyFoam.Infrastructure.Logging import foamLogger 
 17  from PyFoam.RunDictionary.SolutionDirectory import SolutionDirectory 
 18  from PyFoam.RunDictionary.ParameterFile import ParameterFile 
 19  from PyFoam.Error import warning,error 
 20  from PyFoam import configuration as config 
 21   
22 -def restoreControlDict(ctrl):
23 """Timed function to avoid time-stamp-problems""" 24 warning("Restoring the controlDict") 25 ctrl.restore()
26
27 -class BasicRunner(object):
28 """Base class for the running of commands 29 30 When the command is run the output is copied to a LogFile and 31 (optionally) standard-out 32 33 The argument list assumes for the first three elements the 34 OpenFOAM-convention: 35 36 <cmd> <dir> <case> 37 38 The directory name for outputs is therefor created from <dir> and 39 <case> 40 41 Provides some handle-methods that are to be overloaded for 42 additional functionality""" 43
44 - def __init__(self,argv=None,silent=False,logname=None,lam=None,server=False,restart=False):
45 """@param argv: list with the tokens that are the command line 46 if not set the standard command line is used 47 @param silent: if True no output is sent to stdout 48 @param logname: name of the logfile 49 @param lam: Information about a parallel run 50 @param server: Whether or not to start the network-server 51 @type lam: PyFoam.Execution.ParallelExecution.LAMMachine""" 52 53 if sys.version_info < (2,3): 54 # Python 2.2 does not have the capabilities for the Server-Thread 55 if server: 56 warning("Can not start server-process because Python-Version is too old") 57 server=False 58 59 if argv==None: 60 self.argv=sys.argv[1:] 61 else: 62 self.argv=argv 63 self.dir=path.join(self.argv[1],self.argv[2]) 64 if self.argv[2][-1]==path.sep: 65 self.argv[2]=self.argv[2][:-1] 66 67 if logname==None: 68 logname="PyFoam."+path.basename(argv[0]) 69 70 try: 71 sol=self.getSolutionDirectory() 72 except OSError,e: 73 error("Solution directory",self.dir,"does not exist. No use running. Problem:",e) 74 75 self.silent=silent 76 self.lam=lam 77 self.origArgv=self.argv 78 79 if self.lam!=None: 80 self.argv=lam.buildMPIrun(self.argv) 81 self.cmd=string.join(self.argv," ") 82 foamLogger().info("Starting: "+self.cmd+" in "+path.abspath(path.curdir)) 83 self.logFile=path.join(self.dir,logname+".logfile") 84 85 self.fatalError=False 86 self.warnings=0 87 self.started=False 88 89 self.isRestarted=False 90 if restart: 91 self.controlDict=ParameterFile(path.join(self.dir,"system","controlDict"),backup=True) 92 self.controlDict.replaceParameter("startFrom","latestTime") 93 self.isRestarted=True 94 else: 95 self.controlDict=None 96 97 self.run=FoamThread(self.cmd,self) 98 99 self.server=None 100 if server: 101 self.server=FoamServer(run=self.run,master=self) 102 self.server.setDaemon(True) 103 self.server.start() 104 try: 105 IP,PID,Port=self.server.info() 106 f=open(path.join(self.dir,"PyFoamServer.info"),"w") 107 print >>f,IP,PID,Port 108 f.close() 109 except AttributeError: 110 warning("There seems to be a problem with starting the server:",self.server,"with attributes",dir(self.server)) 111 self.server=None 112 113 self.createTime=None 114 self.nowTime=None 115 116 self.stopMe=False 117 self.writeRequested=False 118 119 self.endTriggers=[]
120
121 - def start(self):
122 """starts the command and stays with it till the end""" 123 124 self.started=True 125 fh=open(self.logFile,"w") 126 127 self.startHandle() 128 129 check=BasicRunnerCheck() 130 131 self.run.start() 132 133 while self.run.check(): 134 try: 135 self.run.read() 136 if not self.run.check(): 137 break 138 139 line=self.run.getLine() 140 141 tmp=check.getTime(line) 142 if check.controlDictRead(line): 143 if self.writeRequested: 144 warning("Preparing to reset controlDict to old glory") 145 Timer(config().getfloat("Execution","controlDictRestoreWait",default=30.), 146 restoreControlDict, 147 args=[self.controlDict]).start() 148 self.writeRequested=False 149 150 if tmp!=None: 151 self.nowTime=tmp 152 if self.createTime==None: 153 # necessary because interFoam reports no creation time 154 self.createTime=tmp 155 156 tmp=check.getCreateTime(line) 157 if tmp!=None: 158 self.createTime=tmp 159 160 if not self.silent: 161 print line 162 163 if line.find("FOAM FATAL ERROR")>=0 or line.find("FOAM FATAL IO ERROR")>=0: 164 self.fatalError=True 165 166 if self.fatalError and line!="": 167 foamLogger().error(line) 168 169 if line.find("FOAM Warning")>=0: 170 self.warnings+=1 171 172 if self.server!=None: 173 self.server._insertLine(line) 174 175 self.lineHandle(line) 176 177 fh.write(line+"\n") 178 fh.flush() 179 except KeyboardInterrupt,e: 180 foamLogger().warning("Keyboard Interrupt") 181 self.run.interrupt() 182 183 self.stopHandle() 184 185 for t in self.endTriggers: 186 t() 187 188 fh.close() 189 190 if self.server!=None: 191 self.server.deregister() 192 self.server.kill() 193 194 foamLogger().info("Finished")
195
196 - def runOK(self):
197 """checks whether the run was successful""" 198 if self.started: 199 return not self.fatalError 200 else: 201 return False
202
203 - def startHandle(self):
204 """to be called before the program is started""" 205 pass
206
207 - def stopGracefully(self):
208 """Tells the runner to stop at the next convenient time""" 209 if not self.stopMe: 210 self.stopMe=True 211 if not self.isRestarted: 212 self.controlDict=ParameterFile(path.join(self.dir,"system","controlDict"),backup=True) 213 self.controlDict.replaceParameter("stopAt","writeNow") 214 warning("Stopping run at next write")
215
216 - def writeResults(self):
217 """Writes the next possible time-step""" 218 # warning("writeResult is not yet implemented") 219 if not self.writeRequested: 220 if not self.isRestarted: 221 self.controlDict=ParameterFile(path.join(self.dir,"system","controlDict"),backup=True) 222 self.controlDict.replaceParameter("writeControl","timeStep") 223 self.controlDict.replaceParameter("writeInterval","1") 224 self.writeRequested=True
225
226 - def stopHandle(self):
227 """called after the program has stopped""" 228 if self.stopMe or self.isRestarted: 229 self.controlDict.restore()
230
231 - def lineHandle(self,line):
232 """called every time a new line is read""" 233 pass
234
235 - def logName(self):
236 """Get the name of the logfiles""" 237 return self.logFile
238
239 - def getSolutionDirectory(self,archive=None):
240 """@return: The directory of the case 241 @rtype: PyFoam.RunDictionary.SolutionDirectory 242 @param archive: Name of the directory for archiving results""" 243 244 return SolutionDirectory(self.dir,archive=archive)
245
246 - def addEndTrigger(self,f):
247 """@param f: A function that is to be executed at the end of the simulation""" 248 self.endTriggers.append(f)
249 250 import re 251
252 -class BasicRunnerCheck(object):
253 """A small class that does primitve checking for BasicRunner 254 Duplicates other efforts, but ....""" 255 256 floatRegExp="[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?" 257
258 - def __init__(self):
259 self.timeExpr=re.compile("^Time = (%f%)$".replace("%f%",self.floatRegExp)) 260 self.createExpr=re.compile("^Create mesh for time = (%f%)$".replace("%f%",self.floatRegExp))
261
262 - def getTime(self,line):
263 """Does this line contain time information?""" 264 m=self.timeExpr.match(line) 265 if m: 266 return float(m.group(1)) 267 else: 268 return None
269
270 - def getCreateTime(self,line):
271 """Does this line contain mesh time information?""" 272 m=self.createExpr.match(line) 273 if m: 274 return float(m.group(1)) 275 else: 276 return None
277
278 - def controlDictRead(self,line):
279 """Was the controlDict reread?""" 280 if line.find("Reading object controlDict from file"): 281 return True 282 else: 283 return False
284