-
Notifications
You must be signed in to change notification settings - Fork 94
/
Copy pathsf_lookup.f
245 lines (199 loc) · 5.86 KB
/
sf_lookup.f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
subroutine sf_lookup_init(infile,protonflag)
! Read in spectral function. First line has to have # of Pm,Em bins.
! Subsequent lines (number of lines = numPm*numEm) are of the form:
!
! <Pmvalue> <Emvalue> <SF_PROB> <dPm> <dEm>
!
! where Pmvalue/Emvalue are the center of the Pm/Em bins, dPm/dEm are widths,
! and <SF_PROB> is the integrated spectral function within that bin,
! (SF_PROB = SF * dE * P**2 * dP * 4 * pi), and is the probability within
! the Em/Pm bin, IF the spectral function is normalized to 1.
!
implicit none
include 'sf_lookup.inc'
include 'target.inc'
include 'constants.inc'
real*8 tmpPm,tmpEm,tmpsfp,tmpsfn,tmpdEm,tmpdPm
integer*4 iPm,iEm
character infile*80
logical protonflag
open(unit=55,file=infile,status='old')
read (55,*) numPm , numEm
do iPm = 1 , numPm
do iEm = 1 , numEm
read (55,*) tmpPm,tmpEm,tmpsfp,tmpsfn,tmpdPm,tmpdEm
! Choose proton or neutron spectral function.
if (protonflag) then
sfval(iEm,iPm)=tmpsfp
else
sfval(iEm,iPm)=tmpsfn
endif
! Check that Pm value is consistent with others in same bin
if (iEm.eq.1) then
Pmval(iPm)=tmpPm
dPm(iPm)=tmpdPm
else
if (abs(tmpPm-Pmval(iPm)).gt.0.01) then
write(6,*) 'Bad Pm value, line number is approx',(numEm*(iPm-1)+iEm)
write(6,*) 'iPm,oldPm,newPm=',iPm,Pmval(iPm),tmpPm
endif
endif
! Check that Em value is consistent with others in same bin
if (iPm.eq.1) then
Emval(iEm)=tmpEm
dEm(iEm)=tmpdEm
else
if (abs(tmpEm-Emval(iEm)).gt.0.01) then
write(6,*) 'Bad Em value, line number is approx',(numEm*(iPm-1)+iEm)
write(6,*) 'iEm,oldEm,newEm=',iEm,Emval(iEm),tmpEm
endif
endif
enddo
enddo
sftotnorm = 0.0
do iPm = 1 , numPm
sfnorm(iPm) = 0.0
do iEm = 1 , numEm
sfnorm(iPm) = sfnorm(iPm) + sfval(iEm,iPm)
sftotnorm = sftotnorm + sfval(iEm,iPm)
enddo
! write(6,*) 'Pm=',Pmval(iPm),' has normalization=',sfnorm(iPm)
enddo
write(6,*) 'Uncorrected S.F. has normalization=',sftotnorm
do iPm = 1 , numPm
do iEm = 1 , numEm
sfval(iEm,iPm) = sfval(iEm,iPm) / sftotnorm
enddo
enddo
return
end
!----------------------------------------------------------------------
subroutine sf_lookup_diff(Em,Pm,SFd)
! Get value of fully differential spectral function at Em, Pm.
implicit none
real*8 Em, Pm
real*8 SFd
real*8 SF
call sf_lookup(Em, Pm, SF)
SFd = SF/4/3.1415926535/(Pm*Pm)/5.0/20.0
return
end
!----------------------------------------------------------------------
subroutine sf_lookup(Em,Pm,SF)
! Get value of spectral function <SF_PROB> at Em, Pm.
!
! Where <SF_PROB> is the integrated spectral function within that bin,
! (SF_PROB = SF * dE * P**2 * dP * 4 * pi), and is the probability within
! the Em/Pm bin, once the spectral function has been normalized to 1.
!
implicit none
include 'sf_lookup.inc'
integer*4 ind,iPm,iEm
real*8 Em,Pm
real*8 Em1,Em2,sf1,sf2,logsf,w1,w2
real*8 SF
!find nearest Pm value
if (Pm.ge.Pmval(numPm)) then
iPm=numPm-1
w1=0
w2=1
else if (Pm.le.Pmval(1)) then
iPm=1
w1=1
w2=0
else
ind=1
do while(Pm.gt.Pmval(ind))
ind = ind + 1
enddo
iPm=ind-1
w2=(Pm-Pmval(iPm))/(Pmval(iPm+1)-Pmval(iPm))
w1=(Pmval(iPm+1)-Pm)/(Pmval(iPm+1)-Pmval(iPm))
if (abs(w1*Pmval(iPm)+w2*Pmval(iPm+1)-Pm).gt.0.0001) then
write(6,*) 'w1,w2,Pm,Pmval(iPm)=',w1,w2,Pm,Pmval(iPm)
stop
endif
! write(6,*) 'Pm,iPm,Pm,w1,w2=',Pm,iPm,Pmval(iPm),w1,w2
! do ind=1,numPm
! if (Pm.gt.Pmval(ind)) then
! iPm=ind !ind, or ind-1 ???
! w2=(Pm-Pmval(iPm))/(Pmval(iPm+1)-Pmval(iPm))
! w1=(Pmval(iPm+1)-Pm)/(Pmval(iPm+1)-Pmval(iPm))
! if (abs(w1*Pmval(iPm)+w2*Pmval(iPm+1)-Pm).gt.0.0001) then
! write(6,*) 'w1,w2,Pm,Pmval(iPm)=',w1,w2,Pm,Pmval(iPm)
! stop
! endif
! write(6,*) 'Pm,iPm,Pm,w1,w2=',Pm,iPm,Pmval(iPm),w1,w2
! endif
! enddo
endif
if (abs(w1+w2-1).gt.0.0001) then
write(6,*) 'iPm,Pm,w1+w2=',iPm,Pm,w1+w2
stop
endif
if (Em.le.Emval(1)) then !linear extrapolation of LOG(f(Em)).
Em1=Emval(1)
Em2=Emval(2)
sf1=w1*sfval(1,iPm)+w2*sfval(1,iPm+1)
sf2=w1*sfval(2,iPm)+w2*sfval(2,iPm+1)
else if (Em.gt.Emval(numEm)) then !linear extrapolation of LOG(f(Em))
Em1=Emval(numEm-1)
Em2=Emval(numEm)
sf1=w1*sfval(numEm-1,iPm)+w2*sfval(numEm-1,iPm+1)
sf2=w1*sfval(numEm,iPm)+w2*sfval(numEm,iPm+1)
else
do iEm=1,numEm-1
if (Em.ge.Emval(iEm) .and. Em.lt.Emval(iEm+1)) then
Em1=Emval(iEm)
Em2=Emval(iEm+1)
sf1=w1*sfval(iEm,iPm)+w2*sfval(iEm,iPm+1)
sf2=w1*sfval(iEm+1,iPm)+w2*sfval(iEm+1,iPm+1)
! write(6,*) 'iEm,w1,w2=',iEm,w1,w2
endif
enddo
endif
logsf=(sf1 + (Em-Em1)*(sf2-sf1)/(Em2-Em1))
SF=logsf
if (SF.lt.1.e-20) SF=0
return
end
!----------------------------------------------------------------------
subroutine generate_em(Pm,Em)
! Generate a missing energy for an event with a given Pm.
!
! Have to get spectral function for several Em bins, at the given value
! of Pm. Then, select Em according to the energy distribution at fixed Pm.
!
implicit none
include 'sf_lookup.inc'
integer*4 ind,iEm
real*8 Pm,Em !input Pm value, generated Em value.
real*8 x(nEmmax),y(nEmmax)
real*8 ynorm
real*8 ranprob
real*8 grnd
! Determine Em distribution at fixed Pm (integrated SF up to Em).
ynorm = 0.
x(1) = Emval(1)
call sf_lookup(x(1),Pm,y(1))
do iEm = 2 , numEm
x(iEm) = Emval(iEm)
call sf_lookup(x(iEm),Pm,y(iEm))
y(iEm) = y(iEm) + y(iEm-1)
enddo
! Normalize the Em distribution.
do iEm = 1 , numEm
y(iEm) = y(iEm) / y(numEm)
enddo
! Generate Em.
ranprob = grnd()
ind = 1
do while (ranprob.gt.y(ind))
ind = ind + 1
enddo
Em = Emval(ind) + dEm(ind)*(grnd()-0.5)
! CHECK NORMALIZATION, HAVE CODE SAVE EM/PM DISTRIBUTIONS TO CHECK.
! MAKE SURE EM IS NOT BELOW EM_MIN.
! write(99,'(2f8.2)') Pm,Em
return
end