FairShip
Loading...
Searching...
No Matches
proton_bremsstrahlung.py
Go to the documentation of this file.
1# SPDX-License-Identifier: LGPL-3.0-or-later
2# SPDX-FileCopyrightText: Copyright CERN for the benefit of the SHiP Collaboration
3
4import math
5import sys
6
7import numpy as np
8import ROOT as r
9from darkphoton import alphaQED
10from scipy.integrate import dblquad
11
12# proton mass
13mProton = 0.938272081 # GeV/c - PDG2016
14protonEnergy = 400.0 # GeV/c
15protonMomentum = math.sqrt(protonEnergy * protonEnergy - mProton * mProton)
16
17
18# VDM FORM FACTOR
20 """From https://arxiv.org/abs/0910.5589"""
21 # constants from the code from Inar: https://github.com/pgdeniverville/BdNMC/blob/master/src/Proton_Brem_Distribution.cpp
22 f1ra = 0.6165340033101271
23 f1rb = 0.22320420111672623
24 f1rc = -0.33973820442685326
25 f1wa = 1.0117544786579074
26 f1wb = -0.8816565944110686
27 f1wc = 0.3699021157531611
28 f1prho = f1ra * 0.77**2 / (0.77**2 - m**2 - 0.77 * 0.15j)
29 f1prhop = f1rb * 1.25**2 / (1.25**2 - m**2 - 1.25 * 0.3j)
30 f1prhopp = f1rc * 1.45**2 / (1.45**2 - m**2 - 1.45 * 0.5j)
31 f1pomega = f1wa * 0.77**2 / (0.77**2 - m**2 - 0.77 * 0.0085j)
32 f1pomegap = f1wb * 1.25**2 / (1.25**2 - m**2 - 1.25 * 0.3j)
33 f1pomegapp = f1wc * 1.45**2 / (1.45**2 - m**2 - 1.45 * 0.5j)
34 return abs(f1prho + f1prhop + f1prhopp + f1pomega + f1pomegap + f1pomegapp)
35
36
37# useful functions
38def energy(p, m):
39 """Compute energy from momentum and mass"""
40 return math.sqrt(p * p + m * m)
41
42
44 """Penalty factor for high masses - dipole form factor in the proton-A' vertex"""
45 """ m in GeV """
46 if m * m > 0.71:
47 return math.pow(m * m / 0.71, -4)
48 else:
49 return 1
50
51
52def zeta(p, theta):
53 """Fraction of the proton momentum carried away by the paraphoton in the beam direction"""
54 return p / (protonMomentum * math.sqrt(theta * theta + 1.0))
55
56
57def pTransverse(p, theta):
58 """Paraphoton transverse momentum in the lab frame"""
59 return protonMomentum * theta * zeta(p, theta)
60
61
62def ptSquare(p, theta):
63 """Square paraphoton transverse momentum in the lab frame"""
64 return pow(pTransverse(p, theta), 2.0)
65
66
67def H(p, theta, mDarkPhoton):
68 """A kinematic term"""
69 return (
70 ptSquare(p, theta)
71 + (1.0 - zeta(p, theta)) * mDarkPhoton * mDarkPhoton
72 + pow(zeta(p, theta), 2.0) * mProton * mProton
73 )
74
75
76def wba(p, theta, mDarkPhoton, epsilon):
77 """Cross section weighting function in the Fermi-Weizsaeker-Williams approximation"""
78 const = epsilon * epsilon * alphaQED / (2.0 * math.pi * H(p, theta, mDarkPhoton))
79
80 h2 = pow(H(p, theta, mDarkPhoton), 2.0)
81 oneMinusZSquare = pow(1.0 - zeta(p, theta), 2.0)
82 mp2 = mProton * mProton
83 mA2 = mDarkPhoton * mDarkPhoton
84
85 p1 = (1.0 + oneMinusZSquare) / zeta(p, theta)
86 p2 = (
87 2.0
88 * zeta(p, theta)
89 * (1.0 - zeta(p, theta))
90 * ((2.0 * mp2 + mA2) / H(p, theta, mDarkPhoton) - pow(zeta(p, theta), 2.0) * 2.0 * mp2 * mp2 / h2)
91 )
92 # p3 = 2.*zeta(p,theta)*(1.-zeta(p,theta))*(zeta(p,theta)+oneMinusZSquare)*mp2*mA2/h2
93 p3 = 2.0 * zeta(p, theta) * (1.0 - zeta(p, theta)) * (1 + oneMinusZSquare) * mp2 * mA2 / h2
94 p4 = 2.0 * zeta(p, theta) * oneMinusZSquare * mA2 * mA2 / h2
95 return const * (p1 - p2 + p3 + p4)
96
97
98def sigma(s): # s in GeV^2 ---> sigma in mb
99 """Parametrisation of sigma(s)"""
100 a1 = 35.45
101 a2 = 0.308
102 a3 = 28.94
103 a4 = 33.34
104 a5 = 0.545
105 a6 = 0.458
106 a7 = 42.53
107 p1 = a2 * pow(math.log(s / a3), 2.0)
108 p2 = a4 * pow((1.0 / s), a5)
109 p3 = a7 * pow((1.0 / s), a6)
110 return a1 + p1 - p2 + p3
111
112
113def es(p, mDarkPhoton):
114 """s(p,mA)"""
115 return 2.0 * mProton * (energy(protonMomentum, mProton) - energy(p, mDarkPhoton))
116
117
118def sigmaRatio(p, mDarkPhoton):
119 """sigma(s') / sigma(s)"""
120 return sigma(es(p, mDarkPhoton)) / sigma(2.0 * mProton * energy(protonMomentum, mProton))
121
122
123def dNdZdPtSquare(p, mDarkPhoton, theta, epsilon):
124 """Differential A' rate per p.o.t. as a function of Z and Pt^2"""
125 return sigmaRatio(p, mDarkPhoton) * wba(p, theta, mDarkPhoton, epsilon)
126
127
128def dPt2dTheta(p, theta):
129 """Jacobian Pt^2->theta"""
130 z2 = pow(zeta(p, theta), 2.0)
131 return 2.0 * theta * z2 * protonMomentum * protonMomentum
132
133
134def dZdP(p, theta):
135 """Jacobian z->p"""
136 return 1.0 / (protonMomentum * math.sqrt(theta * theta + 1.0))
137
138
139def dNdPdTheta(p, theta, mDarkPhoton, epsilon):
140 """Differential A' rate per p.o.t. as a function of P and theta"""
141 diffRate = dNdZdPtSquare(p, mDarkPhoton, theta, epsilon) * dPt2dTheta(p, theta) * dZdP(p, theta)
142 return math.fabs(diffRate) # integrating in (-pi, pi)...
143
144
145def pMin(mDarkPhoton):
146 return max(0.14 * protonMomentum, mDarkPhoton)
147
148
149def pMax(mDarkPhoton):
150 # return min(0.86*protonMomentum, math.sqrt( (energy(protonMomentum,mProton)**2. - mDarkPhoton**2.) - mDarkPhoton**2.))
151 return math.sqrt((energy(protonMomentum, mProton) ** 2.0 - mDarkPhoton**2.0) - mDarkPhoton**2.0)
152
153
154def prodRate(mDarkPhoton, epsilon, tmin=-0.5 * math.pi, tmax=0.5 * math.pi):
155 """dNdPdTheta integrated over p and theta"""
156 integral = dblquad(
157 dNdPdTheta, # integrand
158 tmin,
159 tmax, # theta boundaries (2nd argument of integrand)
160 lambda x: pMin(mDarkPhoton),
161 lambda x: pMax(mDarkPhoton), # p boundaries (1st argument of integrand)
162 args=(mDarkPhoton, epsilon),
163 ) # extra parameters to pass to integrand
164 return integral[0]
165
166
167# total production rate of A'
168# norm = prodRate(1.1,3.e-7) #mDarkPhoton,epsilon)
169# number of A' produced
170# numDarkPhotons = int(math.floor(norm*protonFlux))
171#
172# print
173# print "Epsilon \t %s"%epsilon
174# print "mDarkPhoton \t %s"%mDarkPhoton
175# print "A' production rate per p.o.t: \t %.8g"%norm
176# print "Number of A' produced in SHiP: \t %.8g"%numDarkPhotons
177
178
179def normalisedProductionPDF(p, theta, mDarkPhoton, epsilon, norm):
180 """Probability density function for A' production in SHIP"""
181 return (1.0 / norm) * dNdPdTheta(p, theta, mDarkPhoton, epsilon)
182
183
184def hProdPDF(mDarkPhoton, epsilon, norm, binsp, binstheta, tmin=-0.5 * math.pi, tmax=0.5 * math.pi, suffix=""):
185 """Histogram of the PDF for A' production in SHIP"""
186 angles = np.linspace(tmin, tmax, binstheta).tolist()
187 anglestep = 2.0 * (tmax - tmin) / binstheta
188 momentumStep = (pMax(mDarkPhoton) - pMin(mDarkPhoton)) / (binsp - 1)
189 momenta = np.linspace(pMin(mDarkPhoton), pMax(mDarkPhoton), binsp, endpoint=False).tolist()
190 hPDF = r.TH2F(
191 f"hPDF_eps{epsilon}_m{mDarkPhoton}",
192 f"hPDF_eps{epsilon}_m{mDarkPhoton}",
193 binsp,
194 pMin(mDarkPhoton) - 0.5 * momentumStep,
195 pMax(mDarkPhoton) - 0.5 * momentumStep,
196 binstheta,
197 tmin - 0.5 * anglestep,
198 tmax - 0.5 * anglestep,
199 )
200 hPDF.SetTitle(f"PDF for A' production (m_{{A'}}={mDarkPhoton} GeV, #epsilon ={epsilon})")
201 hPDF.GetXaxis().SetTitle("P_{A'} [GeV]")
202 hPDF.GetYaxis().SetTitle("#theta_{A'} [rad]")
203 hPDFtheta = r.TH1F(
204 f"hPDFtheta_eps{epsilon}_m{mDarkPhoton}",
205 f"hPDFtheta_eps{epsilon}_m{mDarkPhoton}",
206 binstheta,
207 tmin - 0.5 * anglestep,
208 tmax - 0.5 * anglestep,
209 )
210 hPDFp = r.TH1F(
211 f"hPDFp_eps{epsilon}_m{mDarkPhoton}",
212 f"hPDFp_eps{epsilon}_m{mDarkPhoton}",
213 binsp,
214 pMin(mDarkPhoton) - 0.5 * momentumStep,
215 pMax(mDarkPhoton) - 0.5 * momentumStep,
216 )
217 hPDFp.GetXaxis().SetTitle("P_{A'} [GeV]")
218 hPDFtheta.GetXaxis().SetTitle("#theta_{A'} [rad]")
219 for theta in angles:
220 for p in momenta:
221 w = normalisedProductionPDF(p, theta, mDarkPhoton, epsilon, norm)
222 hPDF.Fill(p, theta, w)
223 hPDFtheta.Fill(theta, w)
224 hPDFp.Fill(p, w)
225 hPdfFilename = sys.modules["__main__"].options.outputDir + f"/ParaPhoton_eps{epsilon}_m{mDarkPhoton}{suffix}.root"
226 outfile = r.TFile(hPdfFilename, "recreate")
227 # weight = hPDF.Integral("width")
228 # print "Weight = %3.3f"%weight
229 # hPDF.Scale(1./weight)
230 hPDF.Write()
231 hPDFp.Write()
232 hPDFtheta.Write()
233 outfile.Close()
234 del angles
235 del momenta
236 return hPDF
def prodRate(mDarkPhoton, epsilon, tmin=-0.5 *math.pi, tmax=0.5 *math.pi)
def dNdZdPtSquare(p, mDarkPhoton, theta, epsilon)
def wba(p, theta, mDarkPhoton, epsilon)
def dNdPdTheta(p, theta, mDarkPhoton, epsilon)
def sigmaRatio(p, mDarkPhoton)
def normalisedProductionPDF(p, theta, mDarkPhoton, epsilon, norm)
def H(p, theta, mDarkPhoton)
def hProdPDF(mDarkPhoton, epsilon, norm, binsp, binstheta, tmin=-0.5 *math.pi, tmax=0.5 *math.pi, suffix="")