1
2 """Working with a solution directory"""
3
4 from PyFoam.Basics.Utilities import Utilities
5 from PyFoam.Basics.BasicFile import BasicFile
6
7 from os import listdir,path,mkdir,symlink
8 import tarfile,fnmatch
9 import re
10
12 """Represents a solution directory
13
14 In the solution directory subdirectories whose names are numbers
15 are assumed to be solutions for a specific time-step
16
17 A sub-directory (called the Archive) is created to which solution
18 data is copied"""
19
20 - def __init__(self,name,archive="ArchiveDir",paraviewLink=True):
21 """@param name: Name of the solution directory
22 @param archive: name of the directory where the lastToArchive-method
23 should copy files, if None no archive is created
24 @param paraviewLink: Create a symbolic link controlDict.foam for paraview"""
25
26 self.name=name
27 self.archive=None
28 if archive!=None:
29 self.archive=path.join(name,archive)
30 if not path.exists(self.archive):
31 mkdir(self.archive)
32
33 self.backups=[]
34
35 self.reread()
36
37 self.essential=[self.systemDir(),self.constantDir(),self.initialDir()]
38
39 if paraviewLink and not path.exists(self.controlDict()+".foam"):
40 symlink(path.basename(self.controlDict()),self.controlDict()+".foam")
41
43 """Checks whether this is a valid case directory by looking for
44 the system- and constant-directories and the controlDict-file"""
45 if not path.exists(self.systemDir()):
46 return False
47 elif not path.isdir(self.systemDir()):
48 return False
49 elif not path.exists(self.constantDir()):
50 return False
51 elif not path.isdir(self.constantDir()):
52 return False
53 elif not path.exists(self.controlDict()):
54 return False
55 else:
56 return True
57
59 """add directory to the list that is needed to clone this case
60 @param name: name of the subdirectory (the case directory is prepended)"""
61 self.essential.append(path.join(self.name,name))
62
64 """create a clone of this case directory. Remove the target directory, if it already exists
65
66 @param name: Name of the new case directory
67 @param svnRemove: Look for .svn-directories and remove them
68 @rtype: L{SolutionDirectory} or correct subclass
69 @return: The target directory"""
70
71 if path.exists(name):
72 self.execute("rm -r "+name)
73 mkdir(name)
74 for d in self.essential:
75 self.execute("cp -r "+d+" "+name)
76
77 if svnRemove:
78 self.execute("find "+name+" -name .svn -exec rm -rf {} \\; -prune")
79
80 return self.__class__(name,archive=self.archive)
81
82 - def packCase(self,tarname,last=False,exclude=[],additional=[]):
83 """Packs all the important files into a compressed tarfile.
84 Uses the essential-list and excludes the .svn-directories.
85 Also excludes files ending with ~
86 @param tarname: the name of the tar-file
87 @param last: add the last directory to the list of directories to be added
88 @param exclude: List with additional glob filename-patterns to be excluded
89 @param additional: List with additional glob filename-patterns
90 that are to be added"""
91
92 ex=["*~",".svn"]+exclude
93 members=self.essential[:]
94 if last:
95 if self.getLast()!=self.first:
96 members.append(self.latestDir())
97 for p in additional:
98 for f in listdir(self.name):
99 if (f not in members) and fnmatch.fnmatch(f,p):
100 members.append(path.join(self.name,f))
101
102 tar=tarfile.open(tarname,"w:gz")
103
104 for m in members:
105 self.addToTar(tar,m,exclude=ex)
106
107 tar.close()
108
109 - def addToTar(self,tar,name,exclude=[]):
110 """The workhorse for the packCase-method"""
111
112 for e in exclude:
113 if fnmatch.fnmatch(path.basename(name),e):
114 return
115
116 if path.isdir(name):
117 for m in listdir(name):
118 self.addToTar(tar,path.join(name,m),exclude=exclude)
119 else:
120 tar.add(name)
121
123 """Rescan the directory for the time directories"""
124 self.times=[]
125 self.first=None
126 self.last=None
127 self.procDirs=0
128
129 for f in listdir(self.name):
130 try:
131 val=float(f)
132 self.times.append(f)
133 if self.first==None:
134 self.first=f
135 else:
136 if float(f)<float(self.first):
137 self.first=f
138 if self.last==None:
139 self.last=f
140 else:
141 if float(f)>float(self.last):
142 self.last=f
143
144 except ValueError:
145 if re.compile("processor[0-9]+").match(f):
146 self.procDirs+=1
147
148 self.times.sort(self.sorttimes)
149
151 """List with the processor directories"""
152 dirs=[]
153 for f in listdir(self.name):
154 if re.compile("processor[0-9]+").match(f):
155 dirs.append(f)
156
157 return dirs
158
160 """The number of directories with processor-data"""
161 self.reread()
162 return self.procDirs
163
165 """Sort function for the solution files"""
166 if(float(x)==float(y)):
167 return 0
168 elif float(x)<float(y):
169 return -1
170 else:
171 return 1
172
174 """ @return: List of all the available times"""
175 self.reread()
176 return self.times
177
179 """add file to list of files that are to be copied to the
180 archive"""
181 self.backups.append(path.join(self.name,pth))
182
184 """@return: the last time for which a solution exists
185 @rtype: str"""
186 self.reread()
187 return self.last
188
190 """copy the last solution (plus the backup-files to the
191 archive)
192
193 @param name: name of the sub-directory in the archive"""
194 if self.archive==None:
195 print "Warning: nor Archive-directory"
196 return
197
198 self.reread()
199 fname=path.join(self.archive,name)
200 if path.exists(fname):
201 self.execute("rm -r "+fname)
202 mkdir(fname)
203 self.execute("cp -r "+path.join(self.name,self.last)+" "+fname)
204 for f in self.backups:
205 self.execute("cp -r "+f+" "+fname)
206
208 """remove all time-directories after a certain time. If not time ist
209 set the initial time is used
210 @param after: time after which directories ar to be removed
211 @param removeProcs: if True the processorX-directories are removed.
212 Otherwise the timesteps after last are removed from the
213 processor-directories"""
214
215 self.reread()
216
217 if after==None:
218 time=float(self.first)
219 else:
220 time=float(after)
221
222 for f in self.times:
223 if float(f)>time:
224 self.execute("rm -r "+path.join(self.name,f))
225
226 if self.nrProcs():
227 for f in listdir(self.name):
228 if re.compile("processor[0-9]+").match(f):
229 if removeProcs:
230 self.execute("rm -r "+path.join(self.name,f))
231 else:
232 pDir=path.join(self.name,f)
233 for t in listdir(pDir):
234 try:
235 val=float(t)
236 if val>time:
237 self.execute("rm -r "+path.join(pDir,t))
238 except ValueError:
239 pass
240
242 """Clear all files that fit a certain shell (glob) pattern
243 @param glob: the pattern which the files are going to fit"""
244
245 self.execute("rm -rf "+path.join(self.name,glob))
246
248 """Remove additional directories
249 @param pyfoam: rremove all directories typically created by PyFoam"""
250
251 if pyfoam:
252 self.clearPattern("PyFoam.?*")
253 self.clearPattern("*?.analyzed")
254
255 - def clear(self,after=None,processor=True,pyfoam=True):
256 """One-stop-shop to remove data
257 @param after: time after which directories ar to be removed
258 @param processor: remove the processorXX directories
259 @param pyfoam: rremove all directories typically created by PyFoam"""
260 self.clearResults(after=after,removeProcs=processor)
261 self.clearOther(pyfoam=pyfoam)
262
264 """@return: the name of the first time-directory (==initial
265 conditions
266 @rtype: str"""
267 if self.first:
268 return path.join(self.name,self.first)
269 else:
270 return None
271
273 """@param region: Specify the region for cases with more than 1 mesh
274 @return: the name of the first last-directory (==simulation
275 results)
276 @rtype: str"""
277 last=self.getLast()
278 if last:
279 return path.join(self.name,last)
280 else:
281 return None
282
284 """@param region: Specify the region for cases with more than 1 mesh
285 @return: the name of the C{constant}-directory
286 @rtype: str"""
287 if region:
288 return path.join(self.name,"constant",region)
289 else:
290 return path.join(self.name,"constant")
291
293 """@param region: Specify the region for cases with more than 1 mesh
294 @return: the name of the C{system}-directory
295 @rtype: str"""
296 if region:
297 return path.join(self.name,"system",region)
298 else:
299 return path.join(self.name,"system")
300
302 """@param region: Specify the region for cases with more than 1 mesh
303 @return: the name of the C{controlDict}
304 @rtype: str"""
305 return path.join(self.systemDir(),"controlDict")
306
308 """@param region: Specify the region for cases with more than 1 mesh
309 @return: the name of the C{polyMesh}
310 @rtype: str"""
311 return path.join(self.constantDir(region=region),"polyMesh")
312
314 """@param region: Specify the region for cases with more than 1 mesh
315 @return: name of the C{boundary}-file
316 @rtype: str"""
317 return path.join(self.polyMeshDir(region=region),"boundary")
318
320 """@param region: Specify the region for cases with more than 1 mesh
321 @return: the name of the C{blockMeshDict} if it exists. Returns
322 an empty string if it doesn't
323 @rtype: str"""
324 p=path.join(self.polyMeshDir(region=region),"blockMeshDict")
325 if path.exists(p):
326 return p
327 else:
328 return ""
329
331 """create a file in the solution directory and return a
332 corresponding BasicFile-object
333
334 @param name: Name of the file
335 @rtype: L{BasicFile}"""
336 return BasicFile(path.join(self.name,name))
337
339 """Gets a list of all the available mesh regions by checking all
340 directories in constant and using all those that have a polyMesh-subdirectory"""
341 lst=[]
342 for d in self.listDirectory(self.constantDir()):
343 if path.isdir(path.join(self.constantDir(),d)):
344 if path.exists(self.polyMeshDir(region=d)):
345 lst.append(d)
346 lst.sort()
347 return lst
348
350 """Solution directory with a directory for the Chemkin-files"""
351
352 chemkinName = "chemkin"
353
354 - def __init__(self,name,archive="ArchiveDir"):
358
360 """@rtype: str
361 @return: The directory with the Chemkin-Files"""
362
363 return path.join(self.name,self.chemkinName)
364