Package madgraph :: Package various :: Module rambo
[hide private]
[frames] | no frames]

Source Code for Module madgraph.various.rambo

  1  from __future__ import division 
  2  from __future__ import absolute_import 
  3  from __future__ import print_function 
  4  import math 
  5  import random 
  6  from six.moves import range 
  7   
8 -class FortranList(list):
9
10 - def __init__(self, min, max=None):
11 if max is None: 12 self.min = 1 13 self.max = min + 1 14 else: 15 self.min = min 16 self.max = max + 1 17 list.__init__(self,[0]*(self.max-self.min))
18 19
20 - def __getitem__(self, index):
21 assert self.min <= index < self.max, 'outside range %s <= %s < %s' % (self.min, index, self.max) 22 return list.__getitem__(self, index - self.min)
23
24 - def __setitem__(self, index, value):
25 assert self.min <= index < self.max 26 return list.__setitem__(self, index - self.min , value)
27
28 -class DoubleFortranList(FortranList):
29
30 - def __init__(self, min, max=(None,None)):
31 32 min1 = min[0] 33 max1 = max[0] 34 FortranList.__init__(self, min1, max1) 35 36 min2 = min[1] 37 max2 = max[1] 38 39 for i in range(len(self)): 40 list.__setitem__(self,i,FortranList(min2,max2))
41
42 - def __getitem__(self, index):
43 var1 = index[0] 44 var2 = index[1] 45 list1 = FortranList.__getitem__(self, var1) 46 return list1.__getitem__(var2)
47
48 - def __setitem__(self, index, value):
49 var1 = index[0] 50 var2 = index[1] 51 52 list1 = FortranList.__getitem__(self, var1) 53 list1.__setitem__(var2, value)
54 55
56 -class RAMBOError(Exception):
57 """ A Error class for RAMBO routine """ 58 pass
59
60 -def RAMBO(N,ET,XM):
61 """*********************************************************************** 62 * RAMBO * 63 * RA(NDOM) M(OMENTA) B(EAUTIFULLY) O(RGANIZED) * 64 * * 65 * A DEMOCRATIC MULTI-PARTICLE PHASE SPACE GENERATOR * 66 * AUTHORS: S.D. ELLIS, R. KLEISS, W.J. STIRLING * 67 * -- ADJUSTED BY HANS KUIJF, WEIGHTS ARE LOGARITHMIC (20-08-90) * 68 * THIS IS PY VERSION 1.0 - WRITTEN BY O. MATTELAER * 69 * * 70 * N = NUMBER OF PARTICLES * 71 * ET = TOTAL CENTRE-OF-MASS ENERGY * 72 * XM = PARTICLE MASSES ( DIM=NEXTERNAL-nincoming ) * 73 * RETURN * 74 * P = PARTICLE MOMENTA ( DIM=(4,NEXTERNAL-nincoming) ) * 75 * WT = WEIGHT OF THE EVENT * 76 ***********************************************************************""" 77 # RUN PARAMETER 78 acc = 1e-14 79 itmax = 6 80 ibegin = 0 81 iwarn = FortranList(5) 82 Nincoming = 2 83 84 85 # Object Initialization 86 Z = FortranList(N) 87 Q = DoubleFortranList((4,N)) 88 P = DoubleFortranList((4,N)) 89 R = FortranList(4) 90 B = FortranList(3) 91 XM2 = FortranList(N) 92 P2 = FortranList(N) 93 E = FortranList(N) 94 V= FortranList(N) 95 IWARN = [0,0] 96 # Check input object 97 assert isinstance(XM, FortranList) 98 assert XM.min == 1 99 assert XM.max == N+1 100 101 # INITIALIZATION STEP: FACTORIALS FOR THE PHASE SPACE WEIGHT 102 if not ibegin: 103 ibegin = 1 104 twopi = 8 * math.atan(1) 105 po2log = math.log(twopi/4) 106 Z[2] = po2log 107 for k in range(3, N+1): 108 Z[k] = Z[k-1] + po2log - 2.*math.log(k-2) - math.log(k-1) 109 110 # CHECK ON THE NUMBER OF PARTICLES 111 assert 1 < N < 101 112 113 # CHECK WHETHER TOTAL ENERGY IS SUFFICIENT; COUNT NONZERO MASSES 114 xmt = 0 115 nm = 0 116 for i in range(1,N+1): 117 if XM[i] != 0: 118 nm +=1 119 xmt += abs(XM[i]) 120 121 if xmt > ET: 122 raise RAMBOError(' Not enough energy in this case') 123 124 # 125 # THE PARAMETER VALUES ARE NOW ACCEPTED 126 # 127 # GENERATE N MASSLESS MOMENTA IN INFINITE PHASE SPACE 128 for i in range(1,N+1): 129 r1=random_nb(1) 130 c = 2 * r1 -1 131 s = math.sqrt(1 - c**2) 132 f = twopi * random_nb(2) 133 r1 = random_nb(3) 134 r2 = random_nb(4) 135 136 Q[(4,i)]=-math.log(r1*r2) 137 Q[(3,i)]= Q[(4,i)]*c 138 Q[(2,i)]=Q[(4,i)]*s*math.cos(f) 139 Q[(1,i)]=Q[(4,i)]*s*math.sin(f) 140 141 # CALCULATE THE PARAMETERS OF THE CONFORMAL TRANSFORMATION 142 for i in range(1, N+1): 143 for k in range(1,5): 144 R[k] = R[k] + Q[(k,i)] 145 rmas = math.sqrt(R[4]**2-R[3]**2-R[2]**2-R[1]**2) 146 for k in range(1,4): 147 B[k] = - R[k]/rmas 148 149 g = R[4] / rmas 150 a = 1.0 / (1+g) 151 x = ET / rmas 152 153 # TRANSFORM THE Q'S CONFORMALLY INTO THE P'S 154 for i in range(1, N+1): 155 bq = B[1]*Q[(1,i)]+B[2]*Q[(2,i)]+B[3]*Q[(3,i)] 156 for k in range(1,4): 157 P[k,i] = x*(Q[(k,i)]+B[k]*(Q[(4,i)]+a*bq)) 158 P[(4,i)] = x*(g*Q[(4,i)]+bq) 159 160 # CALCULATE WEIGHT AND POSSIBLE WARNINGS 161 wt = po2log 162 if N != 2: 163 wt = (2 * N-4) * math.log(ET) + Z[N] 164 if wt < -180 and iwarn[1] < 5: 165 print("RAMBO WARNS: WEIGHT = EXP(%f20.9) MAY UNDERFLOW" % wt) 166 iwarn[1] += 1 167 if wt > 174 and iwarn[2] < 5: 168 print(" RAMBO WARNS: WEIGHT = EXP(%f20.9) MAY OVERFLOW" % wt) 169 iwarn[2] += 1 170 171 172 # RETURN FOR WEIGHTED MASSLESS MOMENTA 173 if nm == 0: 174 return P, wt 175 176 177 # MASSIVE PARTICLES: RESCALE THE MOMENTA BY A FACTOR X 178 xmax = math.sqrt(1-(xmt/ET)**2) 179 for i in range(1,N+1): 180 XM2[i] = XM[i] **2 181 P2[i] = P[(4,i)]**2 182 n_iter = 0 183 x= xmax 184 accu = ET * acc 185 186 while 1: 187 f0 = -ET 188 g0 = 0 189 x2 = x**2 190 for i in range(1, N+1): 191 E[i] = math.sqrt(XM2[i]+x2*P2[i]) 192 f0 += E[i] 193 g0 += P2[i]/E[i] 194 if abs(f0) <= accu: 195 break 196 n_iter += 1 197 if n_iter > itmax: 198 print("RAMBO WARNS: %s ITERATIONS DID NOT GIVE THE DESIRED ACCURACY = %s" \ 199 %(n_iter , f0)) 200 break 201 x=x-f0/(x*g0) 202 for i in range(1, N+1): 203 V[i] = x * P[(4,i)] 204 for k in range(1,4): 205 P[(k,i)] = x * P[(k,i)] 206 P[(4,i)] = E[i] 207 208 # CALCULATE THE MASS-EFFECT WEIGHT FACTOR 209 wt2 = 1. 210 wt3 = 0. 211 for i in range(1, N+1): 212 wt2 *= V[i]/E[i] 213 wt3 += V[i]**2/E[i] 214 wtm = (2.*N-3.)*math.log(x)+math.log(wt2/wt3*ET) 215 216 # RETURN FOR WEIGHTED MASSIVE MOMENTA 217 wt += wtm 218 if(wt < -180 and iwarn[3] < 5): 219 print(" RAMBO WARNS: WEIGHT = EXP(%s) MAY UNDERFLOW" % wt) 220 iwarn[3] += 1 221 if(wt > 174 and iwarn[4] > 5): 222 print(" RAMBO WARNS: WEIGHT = EXP(%s) MAY OVERFLOW" % wt) 223 iwarn[4] += 1 224 225 # RETURN 226 return P, wt
227
228 -def random_nb(value):
229 """ random number """ 230 output = 0 231 while output < 1e-16: 232 output= random.uniform(0,1) 233 return output
234