1 """
2 Represents the actual CaseBuilder-File and other things that have to do with the Casebuilder
3 """
4
5 from xml.dom.minidom import parse
6 import xml.dom
7 from os import path
8 import os
9 import shutil
10 import glob
11
12 from PyFoam.Error import error
13 from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile
14 from PyFoam.Execution.BasicRunner import BasicRunner
15 from PyFoam.FoamInformation import oldAppConvention as oldApp
16 from CreateBoundaryPatches import CreateBoundaryPatches
17 from PyFoam import configuration as config
18
20 """Gets a list of the case-builder files found in the current path"""
29
31 for f in self.list:
32 yield f
33
36
39
41 """
42 This class reads an XML-file that describes how to build a case
43 and gives information about the case and if asked to builds the actual case
44 """
45
47 """@param fName: the XML-file that describes how to build the case"""
48
49 dom=parse(fName)
50 self.doc=dom.documentElement
51
52 if self.doc.tagName!='casebuilder':
53 error("Wrong root-element",self.doc.tagName,"Expected: 'casebuilder'")
54
56 return self.doc.getAttribute("name")
57
59 return self.doc.getAttribute("description")
60
62 ht=self.getSingleElement(self.doc,"helptext",optional=True)
63 if ht:
64 return ht.firstChild.nodeValue
65 else:
66 return "<No help text>"
67
70
73
76
79
82
85
87 return self.expandVars(self.doc.getAttribute("template"))
88
90 tmp=self.doc.getAttribute("initialdir")
91 if tmp=="":
92 tmp="0"
93 return tmp
94
96 orig=path.expanduser(orig)
97 orig=path.expandvars(orig)
98 if keys!=None:
99 orig=orig % keys
100 return orig
101
109
117
119 res={}
120 for nm,pat in self.boundaryPatterns():
121 res[nm]=pat
122 return res
123
125 bounds={}
126
127 for a in self.boundaryTree().getElementsByTagName("boundary"):
128 bounds[a.getAttribute("name")]=a.getAttribute("description")
129
130 return bounds
131
133 args=[]
134
135 for a in self.argTree().getElementsByTagName("argumentgroup"):
136 args.append(a.getAttribute("name"))
137
138 return args
139
141 args={}
142
143 for a in self.argTree().getElementsByTagName("argumentgroup"):
144 args[a.getAttribute("name")]=a.getAttribute("description")
145
146 return args
147
149 args=[]
150
151 for a in self.argTree().getElementsByTagName("arg"):
152 args.append(a.getAttribute("name"))
153
154 return args
155
157 """Returns a list with the arguments belongin to a specific group
158 @param name: Name of the group. If none is given, then all the arguments
159 belonging to no group are returned"""
160
161 result=[]
162
163 for c in self.argTree().childNodes:
164 if "tagName" in dir(c):
165 if c.tagName=="arg" and name==None:
166 result.append(c.getAttribute("name"))
167 elif c.tagName=="argumentgroup":
168 if c.getAttribute("name")==name:
169 for e in c.getElementsByTagName("arg"):
170 result.append(e.getAttribute("name"))
171
172 return result
173
175 args={}
176
177 for a in self.argTree().getElementsByTagName("arg"):
178 args[a.getAttribute("name")]=a.getAttribute("description")
179
180 return args
181
183 args={}
184
185 for a in self.argTree().getElementsByTagName("arg"):
186 args[a.getAttribute("name")]=a.getAttribute("default")
187
188 return args
189
191 """Get an element and check that it is the only one
192 @param parent: the parent element
193 @param name: The name of the element"""
194
195 tmp=parent.getElementsByTagName(name)
196 if len(tmp)<1:
197 if optional:
198 return None
199 else:
200 error("Element",name,"does not exist")
201 if len(tmp)>1:
202 error("More than one element",name,"does exist")
203 return tmp[0]
204
206 result="'type':'"+node.getAttribute("type")+"'"
207 para=self.expandVars(node.getAttribute("parameters"),args)
208 if para!="":
209 result+=","+para
210 return "{"+result+"}"
211
213 """Validate the arguments with the provided code (if it exists)"""
214 totalMsg=""
215 for a in self.argTree().getElementsByTagName("arg"):
216 msg=None
217 nm=a.getAttribute("name")
218 verify=self.getSingleElement(a,"verify",optional=True)
219 if verify:
220 valid=self.getSingleElement(verify,"validator",optional=True)
221 script=self.getSingleElement(verify,"script",optional=True)
222 if valid and script:
223 error("Variable",nm,"has script and validator. Only one of them supported")
224 elif valid:
225 typ=valid.getAttribute("type")
226 arg=args[nm]
227 isNumeric=False
228 if typ=="float":
229 isNumeric=True
230 try:
231 tmp=float(arg)
232 except ValueError:
233 msg="Not a floating point number"
234 elif typ=="integer":
235 isNumeric=True
236 try:
237 tmp=int(arg)
238 except ValueError:
239 msg="Not an integer number"
240 elif typ=="file":
241 if not path.exists(arg):
242 msg="File "+arg+" does not exist"
243 else:
244 error("No validator implemented for type",typ,"in variable",nm)
245 if isNumeric and not msg:
246 if valid.hasAttribute("min"):
247 if float(arg)<float(valid.getAttribute("min")):
248 msg="Must be bigger than "+valid.getAttribute("min")
249 if valid.hasAttribute("max"):
250 if float(arg)>float(valid.getAttribute("max")):
251 msg="Must be smaller than "+valid.getAttribute("max")
252
253 elif script:
254 if script.getAttribute("plugin")!="python":
255 error("Only plugin-type 'python' is supported for variable",nm)
256 code=script.firstChild.nodeValue
257 arg=args[nm]
258 exec code
259 if msg:
260 totalMsg+=nm+": "+msg+" "
261
262 if totalMsg=="":
263 totalMsg=None
264
265 return totalMsg
266
268 """Add derived variables to the argument dictionary"""
269
270 for _a_ in _args_:
271 exec "%s = '%s'" % (_a_,_args_[_a_])
272
273 if self.varTree():
274 for _a_ in self.varTree().getElementsByTagName("var"):
275 _nm_=_a_.getAttribute("name")
276 if _nm_ in ["_args_","_a_","_nm_"]:
277 error("Variable",_nm_,"is needed for this routine to work")
278
279 if len(_a_.firstChild.nodeValue)>0:
280 exec _a_.firstChild.nodeValue
281 exec "_args_['"+_nm_+"']=str("+_nm_+")"
282
283 return _args_
284
286 """Builds the case
287 @param cName: The name of the case directory
288 @param args: The arguments (as a dictionary)"""
289
290 args=self.calculateVariables(args)
291
292 os.mkdir(cName)
293
294 for d in self.parameterTree().getElementsByTagName("directory"):
295 dName=path.join(cName,d.getAttribute("name"))
296 if not path.isdir(dName):
297 os.mkdir(dName)
298 sName=path.join(self.templatePath(),d.getAttribute("name"))
299 for f in d.getElementsByTagName("file"):
300 dFile=path.join(dName,f.getAttribute("name"))
301 shutil.copy(path.join(sName,f.getAttribute("name")),dFile)
302 if len(f.getElementsByTagName("parameter"))>0:
303 pf=ParsedParameterFile(dFile)
304 for p in f.getElementsByTagName("parameter"):
305 pName=p.getAttribute("name")
306 pValue=self.expandVars(p.getAttribute("value"),args)
307 exec "pf"+pName+"="+pValue
308 pf.writeFile()
309
310 prep=self.getSingleElement(self.doc,"meshpreparation")
311 util=self.getSingleElement(prep,"utility",optional=True)
312 copy=self.getSingleElement(prep,"copy",optional=True)
313
314 if util and copy:
315 error("Copy and utilitiy mesh preparation specified")
316 elif util:
317 app=util.getAttribute("command")
318 arg=self.expandVars(util.getAttribute("arguments"),args)
319 argv=[app,"-case",cName]+arg.split()
320 if oldApp():
321 argv[1]="."
322 run=BasicRunner(argv=argv,silent=True,logname="CaseBuilder.prepareMesh."+app)
323 run.start()
324 if not run.runOK():
325 error(app,"failed. Check the logs")
326 elif copy:
327 source=self.expandVars(copy.getAttribute("template"),args)
328 time=self.expandVars(copy.getAttribute("time"),args)
329 if time=="":
330 time="constant"
331 shutil.copytree(path.join(source,time,"polyMesh"),
332 path.join(cName,"constant","polyMesh"))
333 else:
334 error("Neither copy nor utilitiy mesh preparation specified")
335
336 dName=path.join(cName,self.initialDir())
337 if not path.isdir(dName):
338 os.mkdir(dName)
339 sName=path.join(self.templatePath(),self.initialDir())
340 for f in self.fieldTree().getElementsByTagName("field"):
341 dFile=path.join(dName,f.getAttribute("name"))
342 shutil.copy(path.join(sName,f.getAttribute("name")),dFile)
343 default=self.makeBC(self.getSingleElement(f,"defaultbc"),args)
344
345 CreateBoundaryPatches(args=["--fix-types",
346 "--overwrite",
347 "--clear",
348 "--default="+default,
349 dFile])
350 bcDict={}
351 bounds=self.boundaries()
352 for b in f.getElementsByTagName("bc"):
353 nm=b.getAttribute("name")
354 if nm not in bounds:
355 error("Boundary",nm,"not in list",bounds,"for field",f.getAttribute("name"))
356 bcDict[nm]=b
357
358 for name,pattern in self.boundaryPatterns():
359 if name in bcDict:
360 default=self.makeBC(bcDict[name],args)
361 CreateBoundaryPatches(args=["--filter="+pattern,
362 "--overwrite",
363 "--default="+default,
364 dFile])
365
366 ic=self.expandVars(self.getSingleElement(f,"ic").getAttribute("value"),args)
367 pf=ParsedParameterFile(dFile)
368 pf["internalField"]="uniform "+ic
369 pf.writeFile()
370