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

Source Code for Module PyFoam.Applications.Decomposer

  1  #  ICE Revision: $Id: /local/openfoam/Python/PyFoam/PyFoam/Applications/Decomposer.py 7393 2011-03-29T14:55:03.425417Z bgschaid  $  
  2  """ 
  3  Class that implements pyFoamDecompose 
  4  """ 
  5   
  6  from optparse import OptionGroup 
  7   
  8  from PyFoamApplication import PyFoamApplication 
  9  from PyFoam.Basics.FoamFileGenerator import FoamFileGenerator 
 10  from PyFoam.Error import error 
 11  from PyFoam.Basics.Utilities import writeDictionaryHeader 
 12  from PyFoam.Execution.UtilityRunner import UtilityRunner 
 13  from PyFoam.RunDictionary.SolutionDirectory import SolutionDirectory 
 14  from PyFoam.RunDictionary.RegionCases import RegionCases 
 15  from PyFoam.FoamInformation import oldAppConvention as oldApp 
 16  from PyFoam.FoamInformation import foamVersion 
 17   
 18  from CommonMultiRegion import CommonMultiRegion 
 19  from CommonStandardOutput import CommonStandardOutput 
 20  from CommonServer import CommonServer 
 21  from CommonVCSCommit import CommonVCSCommit 
 22   
 23  from os import path,system,listdir,symlink 
 24  import sys,string 
 25   
26 -class Decomposer(PyFoamApplication, 27 CommonStandardOutput, 28 CommonServer, 29 CommonMultiRegion, 30 CommonVCSCommit):
31 - def __init__(self,args=None):
32 description=""" 33 Generates a decomposeParDict for a case and runs the decompose-Utility on that case 34 """ 35 PyFoamApplication.__init__(self, 36 args=args, 37 description=description, 38 usage="%prog [options] <case> <procnr>", 39 interspersed=True, 40 nr=2)
41 42 decomposeChoices=["metis","simple","hierarchical","manual"] 43 defaultMethod="metis" 44
45 - def addOptions(self):
46 if foamVersion()>=(1,6): 47 self.defaultMethod="scotch" 48 self.decomposeChoices+=[self.defaultMethod] 49 self.decomposeChoices+=["parMetis"] 50 51 spec=OptionGroup(self.parser, 52 "Decomposition Specification", 53 "How the case should be decomposed") 54 spec.add_option("--method", 55 type="choice", 56 default=self.defaultMethod, 57 dest="method", 58 action="store", 59 choices=self.decomposeChoices, 60 help="The method used for decomposing (Choices: "+string.join(self.decomposeChoices,", ")+") Default: %default") 61 62 spec.add_option("--n", 63 dest="n", 64 action="store", 65 default=None, 66 help="Number of subdivisions in coordinate directions. A python list or tuple (for simple and hierarchical)") 67 68 spec.add_option("--delta", 69 dest="delta", 70 action="store", 71 type="float", 72 default=None, 73 help="Cell skew factor (for simple and hierarchical)") 74 75 spec.add_option("--order", 76 dest="order", 77 action="store", 78 default=None, 79 help="Order of decomposition (for hierarchical)") 80 81 spec.add_option("--processorWeights", 82 dest="processorWeights", 83 action="store", 84 default=None, 85 help="The weights of the processors. A python list. Used for metis, scotch and parMetis") 86 87 spec.add_option("--globalFaceZones", 88 dest="globalFaceZones", 89 action="store", 90 default=None, 91 help="Global face zones. A python string. Used for the GGI interface. Ex: '(GGI_Z1 GGI_Z2)'") 92 93 spec.add_option("--dataFile", 94 dest="dataFile", 95 action="store", 96 default=None, 97 help="File with the allocations. (for manual)") 98 self.parser.add_option_group(spec) 99 100 behave=OptionGroup(self.parser, 101 "Decomposition behaviour", 102 "How the program should behave during decomposition") 103 behave.add_option("--test", 104 dest="test", 105 action="store_true", 106 default=False, 107 help="Just print the resulting dictionary") 108 109 behave.add_option("--clear", 110 dest="clear", 111 action="store_true", 112 default=False, 113 help="Clear the case of previous processor directories") 114 115 behave.add_option("--no-decompose", 116 dest="doDecompose", 117 action="store_false", 118 default=True, 119 help="Don't run the decomposer (only writes the dictionary") 120 121 behave.add_option("--decomposer", 122 dest="decomposer", 123 action="store", 124 default="decomposePar", 125 help="The decompose Utility that should be used") 126 self.parser.add_option_group(behave) 127 128 work=OptionGroup(self.parser, 129 "Additional work", 130 "What else should be done in addition to decomposing") 131 work.add_option("--constant-link", 132 dest="doConstantLinks", 133 action="store_true", 134 default=False, 135 help="Add links to the contents of the constant directory to the constant directories of the processor-directories") 136 self.parser.add_option_group(work) 137 138 CommonMultiRegion.addOptions(self) 139 CommonStandardOutput.addOptions(self) 140 CommonServer.addOptions(self,False) 141 CommonVCSCommit.addOptions(self)
142
143 - def run(self):
144 if self.opts.keeppseudo and (not self.opts.regions and self.opts.region==None): 145 warning("Option --keep-pseudocases only makes sense for multi-region-cases") 146 147 nr=int(self.parser.getArgs()[1]) 148 if nr<2: 149 error("Number of processors",nr,"too small (at least 2)") 150 151 case=path.abspath(self.parser.getArgs()[0]) 152 method=self.opts.method 153 154 result={} 155 result["numberOfSubdomains"]=nr 156 result["method"]=method 157 158 coeff={} 159 result[method+"Coeffs"]=coeff 160 161 if self.opts.globalFaceZones!=None: 162 fZones=eval(self.opts.globalFaceZones) 163 result["globalFaceZones"]=fZones 164 165 if method in ["metis","scotch","parMetis"]: 166 if self.opts.processorWeights!=None: 167 weigh=eval(self.opts.processorWeights) 168 if nr!=len(weigh): 169 error("Number of processors",nr,"and length of",weigh,"differ") 170 coeff["processorWeights"]=weigh 171 elif method=="manual": 172 if self.opts.dataFile==None: 173 error("Missing required option dataFile") 174 else: 175 coeff["dataFile"]="\""+self.opts.dataFile+"\"" 176 elif method=="simple" or method=="hierarchical": 177 if self.opts.n==None or self.opts.delta==None: 178 error("Missing required option n or delta") 179 n=eval(self.opts.n) 180 if len(n)!=3: 181 error("Needs to be three elements, not",n) 182 if nr!=n[0]*n[1]*n[2]: 183 error("Subdomains",n,"inconsistent with processor number",nr) 184 coeff["n"]="(%d %d %d)" % (n[0],n[1],n[2]) 185 186 coeff["delta"]=float(self.opts.delta) 187 if method=="hierarchical": 188 if self.opts.order==None: 189 error("Missing reuired option order") 190 if len(self.opts.order)!=3: 191 error("Order needs to be three characters") 192 coeff["order"]=self.opts.order 193 else: 194 error("Method",method,"not yet implementes") 195 196 gen=FoamFileGenerator(result) 197 198 if self.opts.test: 199 print str(gen) 200 return -1 201 else: 202 f=open(path.join(case,"system","decomposeParDict"),"w") 203 writeDictionaryHeader(f) 204 f.write(str(gen)) 205 f.close() 206 207 if self.opts.clear: 208 system("rm -rf "+path.join(case,"processor*")) 209 210 self.checkAndCommit(SolutionDirectory(case,archive=None)) 211 212 if self.opts.doDecompose: 213 regionNames=[self.opts.region] 214 regions=None 215 216 if self.opts.regions or self.opts.region!=None: 217 print "Building Pseudocases" 218 sol=SolutionDirectory(case) 219 regions=RegionCases(sol,clean=True,processorDirs=False) 220 221 if self.opts.regions: 222 regionNames=sol.getRegions() 223 224 for theRegion in regionNames: 225 theCase=path.normpath(case) 226 if theRegion!=None: 227 theCase+="."+theRegion 228 229 if oldApp(): 230 argv=[self.opts.decomposer,".",theCase] 231 else: 232 argv=[self.opts.decomposer,"-case",theCase] 233 234 self.setLogname(default="Decomposer",useApplication=False) 235 236 run=UtilityRunner(argv=argv, 237 silent=self.opts.progress, 238 logname=self.opts.logname, 239 compressLog=self.opts.compress, 240 server=self.opts.server, 241 noLog=self.opts.noLog, 242 jobId=self.opts.jobId) 243 run.start() 244 245 if theRegion!=None: 246 print "Syncing into master case" 247 regions.resync(theRegion) 248 249 if regions!=None: 250 if not self.opts.keeppseudo: 251 print "Removing pseudo-regions" 252 regions.cleanAll() 253 else: 254 for r in sol.getRegions(): 255 if r not in regionNames: 256 regions.clean(r) 257 258 if self.opts.doConstantLinks: 259 print "Adding symlinks in the constant directories" 260 constPath=path.join(case,"constant") 261 for f in listdir(constPath): 262 srcExpr=path.join(path.pardir,path.pardir,"constant",f) 263 for p in range(nr): 264 dest=path.join(case,"processor%d"%p,"constant",f) 265 if not path.exists(dest): 266 symlink(srcExpr,dest) 267 268 self.addToCaseLog(case)
269