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 masters[custom.id]=custom
283 plotCustom=createPlotTimelines(self.getAnalyzer(custom.name).lines,
284 custom=custom,
285 implementation=plottingImplementation)
286 self.getAnalyzer(custom.name).lines.setSplitting(splitThres=splitThres,
287 advancedSplit=True)
288 plotCustom.setTitle(custom.theTitle)
289 plots["custom%04d" % i]=plotCustom
290 else:
291 slaves.append(custom)
292
293 for s in slaves:
294 if s.master not in masters:
295 error("The custom plot",s.id,"wants the master plot",
296 s.master,"but it is not found in the list of masters",
297 list(masters.keys()))
298 else:
299 slave=self.getAnalyzer(s.name)
300 master=self.getAnalyzer(masters[s.master].name)
301 slave.setMaster(master)
302
303 self.reset()
304
305 return plots
306
308 """Writes the necessary information for the plots permanently to disc,
309 so that it doesn't have to be generated again
310 @param wait: wait for the lock to be allowed to pickle"""
311
312
313
314 lines=allLines()
315 plots=allPlots()
316 if lines and plots:
317 gotIt=self.pickleLock.acquire(wait)
318 if not gotIt:
319 return
320
321 pickleFile=path.join(self.logDir,"pickledPlots")
322 pick=pickle.Pickler(open(pickleFile+".tmp","wb"))
323 pick.dump(lines.prepareForTransfer())
324 pick.dump(plots.prepareForTransfer())
325 move(pickleFile+".tmp",pickleFile)
326
327 if hasattr(self,"data"):
328 pickleFile=path.join(self.logDir,"pickledUnfinishedData")
329 pick=pickle.Pickler(open(pickleFile+".tmp","wb"))
330 pick.dump(self.data)
331 del pick
332 move(pickleFile+".tmp",pickleFile)
333
334 self.pickleLock.release()
335
337 if hasattr(self,"data"):
338 self.data["analyzed"]=data
339
340
341