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

Source Code for Module PyFoam.Applications.CaseReport

  1  #  ICE Revision: $Id: CaseReport.py 10621 2009-07-21 18:46:20Z bgschaid $  
  2  """ 
  3  Application class that implements pyFoamCasedReport.py 
  4  """ 
  5   
  6  import sys,string 
  7  from optparse import OptionGroup 
  8   
  9  from fnmatch import fnmatch 
 10   
 11  from PyFoamApplication import PyFoamApplication 
 12  from PyFoam.RunDictionary.SolutionDirectory import SolutionDirectory 
 13  from PyFoam.RunDictionary.BoundaryDict import BoundaryDict 
 14  from PyFoam.RunDictionary.MeshInformation import MeshInformation 
 15  from PyFoam.RunDictionary.ParsedParameterFile import PyFoamParserError,ParsedBoundaryDict 
 16   
 17  from PyFoam.Error import error,warning 
 18   
 19  from math import log10,ceil 
 20  from os import path 
 21   
22 -class CaseReport(PyFoamApplication):
23 - def __init__(self,args=None):
24 description=""" 25 Produces human-readable reports about a case. Attention: the amount of 26 information in the reports is limited. The truth is always in the 27 dictionary-files 28 """ 29 30 PyFoamApplication.__init__(self, 31 args=args, 32 description=description, 33 usage="%prog [options] <casedir>", 34 nr=1, 35 changeVersion=False, 36 interspersed=True)
37
38 - def addOptions(self):
39 report=OptionGroup(self.parser, 40 "Reports", 41 "What kind of reports should be produced") 42 self.parser.add_option_group(report) 43 select=OptionGroup(self.parser, 44 "Selection", 45 "Which data should be used for the reports") 46 self.parser.add_option_group(select) 47 internal=OptionGroup(self.parser, 48 "Internal", 49 "Details of the parser") 50 self.parser.add_option_group(internal) 51 52 report.add_option("--short-bc-report", 53 action="store_true", 54 default=False, 55 dest="shortBCreport", 56 help="Gives a short overview of the boundary-conditions in the case") 57 58 report.add_option("--long-bc-report", 59 action="store_true", 60 default=False, 61 dest="longBCreport", 62 help="Gives a full overview of the boundary-conditions in the case") 63 64 report.add_option("--dimensions", 65 action="store_true", 66 default=False, 67 dest="dimensions", 68 help="Show the dimensions of the fields") 69 70 report.add_option("--internal-field", 71 action="store_true", 72 default=False, 73 dest="internal", 74 help="Show the internal value of the fields (the initial conditions)") 75 76 select.add_option("--time", 77 action="store", 78 type="float", 79 default=None, 80 dest="time", 81 help="Time to use as the basis for the reports") 82 83 select.add_option("--region", 84 dest="region", 85 default=None, 86 help="Do the report for a special region for multi-region cases") 87 88 internal.add_option("--long-field-threshold", 89 action="store", 90 type="int", 91 default=100, 92 dest="longlist", 93 help="Fields that are longer than this won't be parsed, but read into memory (and compared as strings)") 94 95 select.add_option("--patches", 96 action="append", 97 default=None, 98 dest="patches", 99 help="Patches which should be processed (pattern, can be used more than once)") 100 101 select.add_option("--exclude-patches", 102 action="append", 103 default=None, 104 dest="expatches", 105 help="Patches which should not be processed (pattern, can be used more than once)") 106 107 report.add_option("--processor-matrix", 108 action="store_true", 109 default=False, 110 dest="processorMatrix", 111 help="Prints the matrix how many faces from one processor interact with another") 112 113 report.add_option("--case-size", 114 action="store_true", 115 default=False, 116 dest="caseSize", 117 help="Report the number of cells, points and faces in the case") 118 119 report.add_option("--decomposition", 120 action="store_true", 121 default=False, 122 dest="decomposition", 123 help="Reports the size of the parallel decomposition")
124
125 - def run(self):
126 sol=SolutionDirectory(self.parser.getArgs()[0], 127 archive=None, 128 paraviewLink=False, 129 region=self.opts.region) 130 131 needsPolyBoundaries=False 132 needsInitialTime=False 133 134 if self.opts.longBCreport: 135 needsPolyBoundaries=True 136 needsInitialTime=True 137 if self.opts.shortBCreport: 138 needsPolyBoundaries=True 139 needsInitialTime=True 140 if self.opts.dimensions: 141 needsInitialTime=True 142 if self.opts.internal: 143 needsInitialTime=True 144 if self.opts.decomposition: 145 needsPolyBoundaries=True 146 147 if needsPolyBoundaries: 148 boundary=BoundaryDict(sol.name,region=self.opts.region) 149 150 boundMaxLen=0 151 boundaryNames=[] 152 for b in boundary: 153 boundaryNames.append(b) 154 155 if self.opts.patches!=None: 156 tmp=boundaryNames 157 boundaryNames=[] 158 for b in tmp: 159 for p in self.opts.patches: 160 if fnmatch(b,p): 161 boundaryNames.append(b) 162 break 163 164 if self.opts.expatches!=None: 165 tmp=boundaryNames 166 boundaryNames=[] 167 for b in tmp: 168 keep=True 169 for p in self.opts.expatches: 170 if fnmatch(b,p): 171 keep=False 172 break 173 if keep: 174 boundaryNames.append(b) 175 176 for b in boundaryNames: 177 boundMaxLen=max(boundMaxLen,len(b)) 178 boundaryNames.sort() 179 180 if self.opts.time==None: 181 procTime="constant" 182 else: 183 try: 184 procTime=sol.timeName(sol.timeIndex(self.opts.time,minTime=True)) 185 except IndexError: 186 error("The specified time",self.opts.time,"doesn't exist in the case") 187 188 if needsInitialTime: 189 fields={} 190 191 if self.opts.time==None: 192 try: 193 time=sol.timeName(0) 194 except IndexError: 195 error("There is no timestep in the case") 196 else: 197 try: 198 time=sol.timeName(sol.timeIndex(self.opts.time,minTime=True)) 199 except IndexError: 200 error("The specified time",self.opts.time,"doesn't exist in the case") 201 # print "Using time: ",time 202 203 tDir=sol[time] 204 205 nameMaxLen=0 206 207 for f in tDir: 208 try: 209 fields[f.baseName()]=f.getContent(listLengthUnparsed=self.opts.longlist) 210 nameMaxLen=max(nameMaxLen,len(f.baseName())) 211 except PyFoamParserError,e: 212 warning("Couldn't parse",f.name,"because of an error:",e," -> skipping") 213 214 fieldNames=fields.keys() 215 fieldNames.sort() 216 217 if self.opts.caseSize: 218 print "Size of the case" 219 print 220 info=MeshInformation(sol.name) 221 print "Faces: \t",info.nrOfFaces() 222 print "Points: \t",info.nrOfPoints() 223 try: 224 print "Cells: \t",info.nrOfCells() 225 except: 226 print "Not available" 227 228 if self.opts.decomposition: 229 if sol.nrProcs()<2: 230 error("The case is not decomposed") 231 print "Case is decomposed for",sol.nrProcs(),"processors" 232 233 nCells=[] 234 nFaces=[] 235 nPoints=[] 236 for p in sol.processorDirs(): 237 info=MeshInformation(sol.name,processor=p) 238 nPoints.append(info.nrOfPoints()) 239 nFaces.append(info.nrOfFaces()) 240 nCells.append(info.nrOfCells()) 241 242 digits=int(ceil(log10(max(sol.nrProcs(), 243 max(nCells), 244 max(nFaces), 245 max(nPoints) 246 ))))+2 247 nameLen=max(len("Points"),boundMaxLen) 248 249 nrFormat ="%%%dd" % digits 250 nameFormat="%%%ds" % nameLen 251 252 print " "*nameLen,"|", 253 for i in range(sol.nrProcs()): 254 print nrFormat % i, 255 print 256 257 print "-"*(nameLen+3+(digits+1)*sol.nrProcs()) 258 259 print nameFormat % "Points","|", 260 for p in nPoints: 261 print nrFormat % p, 262 print 263 print nameFormat % "Faces","|", 264 for p in nFaces: 265 print nrFormat % p, 266 print 267 print nameFormat % "Cells","|", 268 for p in nCells: 269 print nrFormat % p, 270 print 271 272 print "-"*(nameLen+3+(digits+1)*sol.nrProcs()) 273 274 for b in boundaryNames: 275 print nameFormat % b,"|", 276 for p in sol.processorDirs(): 277 print nrFormat % ParsedBoundaryDict(sol.boundaryDict(processor=p))[b]["nFaces"], 278 print 279 280 if self.opts.longBCreport: 281 print "\nThe boundary conditions for t =",time 282 283 for b in boundaryNames: 284 print "\nBoundary: \t",b 285 bound=boundary[b] 286 print " type:\t",bound["type"], 287 if "physicalType" in bound: 288 print "( Physical:",bound["physicalType"],")", 289 print " \t Faces:",bound["nFaces"] 290 for fName in fieldNames: 291 print " ",fName, 292 f=fields[fName] 293 if b not in f["boundaryField"]: 294 print " "*(nameMaxLen-len(fName)+2)+": MISSING !!!" 295 else: 296 bf=f["boundaryField"][b] 297 maxKeyLen=0 298 for k in bf: 299 maxKeyLen=max(maxKeyLen,len(k)) 300 301 print " "*(nameMaxLen-len(fName)+2)+"type "+" "*(maxKeyLen-4)+": ",bf["type"] 302 for k in bf: 303 if k!="type": 304 print " "*(nameMaxLen+6),k," "*(maxKeyLen-len(k))+": ", 305 cont=str(bf[k]) 306 if cont.find("\n")>=0: 307 print cont[:cont.find("\n")],"..." 308 else: 309 print cont 310 311 if self.opts.shortBCreport: 312 print "\nTable of boundary conditions for t =",time 313 print 314 315 colLen = {} 316 types={} 317 hasPhysical=False 318 nameMaxLen=max(nameMaxLen,len("Patch Type")) 319 for b in boundary: 320 colLen[b]=max(len(b),len(boundary[b]["type"])) 321 colLen[b]=max(len(b),len(str(boundary[b]["nFaces"]))) 322 if "physicalType" in boundary[b]: 323 hasPhysical=True 324 nameMaxLen=max(nameMaxLen,len("Physical Type")) 325 colLen[b]=max(colLen[b],len(boundary[b]["physicalType"])) 326 327 types[b]={} 328 329 for fName in fields: 330 f=fields[fName] 331 if b not in f["boundaryField"]: 332 types[b][fName]="MISSING" 333 else: 334 types[b][fName]=f["boundaryField"][b]["type"] 335 colLen[b]=max(colLen[b],len(types[b][fName])) 336 337 print " "*(nameMaxLen), 338 nr=nameMaxLen+1 339 for b in boundaryNames: 340 print "| "+b+" "*(colLen[b]-len(b)), 341 nr+=colLen[b]+3 342 print 343 print "-"*nr 344 print "Patch Type"+" "*(nameMaxLen-len("Patch Type")), 345 for b in boundaryNames: 346 t=boundary[b]["type"] 347 print "| "+t+" "*(colLen[b]-len(t)), 348 print 349 if hasPhysical: 350 print "Physical Type"+" "*(nameMaxLen-len("Physical Type")), 351 for b in boundaryNames: 352 t="" 353 if "physicalType" in boundary[b]: 354 t=boundary[b]["physicalType"] 355 print "| "+t+" "*(colLen[b]-len(t)), 356 print 357 print "Length"+" "*(nameMaxLen-len("Length")), 358 for b in boundaryNames: 359 s=str(boundary[b]["nFaces"]) 360 print "| "+s+" "*(colLen[b]-len(s)), 361 print 362 print "-"*nr 363 for fName in fieldNames: 364 print fName+" "*(nameMaxLen-len(fName)), 365 for b in boundaryNames: 366 t=types[b][fName] 367 print "| "+t+" "*(colLen[b]-len(t)), 368 print 369 370 print 371 372 if self.opts.dimensions: 373 print "\nDimensions of fields for t =",time 374 print 375 376 head="Name"+" "*(nameMaxLen-len("Name"))+" : [kg m s K mol A cd]" 377 print head 378 print "-"*len(head) 379 for fName in fieldNames: 380 f=fields[fName] 381 382 print fName+" "*(nameMaxLen-len(fName))+" :",f["dimensions"] 383 384 if self.opts.internal: 385 print "\Internal value of fields for t =",time 386 print 387 388 head="Name"+" "*(nameMaxLen-len("Name"))+" : Value " 389 print head 390 print "-"*len(head) 391 for fName in fieldNames: 392 f=fields[fName] 393 394 print fName+" "*(nameMaxLen-len(fName))+" :", 395 396 cont=str(f["internalField"]) 397 if cont.find("\n")>=0: 398 print cont[:cont.find("\n")],"..." 399 else: 400 print cont 401 402 if self.opts.processorMatrix: 403 if sol.nrProcs()<2: 404 error("The case is not decomposed") 405 406 matrix=[ [0,]*sol.nrProcs() for i in range(sol.nrProcs())] 407 408 for i,p in enumerate(sol.processorDirs()): 409 bound=ParsedBoundaryDict(path.join(sol.name,p,procTime,"polyMesh","boundary")) 410 for j in range(sol.nrProcs()): 411 name="procBoundary%dto%d" %(j,i) 412 name2="procBoundary%dto%d" %(i,j) 413 if name in bound: 414 matrix[i][j]=bound[name]["nFaces"] 415 if name2 in bound: 416 matrix[i][j]=bound[name2]["nFaces"] 417 418 print "Matrix of processor interactions (faces)" 419 print 420 421 digits=int(ceil(log10(sol.nrProcs())))+2 422 colDigits=int(ceil(log10(max(digits,max(max(matrix))))))+2 423 424 format="%%%dd" % digits 425 colFormat="%%%dd" % colDigits 426 427 print " "*(digits),"|", 428 for j in range(sol.nrProcs()): 429 print colFormat % j, 430 print 431 print "-"*(digits+3+(colDigits+1)*sol.nrProcs()) 432 433 for i,col in enumerate(matrix): 434 print format % i,"|", 435 for j,nr in enumerate(col): 436 print colFormat % matrix[i][j], 437 print
438