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

Source Code for Module PyFoam.Applications.Decomposer

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