1 """
2 Class that implements pyFoamDecompose
3 """
4
5 from PyFoamApplication import PyFoamApplication
6 from PyFoam.Basics.FoamFileGenerator import FoamFileGenerator
7 from PyFoam.Error import error
8 from PyFoam.Basics.Utilities import writeDictionaryHeader
9 from PyFoam.Execution.UtilityRunner import UtilityRunner
10
11 from os import path,system
12
15 description="""
16 Generates a decomposeParDict for a case and runs the decompose-Utility on that case
17 """
18 PyFoamApplication.__init__(self,description=description,usage="%prog [options] <case> <procnr>",interspersed=True,nr=2)
19
21 self.parser.add_option("--method",type="choice",default="metis",dest="method",action="store",
22 choices=["metis","simple","hierarchical","manual"],
23 help="The method used for decomposing")
24
25 self.parser.add_option("--test",dest="test",action="store_true",default=False,
26 help="Just print the resulting dictionary")
27
28 self.parser.add_option("--n",dest="n",action="store",default=None,
29 help="Number of subdivisions in coordinate directions. A python list or tuple (for simple and hierarchical)")
30 self.parser.add_option("--delta",dest="delta",action="store",type="float",default=None,
31 help="Cell skew factor (for simple and hierarchical)")
32 self.parser.add_option("--order",dest="order",action="store",default=None,
33 help="Order of decomposition (for hierarchical)")
34 self.parser.add_option("--processorWeights",dest="processorWeights",action="store",default=None,
35 help="The weights of the processors. A python list. Used for metis")
36 self.parser.add_option("--dataFile",dest="dataFile",action="store",default=None,
37 help="File with the allocations. (for manual)")
38
39 self.parser.add_option("--clear",dest="clear",action="store_true",default=False,
40 help="Clear the case of previous processor directories")
41 self.parser.add_option("--no-decompose",dest="doDecompose",action="store_false",default=True,
42 help="Don't run the decomposer (only writes the dictionary")
43 self.parser.add_option("--decomposer",dest="decomposer",action="store",default="decomposePar",
44 help="The decompose Utility that should be used")
45
47 nr=int(self.parser.getArgs()[1])
48 if nr<2:
49 error("Number of processors",nr,"too small (at least 2)")
50
51 case=self.parser.getArgs()[0]
52 method=self.opts.method
53
54 result={}
55 result["numberOfSubdomains"]=nr
56 result["method"]=method
57
58 coeff={}
59 result[method+"Coeffs"]=coeff
60
61 if method=="metis":
62 if self.opts.processorWeights!=None:
63 weigh=eval(self.opts.processorWeights)
64 if nr!=len(weigh):
65 error("Number of processors",nr,"and length of",weigh,"differ")
66 coeff["processorWeights"]=weigh
67 elif method=="manual":
68 if self.opts.dataFile==None:
69 error("Missing required option dataFile")
70 else:
71 coeff["dataFile"]="\""+self.opts.dataFile+"\""
72 elif method=="simple" or method=="hierarchical":
73 if self.opts.n==None or self.opts.delta==None:
74 error("Missing required option n or delta")
75 n=eval(self.opts.n)
76 if len(n)!=3:
77 error("Needs to be three elements, not",n)
78 if nr!=n[0]*n[1]*n[2]:
79 error("Subdomains",n,"inconsistent with processor number",nr)
80 coeff["n"]="(%d %d %d)" % (n[0],n[1],n[2])
81
82 coeff["delta"]=float(self.opts.delta)
83 if method=="hierarchical":
84 if self.opts.order==None:
85 error("Missing reuired option order")
86 if len(self.opts.order)!=3:
87 error("Order needs to be three characters")
88 coeff["order"]=self.opts.order
89 else:
90 error("Method",method,"not yet implementes")
91
92 gen=FoamFileGenerator(result)
93
94 if self.opts.test:
95 print gen.makeString()
96 sys.exit(-1)
97 else:
98 f=open(path.join(case,"system","decomposeParDict"),"w")
99 writeDictionaryHeader(f)
100 f.write(gen.makeString())
101 f.close()
102
103 if self.opts.clear:
104 system("rm -rf "+path.join(case,"processor*"))
105
106 if self.opts.doDecompose:
107 run=UtilityRunner(argv=[self.opts.decomposer,".",case],silent=False,server=False)
108 run.start()
109