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

Source Code for Module PyFoam.Applications.RunParameterVariation

  1  #  ICE Revision: $Id$ 
  2  """ 
  3  Application class that implements pyFoamPrepareCase 
  4  """ 
  5   
  6  from optparse import OptionGroup 
  7  from os import path 
  8   
  9  from .PrepareCase import PrepareCase 
 10   
 11  from PyFoam.Execution.AnalyzedRunner import AnalyzedRunner 
 12  from PyFoam.LogAnalysis.BoundingLogAnalyzer import BoundingLogAnalyzer 
 13  from PyFoam.RunDictionary.SolutionDirectory import SolutionDirectory 
 14  from PyFoam.RunDictionary.RegionCases import RegionCases 
 15  from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile 
 16  try: 
 17      from PyFoam.Basics.RunDatabase import RunDatabase 
 18      hasDatabase=True 
 19  except ImportError: 
 20      hasDatabase=False 
 21   
 22  from PyFoam.Error import warning 
 23   
 24  from .CommonPlotLines import CommonPlotLines 
 25  from .CommonReportUsage import CommonReportUsage 
 26  from .CommonReportRunnerData import CommonReportRunnerData 
 27  from .CommonStandardOutput import CommonStandardOutput 
 28  from .CommonParallel import CommonParallel 
 29  from .CommonServer import CommonServer 
 30  from .CommonPrePostHooks import CommonPrePostHooks 
 31   
 32  from PyFoam.Basics.CustomPlotInfo import resetCustomCounter 
 33  from PyFoam.Basics.TimeLineCollection import allLines 
 34  from PyFoam.Basics.GeneralPlotTimelines import allPlots 
 35   
 36  from PyFoam.ThirdParty.six import print_ 
 37   
38 -class RunParameterVariation(PrepareCase, 39 CommonPlotLines, 40 CommonReportUsage, 41 CommonReportRunnerData, 42 CommonParallel, 43 CommonServer, 44 CommonStandardOutput, 45 CommonPrePostHooks):
46 - def __init__(self, 47 args=None, 48 **kwargs):
49 description="""\ 50 Takes a template case and a file that specifies the parameters to be varied. 51 Using the machinery from pyFoamPrepareCase.py it sets up the case with each 52 parameters and runs the solver on it. Collects the results in a database 53 """ 54 55 examples="""\ 56 Do all the variations in the template case: 57 58 %prog --inplace-execution templateCase parameter.file 59 60 One case for every variation and start with the 4th variant 61 62 %prog --every-variant-one-case-execution templateCase parameter.file --start=4 63 """ 64 CommonPlotLines.__init__(self) 65 PrepareCase.__init__(self, 66 nr=2, 67 usage="%prog <case> <parameterFile>", 68 exactNr=True, 69 args=args, 70 interspersed=True, 71 description=description, 72 examples=examples, 73 **kwargs)
74
75 - def addOptions(self):
76 CommonReportUsage.addOptions(self) 77 CommonReportRunnerData.addOptions(self) 78 CommonStandardOutput.addOptions(self) 79 CommonParallel.addOptions(self) 80 CommonPlotLines.addOptions(self) 81 CommonServer.addOptions(self) 82 CommonPrePostHooks.addOptions(self) 83 84 PrepareCase.addOptions(self) 85 86 variation=OptionGroup(self.parser, 87 "Parameter variation", 88 "Parameters specific to the parameter variation") 89 self.parser.add_option_group(variation) 90 91 variation.add_option("--inplace-execution", 92 action="store_true", 93 dest="inplaceExecution", 94 default=False, 95 help="Do everything in the template case (preparation and execution)") 96 variation.add_option("--one-cloned-case-execution", 97 action="store_true", 98 dest="oneClonedCase", 99 default=False, 100 help="Clone to one case and do everything in that case (preparation and execution)") 101 variation.add_option("--every-variant-one-case-execution", 102 action="store_true", 103 dest="everyVariantOneCase", 104 default=False, 105 help="Every variation gets its own case (that is not erased)") 106 variation.add_option("--no-execute-solver", 107 action="store_true", 108 dest="noExecuteSolver", 109 default=False, 110 help="Only prepare the cases but do not execute the solver") 111 variation.add_option("--cloned-case-prefix", 112 action="store", 113 dest="clonedCasePrefix", 114 default=None, 115 help="Prefix of the cloned cases. If unspecified the name of parameter file is used") 116 variation.add_option("--clone-to-directory", 117 action="store", 118 dest="cloneToDirectory", 119 default=None, 120 help="Directory to clone to. If unspecified use the directory in which the original case resides") 121 variation.add_option("--single-variation", 122 action="store", 123 type="int", 124 dest="singleVariation", 125 default=None, 126 help="Single variation to run") 127 variation.add_option("--start-variation-number", 128 action="store", 129 type="int", 130 dest="startVariation", 131 default=None, 132 help="Variation number to start with") 133 variation.add_option("--end-variation-number", 134 action="store", 135 type="int", 136 dest="endVariation", 137 default=None, 138 help="Variation number to end with") 139 variation.add_option("--database", 140 action="store", 141 dest="database", 142 default=None, 143 help="Path to the database. If unset the name of parameter-file appended with '.results' will be used") 144 variation.add_option("--create-database", 145 action="store_true", 146 dest="createDatabase", 147 default=False, 148 help="Create a new database file. Fail if it already exists") 149 variation.add_option("--auto-create-database", 150 action="store_true", 151 dest="autoCreateDatabase", 152 default=False, 153 help="Create a new database file if it doesn't exist yet'") 154 variation.add_option("--list-variations", 155 action="store_true", 156 dest="listVariations", 157 default=False, 158 help="List the selected variations but don't do anything") 159 variation.add_option("--no-database-write", 160 action="store_true", 161 dest="noDatabaseWrite", 162 default=False, 163 help="Do not write to the database")
164
165 - def printPhase(self,*args):
166 out=" ".join([str(a) for a in args]) 167 print_() 168 print_("="*len(out)) 169 print_(out) 170 print_("="*len(out)) 171 print_()
172
173 - def run(self):
174 origPath=self.parser.getArgs()[0] 175 parameterFile=self.parser.getArgs()[1] 176 177 self.addLocalConfig(origPath) 178 self.checkCase(origPath) 179 180 nrModes=(1 if self.opts.inplaceExecution else 0) + \ 181 (1 if self.opts.oneClonedCase else 0) + \ 182 (1 if self.opts.listVariations else 0) + \ 183 (1 if self.opts.everyVariantOneCase else 0) 184 if nrModes==0: 185 self.error("Specify one of the modes --list-variations, --inplace-execution, --one-cloned-case-execution or --every-variant-one-case-execution") 186 elif nrModes>1: 187 self.error("The modes --list-variations, --inplace-execution, --one-cloned-case-execution or --every-variant-one-case-execution are mutual exclusive") 188 if self.opts.noExecuteSolver: 189 if not self.opts.everyVariantOneCase and self.opts.singleVariation==None and not self.opts.listVariations: 190 self.error("--no-execute-solver only works with --every-variant-one-case-execution") 191 192 if not self.opts.clonedCasePrefix: 193 self.opts.clonedCasePrefix=path.basename(parameterFile) 194 if not self.opts.cloneToDirectory: 195 self.opts.cloneToDirectory=path.dirname(path.abspath(origPath)) 196 if not self.opts.database: 197 self.opts.database=parameterFile+".database" 198 199 variationData=ParsedParameterFile(parameterFile, 200 noHeader=True, 201 noVectorOrTensor=True) 202 if not "values" in variationData: 203 self.error("Entry 'values' (dictionary) needed in",parameterFile) 204 if not "solver" in variationData["values"]: 205 self.error("Entry 'solver' (list or string) needed in 'values' in",parameterFile) 206 207 fixed={} 208 varied=[] 209 nrVariations=1 210 211 for k in variationData["values"]: 212 v=variationData["values"][k] 213 if type(v)!=list: 214 self.error("Entry",k,"is not a list") 215 if len(v)==1: 216 fixed[k]=v[0] 217 elif len(v)>1: 218 varied.append((k,v)) 219 nrVariations*=len(v) 220 else: 221 self.warning("Entry",k,"is empty") 222 223 if len(varied)==0: 224 self.error("No parameters to vary") 225 226 self.printPhase(nrVariations,"variations with",len(varied),"parameters") 227 228 def makeVariations(vList): 229 name,vals=vList[0] 230 if len(vList)>1: 231 var=makeVariations(vList[1:]) 232 variation=[] 233 for orig in var: 234 for v in vals: 235 d=orig.copy() 236 d[name]=v 237 variation.append(d) 238 return variation 239 else: 240 return [{name:v} for v in vals]
241 242 variations=makeVariations(varied) 243 self["variations"]=variations 244 self["fixed"]=fixed 245 246 if self.opts.startVariation!=None: 247 start=self.opts.startVariation 248 else: 249 start=0 250 if self.opts.endVariation!=None: 251 end=self.opts.endVariation 252 if end>=len(variations): 253 end=len(variations)-1 254 else: 255 end=len(variations)-1 256 257 if self.opts.singleVariation!=None: 258 if self.opts.startVariation or self.opts.endVariation: 259 self.error("--single-variation not possible with --end-variation-number or --start-variation-number") 260 if self.opts.singleVariation<0: 261 self.error("--single-variation must be greater or equal to 0") 262 if self.opts.singleVariation>=len(variations): 263 self.error("Only",len(variations)) 264 start=self.opts.singleVariation 265 end =self.opts.singleVariation 266 267 if end<start: 268 self.error("Start value",start,"bigger than end value",end) 269 270 if self.opts.listVariations: 271 self.printPhase("Listing variations") 272 for i in range(start,end+1): 273 print_("Variation",i,":",variations[i]) 274 return 275 276 if not hasDatabase or self.opts.noDatabaseWrite: 277 if path.exists(self.opts.database) and self.opts.createDatabase: 278 self.error("database-file",self.opts.database,"exists already.") 279 elif not path.exists(self.opts.database) and not self.opts.createDatabase and not self.opts.autoCreateDatabase: 280 self.error("database-file",self.opts.database,"does not exist") 281 282 createDatabase=self.opts.createDatabase 283 if self.opts.autoCreateDatabase and not path.exists(self.opts.database): 284 createDatabase=True 285 286 if not hasDatabase or self.opts.noDatabaseWrite: 287 db=None 288 else: 289 db=RunDatabase(self.opts.database, 290 create=createDatabase, 291 verbose=self.opts.verbose) 292 293 origCase=SolutionDirectory(origPath,archive=None) 294 if self.opts.oneClonedCase: 295 self.printPhase("Cloning work case") 296 workCase=origCase.cloneCase(path.join(self.opts.cloneToDirectory, 297 self.opts.clonedCasePrefix+"_"+path.basename(origPath))) 298 299 self.printPhase("Starting actual variations") 300 301 for i in range(start,end+1): 302 self.printPhase("Variation",i,"of [",start,",",end,"]") 303 304 usedVals=variations[i].copy() 305 usedVals.update(fixed) 306 307 self.prepareHooks() 308 309 clone=False 310 if self.opts.inplaceExecution: 311 workCase=origCase 312 elif self.opts.oneClonedCase: 313 pass 314 else: 315 self.printPhase("Cloning work case") 316 workCase=origCase.cloneCase(path.join(self.opts.cloneToDirectory, 317 self.opts.clonedCasePrefix+"_"+ 318 ("%05d" % i)+"_"+path.basename(origPath))) 319 320 self.processPlotLineOptions(autoPath=workCase.name) 321 322 self.printPhase("Setting up the case") 323 324 self.prepare(workCase,overrideParameters=usedVals) 325 326 if self.opts.noExecuteSolver: 327 self.printPhase("Not executing the solver") 328 continue 329 330 if self.opts.oneClonedCase or self.opts.inplaceExecution: 331 self.setLogname(self.opts.clonedCasePrefix+("_%05d_"%i)+usedVals["solver"], 332 useApplication=False, 333 force=True) 334 else: 335 self.setLogname(self.opts.clonedCasePrefix+"_"+usedVals["solver"], 336 useApplication=False, 337 force=True) 338 339 lam=self.getParallel(workCase) 340 341 allLines().clear() 342 allPlots().clear() 343 resetCustomCounter() 344 345 run=AnalyzedRunner(BoundingLogAnalyzer(progress=self.opts.progress, 346 doFiles=self.opts.writeFiles, 347 singleFile=self.opts.singleDataFilesOnly, 348 doTimelines=True), 349 silent=self.opts.progress or self.opts.silent, 350 argv=[usedVals["solver"],"-case",workCase.name], 351 server=self.opts.server, 352 lam=lam, 353 logname=self.opts.logname, 354 compressLog=self.opts.compress, 355 logTail=self.opts.logTail, 356 noLog=self.opts.noLog, 357 remark=self.opts.remark, 358 parameters=usedVals, 359 echoCommandLine=self.opts.echoCommandPrefix, 360 jobId=self.opts.jobId) 361 362 run.createPlots(customRegexp=self.lines_, 363 writeFiles=self.opts.writeFiles) 364 365 self.runPreHooks() 366 367 self.printPhase("Running") 368 369 run.start() 370 371 self.printPhase("Getting data") 372 373 self["run%05d" % i]=run.data 374 if db: 375 db.add(run.data) 376 377 self.runPostHooks() 378 379 self.reportUsage(run) 380 self.reportRunnerData(run) 381 382 self.printPhase("Ending variation")
383 # Should work with Python3 and Python2 384