1
2 """Run a OpenFOAM command"""
3
4 import sys
5 import string
6 import gzip
7 from os import path
8 from threading import Timer
9 from time import time
10
11 from PyFoam.FoamInformation import oldAppConvention as oldApp
12
13 if not 'curdir' in dir(path) or not 'sep' in dir(path):
14 print "Warning: Inserting symbols into os.path (Python-Version<2.3)"
15 path.curdir='.'
16 path.sep ='/'
17
18 from FoamThread import FoamThread
19 from PyFoam.Infrastructure.FoamServer import FoamServer
20 from PyFoam.Infrastructure.Logging import foamLogger
21 from PyFoam.RunDictionary.SolutionDirectory import SolutionDirectory
22 from PyFoam.RunDictionary.ParameterFile import ParameterFile
23 from PyFoam.Error import warning,error
24 from PyFoam import configuration as config
25
27 """Timed function to avoid time-stamp-problems"""
28 warning("Restoring the controlDict")
29 ctrl.restore()
30 runner.controlDict=None
31
33 """Base class for the running of commands
34
35 When the command is run the output is copied to a LogFile and
36 (optionally) standard-out
37
38 The argument list assumes for the first three elements the
39 OpenFOAM-convention:
40
41 <cmd> <dir> <case>
42
43 The directory name for outputs is therefor created from <dir> and
44 <case>
45
46 Provides some handle-methods that are to be overloaded for
47 additional functionality"""
48
49 - def __init__(self,
50 argv=None,
51 silent=False,
52 logname=None,
53 compressLog=False,
54 lam=None,
55 server=False,
56 restart=False,
57 noLog=False,
58 remark=None,
59 jobId=None):
60 """@param argv: list with the tokens that are the command line
61 if not set the standard command line is used
62 @param silent: if True no output is sent to stdout
63 @param logname: name of the logfile
64 @param compressLog: Compress the logfile into a gzip
65 @param lam: Information about a parallel run
66 @param server: Whether or not to start the network-server
67 @type lam: PyFoam.Execution.ParallelExecution.LAMMachine
68 @param noLog: Don't output a log file
69 @param remark: User defined remark about the job
70 @param jobId: Job ID of the controlling system (Queueing system)"""
71
72 if sys.version_info < (2,3):
73
74 if server:
75 warning("Can not start server-process because Python-Version is too old")
76 server=False
77
78 if argv==None:
79 self.argv=sys.argv[1:]
80 else:
81 self.argv=argv
82
83 if oldApp():
84 self.dir=path.join(self.argv[1],self.argv[2])
85 if self.argv[2][-1]==path.sep:
86 self.argv[2]=self.argv[2][:-1]
87 else:
88 self.dir=path.curdir
89 if "-case" in self.argv:
90 self.dir=self.argv[self.argv.index("-case")+1]
91
92 if logname==None:
93 logname="PyFoam."+path.basename(argv[0])
94
95 try:
96 sol=self.getSolutionDirectory()
97 except OSError,e:
98 error("Solution directory",self.dir,"does not exist. No use running. Problem:",e)
99
100 self.silent=silent
101 self.lam=lam
102 self.origArgv=self.argv
103
104 if self.lam!=None:
105 self.argv=lam.buildMPIrun(self.argv)
106 self.cmd=string.join(self.argv," ")
107 foamLogger().info("Starting: "+self.cmd+" in "+path.abspath(path.curdir))
108 self.logFile=path.join(self.dir,logname+".logfile")
109 self.noLog=noLog
110 self.compressLog=compressLog
111 if self.compressLog:
112 self.logFile+=".gz"
113
114 self.fatalError=False
115 self.fatalFPE=False
116 self.fatalStackdump=False
117
118 self.warnings=0
119 self.started=False
120
121 self.isRestarted=False
122 if restart:
123 self.controlDict=ParameterFile(path.join(self.dir,"system","controlDict"),backup=True)
124 self.controlDict.replaceParameter("startFrom","latestTime")
125 self.isRestarted=True
126 else:
127 self.controlDict=None
128
129 self.run=FoamThread(self.cmd,self)
130
131 self.server=None
132 if server:
133 self.server=FoamServer(run=self.run,master=self)
134 self.server.setDaemon(True)
135 self.server.start()
136 try:
137 IP,PID,Port=self.server.info()
138 f=open(path.join(self.dir,"PyFoamServer.info"),"w")
139 print >>f,IP,PID,Port
140 f.close()
141 except AttributeError:
142 warning("There seems to be a problem with starting the server:",self.server,"with attributes",dir(self.server))
143 self.server=None
144
145 self.createTime=None
146 self.nowTime=None
147 self.startTimestamp=time()
148
149 self.stopMe=False
150 self.writeRequested=False
151
152 self.endTriggers=[]
153
154 self.lastLogLineSeen=None
155 self.lastTimeStepSeen=None
156
157 self.remark=remark
158 self.jobId=jobId
159
254
256 """checks whether the run was successful"""
257 if self.started:
258 return not self.fatalError and not self.fatalFPE and not self.fatalStackdump
259 else:
260 return False
261
263 """to be called before the program is started"""
264 pass
265
267 """Tells the runner to stop at the next convenient time"""
268 if not self.stopMe:
269 self.stopMe=True
270 if not self.isRestarted:
271 if self.controlDict:
272 warning("The controlDict has already been modified. Restoring will be problementic")
273 self.controlDict=ParameterFile(path.join(self.dir,"system","controlDict"),backup=True)
274 self.controlDict.replaceParameter("stopAt","writeNow")
275 warning("Stopping run at next write")
276
288
290 """called after the program has stopped"""
291 if self.stopMe or self.isRestarted:
292 self.controlDict.restore()
293
295 """called every time a new line is read"""
296 pass
297
299 """Get the name of the logfiles"""
300 return self.logFile
301
303 """@return: The directory of the case
304 @rtype: PyFoam.RunDictionary.SolutionDirectory
305 @param archive: Name of the directory for archiving results"""
306
307 return SolutionDirectory(self.dir,archive=archive,parallel=True)
308
310 """@param f: A function that is to be executed at the end of the simulation"""
311 self.endTriggers.append(f)
312
313 import re
314
316 """A small class that does primitve checking for BasicRunner
317 Duplicates other efforts, but ...."""
318
319 floatRegExp="[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?"
320
322 self.timeExpr=re.compile("^Time = (%f%)$".replace("%f%",self.floatRegExp))
323 self.createExpr=re.compile("^Create mesh for time = (%f%)$".replace("%f%",self.floatRegExp))
324
326 """Does this line contain time information?"""
327 m=self.timeExpr.match(line)
328 if m:
329 return float(m.group(1))
330 else:
331 return None
332
334 """Does this line contain mesh time information?"""
335 m=self.createExpr.match(line)
336 if m:
337 return float(m.group(1))
338 else:
339 return None
340
342 """Was the controlDict reread?"""
343 if line.find("Reading object controlDict from file")>=0:
344 return True
345 else:
346 return False
347