1
2 """Common stuff for classes that use analyzers"""
3
4 from os import path,mkdir
5 from shutil import move
6
7 from PyFoam.Basics.PlotTimelinesFactory import createPlotTimelines,createPlotTimelinesDirect
8 from PyFoam.Basics.TimeLineCollection import signedMax
9 from PyFoam.LogAnalysis.RegExpLineAnalyzer import RegExpLineAnalyzer
10 from PyFoam.LogAnalysis.PhaseChangerLineAnalyzer import PhaseChangerLineAnalyzer
11
12 from PyFoam.Error import error
13
14
15 from PyFoam.ThirdParty.six.moves import cPickle as pickle
16
17 from PyFoam.Basics.GeneralPlotTimelines import allPlots
18 from PyFoam.Basics.TimeLineCollection import allLines
19
20 from threading import Lock
21
23 """This class collects information and methods that are needed for
24 handling analyzers"""
25
26 - def __init__(self,
27 filename,
28 analyzer,
29 doPickling=True):
30 """@param filename: name of the file that is being analyzed
31 @param analyzer: the analyzer itself
32 @param doPickling: write the pickled plot data"""
33
34 self.analyzer=analyzer
35
36 if 'dir' in dir(self):
37 self.logDir=path.join(self.dir,filename+".analyzed")
38 else:
39 self.logDir=filename+".analyzed"
40
41 if not path.exists(self.logDir):
42 mkdir(self.logDir)
43
44 self.doPickling=doPickling
45 if self.doPickling:
46 self.pickleLock=Lock()
47
48 self.reset()
49
50 if hasattr(self,"data"):
51 pickleFile=path.join(self.logDir,"pickledStartData")
52 pick=pickle.Pickler(open(pickleFile,"wb"))
53 pick.dump(self.data)
54
56 self.analyzer.tearDown()
57 if hasattr(self,"data"):
58 pickleFile=path.join(self.logDir,"pickledData")
59 pick=pickle.Pickler(open(pickleFile,"wb"))
60 pick.dump(self.data)
61
63 """@returns: A list with the names of the analyzers"""
64 return self.analyzer.listAnalyzers()
65
67 """@param name: name of the LineAnalyzer to get"""
68 return self.analyzer.getAnalyzer(name)
69
71 """@param name: name of the LineAnalyzer we ask for"""
72 return self.analyzer.hasAnalyzer(name)
73
75 """@param name: name of the LineAnalyzer to add
76 @param analyzer: the analyzer to add"""
77 analyzer.setDirectory(self.logDir)
78 return self.analyzer.addAnalyzer(name,analyzer)
79
81 """Not to be called: calls the analyzer for the current line"""
82 self.analyzer.analyzeLine(line)
83
85 """reset the analyzer"""
86 self.analyzer.setDirectory(self.logDir)
87
89 """Get the name of the directory where the data is written to"""
90 return self.logDir
91
93 """Get the execution time"""
94 return self.analyzer.getTime()
95
96 - def addTrigger(self,time,func,once=True,until=None):
97 """Adds a timed trigger to the Analyzer
98 @param time: the time at which the function should be triggered
99 @param func: the trigger function
100 @param once: Should this function be called once or at every time-step
101 @param until: The time until which the trigger should be called"""
102
103 self.analyzer.addTrigger(time,func,once=once,until=until)
104
105 - def createPlots(self,
106 persist=None,
107 raiseit=False,
108 splitThres=2048,
109 plotLinear=True,
110 plotCont=True,
111 plotBound=True,
112 plotIterations=True,
113 plotCourant=True,
114 plotExecution=True,
115 plotDeltaT=True,
116 start=None,
117 end=None,
118 writeFiles=False,
119 customRegexp=None,
120 plottingImplementation="dummy"):
121
122 plots={}
123
124 if plotLinear and self.hasAnalyzer("Linear"):
125 plots["linear"]=createPlotTimelinesDirect("linear",
126 self.getAnalyzer("Linear").lines,
127 persist=persist,
128 raiseit=raiseit,
129 forbidden=["final","iterations"],
130 start=start,
131 end=end,
132 logscale=True,
133 implementation=plottingImplementation)
134 self.getAnalyzer("Linear").lines.setSplitting(splitThres=splitThres,
135 splitFun=max,
136 advancedSplit=True)
137
138 plots["linear"].setTitle("Residuals")
139 plots["linear"].setYLabel("Initial residual")
140
141 if plotCont and self.hasAnalyzer("Continuity"):
142 plots["cont"]=createPlotTimelinesDirect("continuity",
143 self.getAnalyzer("Continuity").lines,
144 persist=persist,
145 alternateAxis=["Global"],
146 raiseit=raiseit,
147 start=start,
148 end=end,
149 implementation=plottingImplementation)
150 plots["cont"].setYLabel("Cumulative")
151 plots["cont"].setYLabel2("Global")
152 self.getAnalyzer("Continuity").lines.setSplitting(splitThres=splitThres,
153 advancedSplit=True)
154
155 plots["cont"].setTitle("Continuity")
156
157 if plotBound and self.hasAnalyzer("Bounding"):
158 plots["bound"]=createPlotTimelinesDirect("bounding",
159 self.getAnalyzer("Bounding").lines,
160 persist=persist,
161 raiseit=raiseit,
162 start=start,
163 end=end,
164 implementation=plottingImplementation)
165 self.getAnalyzer("Bounding").lines.setSplitting(splitThres=splitThres,
166 splitFun=signedMax,
167 advancedSplit=True)
168 plots["bound"].setTitle("Bounded variables")
169
170 if plotIterations and self.hasAnalyzer("Iterations"):
171 plots["iter"]=createPlotTimelinesDirect("iterations",
172 self.getAnalyzer("Iterations").lines,
173 persist=persist,
174 with_="steps",
175 raiseit=raiseit,
176 start=start,
177 end=end,
178 implementation=plottingImplementation)
179 self.getAnalyzer("Iterations").lines.setSplitting(splitThres=splitThres,
180 advancedSplit=True)
181
182 plots["iter"].setTitle("Iterations")
183 plots["iter"].setYLabel("Sum of iterations")
184
185 if plotCourant and self.hasAnalyzer("Courant"):
186 plots["courant"]=createPlotTimelinesDirect("courant",
187 self.getAnalyzer("Courant").lines,
188 persist=persist,
189 raiseit=raiseit,
190 start=start,
191 end=end,
192 implementation=plottingImplementation)
193 self.getAnalyzer("Courant").lines.setSplitting(splitThres=splitThres,
194 advancedSplit=True)
195
196 plots["courant"].setTitle("Courant")
197 plots["courant"].setYLabel("Courant Number [1]")
198
199 if plotDeltaT and self.hasAnalyzer("DeltaT"):
200 plots["deltaT"]=createPlotTimelinesDirect("timestep",
201 self.getAnalyzer("DeltaT").lines,
202 persist=persist,
203 raiseit=raiseit,
204 start=start,
205 end=end,
206 logscale=True,
207 implementation=plottingImplementation)
208 self.getAnalyzer("DeltaT").lines.setSplitting(splitThres=splitThres,
209 advancedSplit=True)
210
211 plots["deltaT"].setTitle("DeltaT")
212 plots["deltaT"].setYLabel("dt [s]")
213
214 if plotExecution and self.hasAnalyzer("Execution"):
215 plots["execution"]=createPlotTimelinesDirect("execution",
216 self.getAnalyzer("Execution").lines,
217 persist=persist,
218 with_="steps",
219 raiseit=raiseit,
220 start=start,
221 end=end,
222 implementation=plottingImplementation)
223 self.getAnalyzer("Execution").lines.setSplitting(splitThres=splitThres,
224 advancedSplit=True)
225
226 plots["execution"].setTitle("Execution Time")
227 plots["execution"].setYLabel("Time [s]")
228
229 if customRegexp:
230 self.plotCustom=[]
231 masters={}
232 slaves=[]
233 for i,custom in enumerate(customRegexp):
234 if not custom.enabled:
235 continue
236
237 if persist!=None:
238 custom.persist=persist
239 if start!=None:
240 custom.start=start
241 if end!=None:
242 custom.end=end
243 custom.raiseit=raiseit
244
245 createPlot=True
246 if custom.type=="phase":
247 self.addAnalyzer(custom.name,
248 PhaseChangerLineAnalyzer(custom.expr,
249 idNr=custom.idNr))
250 createPlot=False
251 elif custom.type=="dynamic":
252 self.addAnalyzer(custom.name,
253 RegExpLineAnalyzer(custom.name.lower(),
254 custom.expr,
255 titles=custom.titles,
256 doTimelines=True,
257 doFiles=writeFiles,
258 accumulation=custom.accumulation,
259 progressTemplate=custom.progress,
260 singleFile=True,
261 idNr=custom.idNr,
262 startTime=custom.start,
263 endTime=custom.end))
264
265 elif custom.type=="regular" or custom.type=="slave":
266 self.addAnalyzer(custom.name,
267 RegExpLineAnalyzer(custom.name.lower(),
268 custom.expr,
269 titles=custom.titles,
270 doTimelines=True,
271 doFiles=writeFiles,
272 accumulation=custom.accumulation,
273 progressTemplate=custom.progress,
274 singleFile=True,
275 startTime=custom.start,
276 endTime=custom.end))
277 else:
278 error("Unknown type",custom.type,"in custom expression",custom.name)
279
280 if createPlot:
281 if custom.master==None:
282 if custom.type=="slave":
283 error("Custom expression",custom.name,"is supposed to be a 'slave' but no master is defined")
284 masters[custom.id]=custom
285 plotCustom=createPlotTimelines(self.getAnalyzer(custom.name).lines,
286 custom=custom,
287 implementation=plottingImplementation)
288 self.getAnalyzer(custom.name).lines.setSplitting(splitThres=splitThres,
289 advancedSplit=True)
290 plotCustom.setTitle(custom.theTitle)
291 plots["custom%04d" % i]=plotCustom
292 else:
293 slaves.append(custom)
294
295 for s in slaves:
296 if s.master not in masters:
297 error("The custom plot",s.id,"wants the master plot",
298 s.master,"but it is not found in the list of masters",
299 list(masters.keys()))
300 else:
301 slave=self.getAnalyzer(s.name)
302 master=self.getAnalyzer(masters[s.master].name)
303 slave.setMaster(master)
304
305 self.reset()
306
307 return plots
308
310 """Writes the necessary information for the plots permanently to disc,
311 so that it doesn't have to be generated again
312 @param wait: wait for the lock to be allowed to pickle"""
313
314
315
316 lines=allLines()
317 plots=allPlots()
318 if lines and plots:
319 gotIt=self.pickleLock.acquire(wait)
320 if not gotIt:
321 return
322
323 pickleFile=path.join(self.logDir,"pickledPlots")
324 pick=pickle.Pickler(open(pickleFile+".tmp","wb"))
325 pick.dump(lines.prepareForTransfer())
326 pick.dump(plots.prepareForTransfer())
327 move(pickleFile+".tmp",pickleFile)
328
329 if hasattr(self,"data"):
330 pickleFile=path.join(self.logDir,"pickledUnfinishedData")
331 pick=pickle.Pickler(open(pickleFile+".tmp","wb"))
332 pick.dump(self.data)
333 del pick
334 move(pickleFile+".tmp",pickleFile)
335
336 self.pickleLock.release()
337
339 if hasattr(self,"data"):
340 self.data["analyzed"]=data
341
342
343