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

Source Code for Module PyFoam.Applications.CaseReport

  1  #  ICE Revision: $Id: CaseReport.py 9422 2008-09-22 08:00:29Z 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 (nad 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],archive=None,paraviewLink=False,region=self.opts.region) 127 128 needsPolyBoundaries=False 129 needsInitialTime=False 130 131 if self.opts.longBCreport: 132 needsPolyBoundaries=True 133 needsInitialTime=True 134 if self.opts.shortBCreport: 135 needsPolyBoundaries=True 136 needsInitialTime=True 137 if self.opts.dimensions: 138 needsInitialTime=True 139 if self.opts.internal: 140 needsInitialTime=True 141 if self.opts.decomposition: 142 needsPolyBoundaries=True 143 144 if needsPolyBoundaries: 145 boundary=BoundaryDict(sol.name,region=self.opts.region) 146 147 boundMaxLen=0 148 boundaryNames=[] 149 for b in boundary: 150 boundaryNames.append(b) 151 152 if self.opts.patches!=None: 153 tmp=boundaryNames 154 boundaryNames=[] 155 for b in tmp: 156 for p in self.opts.patches: 157 if fnmatch(b,p): 158 boundaryNames.append(b) 159 break 160 161 if self.opts.expatches!=None: 162 tmp=boundaryNames 163 boundaryNames=[] 164 for b in tmp: 165 keep=True 166 for p in self.opts.expatches: 167 if fnmatch(b,p): 168 keep=False 169 break 170 if keep: 171 boundaryNames.append(b) 172 173 for b in boundaryNames: 174 boundMaxLen=max(boundMaxLen,len(b)) 175 boundaryNames.sort() 176 177 if self.opts.time==None: 178 procTime="constant" 179 else: 180 procTime=sol.timeName(sol.timeIndex(self.opts.time,minTime=True)) 181 182 if needsInitialTime: 183 fields={} 184 185 if self.opts.time==None: 186 time=sol.timeName(0) 187 else: 188 time=sol.timeName(sol.timeIndex(self.opts.time,minTime=True)) 189 190 # print "Using time: ",time 191 192 tDir=sol[time] 193 194 nameMaxLen=0 195 196 for f in tDir: 197 try: 198 fields[f.baseName()]=f.getContent(listLengthUnparsed=self.opts.longlist) 199 nameMaxLen=max(nameMaxLen,len(f.baseName())) 200 except PyFoamParserError,e: 201 warning("Couldn't parse",f.name,"because of an error:",e," -> skipping") 202 203 fieldNames=fields.keys() 204 fieldNames.sort() 205 206 if self.opts.caseSize: 207 print "Size of the case" 208 print 209 info=MeshInformation(sol.name) 210 print "Faces: \t",info.nrOfFaces() 211 print "Points: \t",info.nrOfPoints() 212 try: 213 print "Cells: \t",info.nrOfCells() 214 except: 215 print "Not available" 216 217 if self.opts.decomposition: 218 if sol.nrProcs()<2: 219 error("The case is not decomposed") 220 print "Case is decomposed for",sol.nrProcs(),"processors" 221 222 nCells=[] 223 nFaces=[] 224 nPoints=[] 225 for p in sol.processorDirs(): 226 info=MeshInformation(sol.name,processor=p) 227 nPoints.append(info.nrOfPoints()) 228 nFaces.append(info.nrOfFaces()) 229 nCells.append(info.nrOfCells()) 230 231 digits=int(ceil(log10(max(sol.nrProcs(), 232 max(nCells), 233 max(nFaces), 234 max(nPoints) 235 ))))+2 236 nameLen=max(len("Points"),boundMaxLen) 237 238 nrFormat ="%%%dd" % digits 239 nameFormat="%%%ds" % nameLen 240 241 print " "*nameLen,"|", 242 for i in range(sol.nrProcs()): 243 print nrFormat % i, 244 print 245 246 print "-"*(nameLen+3+(digits+1)*sol.nrProcs()) 247 248 print nameFormat % "Points","|", 249 for p in nPoints: 250 print nrFormat % p, 251 print 252 print nameFormat % "Faces","|", 253 for p in nFaces: 254 print nrFormat % p, 255 print 256 print nameFormat % "Cells","|", 257 for p in nCells: 258 print nrFormat % p, 259 print 260 261 print "-"*(nameLen+3+(digits+1)*sol.nrProcs()) 262 263 for b in boundaryNames: 264 print nameFormat % b,"|", 265 for p in sol.processorDirs(): 266 print nrFormat % ParsedBoundaryDict(sol.boundaryDict(processor=p))[b]["nFaces"], 267 print 268 269 if self.opts.longBCreport: 270 print "\nThe boundary conditions for t =",time 271 272 for b in boundaryNames: 273 print "\nBoundary: \t",b 274 bound=boundary[b] 275 print " type:\t",bound["type"], 276 if "physicalType" in bound: 277 print "( Physical:",bound["physicalType"],")", 278 print " \t Faces:",bound["nFaces"] 279 for fName in fieldNames: 280 print " ",fName, 281 f=fields[fName] 282 if b not in f["boundaryField"]: 283 print " "*(nameMaxLen-len(fName)+2)+": MISSING !!!" 284 else: 285 bf=f["boundaryField"][b] 286 maxKeyLen=0 287 for k in bf: 288 maxKeyLen=max(maxKeyLen,len(k)) 289 290 print " "*(nameMaxLen-len(fName)+2)+"type "+" "*(maxKeyLen-4)+": ",bf["type"] 291 for k in bf: 292 if k!="type": 293 print " "*(nameMaxLen+6),k," "*(maxKeyLen-len(k))+": ", 294 cont=str(bf[k]) 295 if cont.find("\n")>=0: 296 print cont[:cont.find("\n")],"..." 297 else: 298 print cont 299 300 if self.opts.shortBCreport: 301 print "\nTable of boundary conditions for t =",time 302 print 303 304 colLen = {} 305 types={} 306 hasPhysical=False 307 nameMaxLen=max(nameMaxLen,len("Patch Type")) 308 for b in boundary: 309 colLen[b]=max(len(b),len(boundary[b]["type"])) 310 colLen[b]=max(len(b),len(str(boundary[b]["nFaces"]))) 311 if "physicalType" in boundary[b]: 312 hasPhysical=True 313 nameMaxLen=max(nameMaxLen,len("Physical Type")) 314 colLen[b]=max(colLen[b],len(boundary[b]["physicalType"])) 315 316 types[b]={} 317 318 for fName in fields: 319 f=fields[fName] 320 if b not in f["boundaryField"]: 321 types[b][fName]="MISSING" 322 else: 323 types[b][fName]=f["boundaryField"][b]["type"] 324 colLen[b]=max(colLen[b],len(types[b][fName])) 325 326 print " "*(nameMaxLen), 327 nr=nameMaxLen+1 328 for b in boundaryNames: 329 print "| "+b+" "*(colLen[b]-len(b)), 330 nr+=colLen[b]+3 331 print 332 print "-"*nr 333 print "Patch Type"+" "*(nameMaxLen-len("Patch Type")), 334 for b in boundaryNames: 335 t=boundary[b]["type"] 336 print "| "+t+" "*(colLen[b]-len(t)), 337 print 338 if hasPhysical: 339 print "Physical Type"+" "*(nameMaxLen-len("Physical Type")), 340 for b in boundaryNames: 341 t="" 342 if "physicalType" in boundary[b]: 343 t=boundary[b]["physicalType"] 344 print "| "+t+" "*(colLen[b]-len(t)), 345 print 346 print "Length"+" "*(nameMaxLen-len("Length")), 347 for b in boundaryNames: 348 s=str(boundary[b]["nFaces"]) 349 print "| "+s+" "*(colLen[b]-len(s)), 350 print 351 print "-"*nr 352 for fName in fieldNames: 353 print fName+" "*(nameMaxLen-len(fName)), 354 for b in boundaryNames: 355 t=types[b][fName] 356 print "| "+t+" "*(colLen[b]-len(t)), 357 print 358 359 print 360 361 if self.opts.dimensions: 362 print "\nDimensions of fields for t =",time 363 print 364 365 head="Name"+" "*(nameMaxLen-len("Name"))+" : [kg m s K mol A cd]" 366 print head 367 print "-"*len(head) 368 for fName in fieldNames: 369 f=fields[fName] 370 371 print fName+" "*(nameMaxLen-len(fName))+" :",f["dimensions"] 372 373 if self.opts.internal: 374 print "\Internal value of fields for t =",time 375 print 376 377 head="Name"+" "*(nameMaxLen-len("Name"))+" : Value " 378 print head 379 print "-"*len(head) 380 for fName in fieldNames: 381 f=fields[fName] 382 383 print fName+" "*(nameMaxLen-len(fName))+" :", 384 385 cont=str(f["internalField"]) 386 if cont.find("\n")>=0: 387 print cont[:cont.find("\n")],"..." 388 else: 389 print cont 390 391 if self.opts.processorMatrix: 392 if sol.nrProcs()<2: 393 error("The case is not decomposed") 394 395 matrix=[ [0,]*sol.nrProcs() for i in range(sol.nrProcs())] 396 397 for i,p in enumerate(sol.processorDirs()): 398 bound=ParsedBoundaryDict(path.join(sol.name,p,procTime,"polyMesh","boundary")) 399 for j in range(sol.nrProcs()): 400 name="procBoundary%dto%d" %(i,j) 401 if name in bound: 402 matrix[i][j]=bound[name]["nFaces"] 403 404 print "Matrix of processor interactions (faces)" 405 print 406 407 digits=int(ceil(log10(sol.nrProcs())))+2 408 colDigits=int(ceil(log10(max(digits,max(max(matrix))))))+2 409 410 format="%%%dd" % digits 411 colFormat="%%%dd" % colDigits 412 413 print " "*(digits),"|", 414 for j in range(sol.nrProcs()): 415 print colFormat % j, 416 print 417 print "-"*(digits+3+(colDigits+1)*sol.nrProcs()) 418 419 for i,col in enumerate(matrix): 420 print format % i,"|", 421 for j,nr in enumerate(col): 422 print colFormat % matrix[i][j], 423 print
424