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