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

Source Code for Module PyFoam.Execution.BasicRunner

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