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

Source Code for Module PyFoam.Execution.BasicRunner

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