Package PyFoam :: Package Applications :: Module CaseBuilderBackend
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Applications.CaseBuilderBackend

  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,warning 
 13  from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile,FoamStringParser 
 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  from PyFoam.Basics.DataStructures import Vector 
 19   
20 -class CaseBuilderDescriptionList(object):
21 """Gets a list of the case-builder files found in the current path"""
22 - def __init__(self):
23 dirList=config().get("CaseBuilder","descriptionpath") 24 self.list=[] 25 for d in dirList: 26 for f in glob.glob(path.join(d,"*.pfcb")): 27 nm=path.basename(f) 28 cb=CaseBuilderFile(f) 29 self.list.append((nm,f,cb.name(),cb.description()))
30
31 - def __iter__(self):
32 for f in self.list: 33 yield f
34
35 - def __len__(self):
36 return len(self.list)
37
38 - def __getitem__(self,i):
39 return self.list[i]
40
41 -class ArgWrapper(object):
42 """Wraps the argument element for convenient access"""
43 - def __init__(self,el):
44 self.el=el
45
46 - def __getattr__(self,name):
47 if name=="type": 48 tmp=self.el.getElementsByTagName("verify") 49 if len(tmp)!=1: 50 return None 51 val=tmp[0].getElementsByTagName("validator") 52 if len(val)!=1: 53 return None 54 else: 55 return val[0].getAttribute("type") 56 elif name=="values": 57 tmp=self.el.getElementsByTagName("verify") 58 if len(tmp)!=1: 59 return None 60 val=tmp[0].getElementsByTagName("validator") 61 if len(val)!=1: 62 return None 63 else: 64 return map(str,val[0].getAttribute("values").split("|")) 65 else: 66 return self.el.getAttribute(name)
67
68 -class CaseBuilderFile(object):
69 """ 70 This class reads an XML-file that describes how to build a case 71 and gives information about the case and if asked to builds the actual case 72 """ 73
74 - def __init__(self,fName):
75 """@param fName: the XML-file that describes how to build the case""" 76 77 dom=parse(fName) 78 self.doc=dom.documentElement 79 80 if self.doc.tagName!='casebuilder': 81 error("Wrong root-element",self.doc.tagName,"Expected: 'casebuilder'")
82
83 - def name(self):
84 return self.doc.getAttribute("name")
85
86 - def description(self):
87 return self.doc.getAttribute("description")
88
89 - def helpText(self):
90 ht=self.getSingleElement(self.doc,"helptext",optional=True) 91 if ht: 92 return ht.firstChild.nodeValue 93 else: 94 return "<No help text>"
95
96 - def argTree(self):
97 return self.getSingleElement(self.doc,"arguments")
98
99 - def varTree(self):
100 return self.getSingleElement(self.doc,"variables",optional=True)
101
102 - def filesTree(self):
103 return self.getSingleElement(self.doc,"files")
104
105 - def boundaryTree(self):
106 return self.getSingleElement(self.filesTree(),"boundaries")
107
108 - def fieldTree(self):
109 return self.getSingleElement(self.filesTree(),"fieldfiles")
110
111 - def parameterTree(self):
112 return self.getSingleElement(self.filesTree(),"parameterfiles")
113
114 - def templatePath(self):
115 return self.expandVars(self.doc.getAttribute("template"))
116
117 - def initialDir(self):
118 tmp=self.doc.getAttribute("initialdir") 119 if tmp=="": 120 tmp="0" 121 return tmp
122
123 - def expandVars(self,orig,keys=None):
124 orig=path.expanduser(orig) 125 orig=path.expandvars(orig) 126 if keys!=None: 127 orig=orig % keys 128 return orig
129
130 - def boundaries(self):
131 bounds=[] 132 133 for a in self.boundaryTree().getElementsByTagName("boundary"): 134 bounds.append(a.getAttribute("name")) 135 136 return bounds
137
138 - def boundaryPatterns(self):
139 bounds=[] 140 141 for a in self.boundaryTree().getElementsByTagName("boundary"): 142 bounds.append((a.getAttribute("name"),a.getAttribute("pattern"))) 143 144 return bounds
145
146 - def boundaryPatternDict(self):
147 res={} 148 for nm,pat in self.boundaryPatterns(): 149 res[nm]=pat 150 return res
151
152 - def boundaryDescriptions(self):
153 bounds={} 154 155 for a in self.boundaryTree().getElementsByTagName("boundary"): 156 bounds[a.getAttribute("name")]=a.getAttribute("description") 157 158 return bounds
159
160 - def argumentGroups(self):
161 args=[] 162 163 for a in self.argTree().getElementsByTagName("argumentgroup"): 164 args.append(a.getAttribute("name")) 165 166 return args
167
168 - def argumentGroupDescription(self):
169 args={} 170 171 for a in self.argTree().getElementsByTagName("argumentgroup"): 172 args[a.getAttribute("name")]=a.getAttribute("description") 173 174 return args
175
176 - def arguments(self):
177 args=[] 178 179 for a in self.argTree().getElementsByTagName("arg"): 180 args.append(a.getAttribute("name")) 181 182 return args
183
184 - def argumentDict(self):
185 args={} 186 187 for a in self.argTree().getElementsByTagName("arg"): 188 args[a.getAttribute("name")]=ArgWrapper(a) 189 190 return args
191
192 - def groupArguments(self,name=None):
193 """Returns a list with the arguments belongin to a specific group 194 @param name: Name of the group. If none is given, then all the arguments 195 belonging to no group are returned""" 196 197 result=[] 198 199 for c in self.argTree().childNodes: 200 if "tagName" in dir(c): 201 if c.tagName=="arg" and name==None: 202 result.append(c.getAttribute("name")) 203 elif c.tagName=="argumentgroup": 204 if c.getAttribute("name")==name: 205 for e in c.getElementsByTagName("arg"): 206 result.append(e.getAttribute("name")) 207 208 return result
209
210 - def argumentDescriptions(self):
211 args={} 212 213 for a in self.argTree().getElementsByTagName("arg"): 214 args[a.getAttribute("name")]=a.getAttribute("description") 215 216 return args
217
218 - def argumentDefaults(self):
219 args={} 220 221 for a in self.argTree().getElementsByTagName("arg"): 222 args[a.getAttribute("name")]=a.getAttribute("default") 223 224 return args
225
226 - def getSingleElement(self,parent,name,optional=False):
227 """Get an element and check that it is the only one 228 @param parent: the parent element 229 @param name: The name of the element""" 230 231 tmp=parent.getElementsByTagName(name) 232 if len(tmp)<1: 233 if optional: 234 return None 235 else: 236 error("Element",name,"does not exist") 237 if len(tmp)>1: 238 error("More than one element",name,"does exist") 239 return tmp[0]
240
241 - def makeBC(self,node,args):
242 result="'type':'"+node.getAttribute("type")+"'" 243 para=self.expandVars(node.getAttribute("parameters"),args) 244 if para!="": 245 result+=","+para 246 return "{"+result+"}"
247
248 - def verifyArguments(self,args):
249 """Validate the arguments with the provided code (if it exists)""" 250 totalMsg="" 251 for a in self.argTree().getElementsByTagName("arg"): 252 msg=None 253 nm=a.getAttribute("name") 254 verify=self.getSingleElement(a,"verify",optional=True) 255 if verify: 256 valid=self.getSingleElement(verify,"validator",optional=True) 257 script=self.getSingleElement(verify,"script",optional=True) 258 if valid and script: 259 error("Variable",nm,"has script and validator. Only one of them supported") 260 elif valid: 261 typ=valid.getAttribute("type") 262 arg=args[nm] 263 isNumeric=False 264 if typ=="float": 265 isNumeric=True 266 try: 267 tmp=float(arg) 268 except ValueError: 269 msg="Not a floating point number" 270 elif typ=="integer": 271 isNumeric=True 272 try: 273 tmp=int(arg) 274 except ValueError: 275 msg="Not an integer number" 276 elif typ=="file": 277 if not path.exists(arg): 278 msg="File "+arg+" does not exist" 279 elif typ=="selection": 280 vals=valid.getAttribute("values").split("|") 281 if not arg in vals: 282 msg="Not in list of possible values: "+", ".join(vals) 283 elif typ=="vector": 284 tmp=FoamStringParser("a "+arg+";") 285 if type(tmp['a'])!=Vector: 286 msg="Is not a valid vector" 287 else: 288 error("No validator implemented for type",typ,"in variable",nm) 289 if isNumeric and not msg: 290 if valid.hasAttribute("min"): 291 if float(arg)<float(valid.getAttribute("min")): 292 msg="Must be bigger than "+valid.getAttribute("min") 293 if valid.hasAttribute("max"): 294 if float(arg)>float(valid.getAttribute("max")): 295 msg="Must be smaller than "+valid.getAttribute("max") 296 297 elif script: 298 if script.getAttribute("plugin")!="python": 299 error("Only plugin-type 'python' is supported for variable",nm) 300 code=script.firstChild.nodeValue 301 arg=args[nm] 302 exec code 303 if msg: 304 totalMsg+=nm+": "+msg+" " 305 306 if totalMsg=="": 307 totalMsg=None 308 309 return totalMsg
310
311 - def calculateVariables(self,_args_):
312 """Add derived variables to the argument dictionary""" 313 314 for _a_ in _args_: 315 exec "%s = '%s'" % (_a_,_args_[_a_]) 316 317 if self.varTree(): 318 for _a_ in self.varTree().getElementsByTagName("var"): 319 _nm_=_a_.getAttribute("name") 320 if _nm_ in ["_args_","_a_","_nm_"]: 321 error("Variable",_nm_,"is needed for this routine to work") 322 323 if len(_a_.firstChild.nodeValue)>0: 324 exec _a_.firstChild.nodeValue 325 exec "_args_['"+_nm_+"']=str("+_nm_+")" 326 327 return _args_
328
329 - def buildCase(self,cName,args):
330 """Builds the case 331 @param cName: The name of the case directory 332 @param args: The arguments (as a dictionary)""" 333 334 args=self.calculateVariables(args) 335 336 os.mkdir(cName) 337 338 for d in self.parameterTree().getElementsByTagName("directory"): 339 dName=path.join(cName,d.getAttribute("name")) 340 if not path.isdir(dName): 341 os.mkdir(dName) 342 sName=path.join(self.templatePath(),d.getAttribute("name")) 343 for f in d.getElementsByTagName("file"): 344 dFile=path.join(dName,f.getAttribute("name")) 345 shutil.copy(path.join(sName,f.getAttribute("name")),dFile) 346 if len(f.getElementsByTagName("parameter"))>0: 347 pf=ParsedParameterFile(dFile) 348 for p in f.getElementsByTagName("parameter"): 349 pName=p.getAttribute("name") 350 pValue=self.expandVars(p.getAttribute("value"),args) 351 exec "pf"+pName+"="+pValue 352 pf.writeFile() 353 354 prep=self.getSingleElement(self.doc,"meshpreparation") 355 util=prep.getElementsByTagName("utility") 356 copy=self.getSingleElement(prep,"copy",optional=True) 357 358 if len(util)>0 and copy: 359 error("Copy and utilitiy mesh preparation specified") 360 elif len(util)>0: 361 for u in util: 362 app=u.getAttribute("command") 363 arg=self.expandVars(u.getAttribute("arguments"),args) 364 argv=[app,"-case",cName]+arg.split() 365 if oldApp(): 366 argv[1]="." 367 run=BasicRunner(argv=argv,silent=True,logname="CaseBuilder.prepareMesh."+app) 368 run.start() 369 if not run.runOK(): 370 error(app,"failed. Check the logs") 371 elif copy: 372 source=self.expandVars(copy.getAttribute("template"),args) 373 time=self.expandVars(copy.getAttribute("time"),args) 374 if time=="": 375 time="constant" 376 shutil.copytree(path.join(source,time,"polyMesh"), 377 path.join(cName,"constant","polyMesh")) 378 else: 379 error("Neither copy nor utilitiy mesh preparation specified") 380 381 dName=path.join(cName,self.initialDir()) 382 if not path.isdir(dName): 383 os.mkdir(dName) 384 sName=path.join(self.templatePath(),self.initialDir()) 385 for f in self.fieldTree().getElementsByTagName("field"): 386 dFile=path.join(dName,f.getAttribute("name")) 387 shutil.copy(path.join(sName,f.getAttribute("name")),dFile) 388 default=self.makeBC(self.getSingleElement(f,"defaultbc"),args) 389 390 CreateBoundaryPatches(args=["--fix-types", 391 "--overwrite", 392 "--clear", 393 "--default="+default, 394 dFile]) 395 bcDict={} 396 bounds=self.boundaries() 397 for b in f.getElementsByTagName("bc"): 398 nm=b.getAttribute("name") 399 if nm not in bounds: 400 error("Boundary",nm,"not in list",bounds,"for field",f.getAttribute("name")) 401 bcDict[nm]=b 402 403 for name,pattern in self.boundaryPatterns(): 404 if name in bcDict: 405 default=self.makeBC(bcDict[name],args) 406 CreateBoundaryPatches(args=["--filter="+pattern, 407 "--overwrite", 408 "--default="+default, 409 dFile]) 410 411 ic=self.expandVars(self.getSingleElement(f,"ic").getAttribute("value"),args) 412 pf=ParsedParameterFile(dFile) 413 pf["internalField"]="uniform "+ic 414 pf.writeFile()
415