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"""
22 dirList=config().get("CaseBuilder","descriptionpath")
23 self.list=[]
24 for d in dirList:
25 for f in glob.glob(path.join(d,"*.pfcb")):
26 nm=path.basename(f)
27 cb=CaseBuilderFile(f)
28 self.list.append((nm,f,cb.name(),cb.description()))
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
111 bounds=[]
112
113 for a in self.boundaryTree().getElementsByTagName("boundary"):
114 bounds.append((a.getAttribute("name"),a.getAttribute("pattern")))
115
116 return bounds
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("arg"):
136 args.append(a.getAttribute("name"))
137
138 return args
139
141 args={}
142
143 for a in self.argTree().getElementsByTagName("arg"):
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[a.getAttribute("name")]=a.getAttribute("default")
153
154 return args
155
157 """Get an element and check that it is the only one
158 @param parent: the parent element
159 @param name: The name of the element"""
160
161 tmp=parent.getElementsByTagName(name)
162 if len(tmp)<1:
163 if optional:
164 return None
165 else:
166 error("Element",name,"does not exist")
167 if len(tmp)>1:
168 error("More than one element",name,"does exist")
169 return tmp[0]
170
172 result="'type':'"+node.getAttribute("type")+"'"
173 para=self.expandVars(node.getAttribute("parameters"),args)
174 if para!="":
175 result+=","+para
176 return "{"+result+"}"
177
179 """Validate the arguments with the provided code (if it exists)"""
180 msg=None
181 for a in self.argTree().getElementsByTagName("arg"):
182 nm=a.getAttribute("name")
183 verify=self.getSingleElement(a,"verify",optional=True)
184 if verify:
185 code=verify.firstChild.nodeValue
186 arg=args[nm]
187 exec code
188 if msg:
189 msg=nm+": "+msg
190 break
191 return msg
192
194 """Add derived variables to the argument dictionary"""
195
196 for _a_ in _args_:
197 exec "%s = '%s'" % (_a_,_args_[_a_])
198
199 if self.varTree():
200 for _a_ in self.varTree().getElementsByTagName("var"):
201 _nm_=_a_.getAttribute("name")
202 if _nm_ in ["_args_","_a_","_nm_"]:
203 error("Variable",_nm_,"is needed for this routine to work")
204
205 if len(_a_.firstChild.nodeValue)>0:
206 exec _a_.firstChild.nodeValue
207 exec "_args_['"+_nm_+"']=str("+_nm_+")"
208
209 return _args_
210
212 """Builds the case
213 @param cName: The name of the case directory
214 @param args: The arguments (as a dictionary)"""
215
216 args=self.calculateVariables(args)
217
218 os.mkdir(cName)
219
220 for d in self.parameterTree().getElementsByTagName("directory"):
221 dName=path.join(cName,d.getAttribute("name"))
222 if not path.isdir(dName):
223 os.mkdir(dName)
224 sName=path.join(self.templatePath(),d.getAttribute("name"))
225 for f in d.getElementsByTagName("file"):
226 dFile=path.join(dName,f.getAttribute("name"))
227 shutil.copy(path.join(sName,f.getAttribute("name")),dFile)
228 if len(f.getElementsByTagName("parameter"))>0:
229 pf=ParsedParameterFile(dFile)
230 for p in f.getElementsByTagName("parameter"):
231 pName=p.getAttribute("name")
232 pValue=self.expandVars(p.getAttribute("value"),args)
233 exec "pf"+pName+"="+pValue
234 pf.writeFile()
235
236 prep=self.getSingleElement(self.doc,"meshpreparation")
237 mode=prep.getAttribute("mode")
238 if mode=="utility":
239 util=self.getSingleElement(prep,"utility")
240 app=util.getAttribute("application")
241 arg=self.expandVars(util.getAttribute("arguments"),args)
242 argv=[app,"-case",cName]+arg.split()
243 if oldApp():
244 argv[1]="."
245 run=BasicRunner(argv=argv,silent=True,logname="CaseBuilder.prepareMesh."+app)
246 run.start()
247 if not run.runOK():
248 error(app,"failed. Check the logs")
249 elif mode=="copy":
250 copy=self.getSingleElement(prep,"copy")
251 source=self.expandVars(copy.getAttribute("template"),args)
252 time=self.expandVars(copy.getAttribute("time"),args)
253 if time=="":
254 time="constant"
255 shutil.copytree(path.join(source,time,"polyMesh"),
256 path.join(cName,"constant","polyMesh"))
257 else:
258 error("Unknon mesh preparation mode:",mode)
259
260 dName=path.join(cName,self.initialDir())
261 if not path.isdir(dName):
262 os.mkdir(dName)
263 sName=path.join(self.templatePath(),self.initialDir())
264 for f in self.fieldTree().getElementsByTagName("field"):
265 dFile=path.join(dName,f.getAttribute("name"))
266 shutil.copy(path.join(sName,f.getAttribute("name")),dFile)
267 default=self.makeBC(self.getSingleElement(f,"defaultbc"),args)
268
269 CreateBoundaryPatches(args=["--fix-types",
270 "--overwrite",
271 "--clear",
272 "--default="+default,
273 dFile])
274 bcDict={}
275 bounds=self.boundaries()
276 for b in f.getElementsByTagName("bc"):
277 nm=b.getAttribute("name")
278 if nm not in bounds:
279 error("Boundary",nm,"not in list",bounds,"for field",f.getAttribute("name"))
280 bcDict[nm]=b
281
282 for name,pattern in self.boundaryPatterns():
283 if name in bcDict:
284 default=self.makeBC(bcDict[name],args)
285 CreateBoundaryPatches(args=["--filter="+pattern,
286 "--overwrite",
287 "--default="+default,
288 dFile])
289
290 ic=self.expandVars(self.getSingleElement(f,"ic").getAttribute("value"),args)
291 pf=ParsedParameterFile(dFile)
292 pf["internalField"]="uniform "+ic
293 pf.writeFile()
294