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

Source Code for Module PyFoam.Applications.CaseReport

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