REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestWimpUtils.cxx
1 /*************************************************************************
2  * This file is part of the REST software framework. *
3  * *
4  * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5  * For more information see http://gifna.unizar.es/trex *
6  * *
7  * REST is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * REST is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have a copy of the GNU General Public License along with *
18  * REST in $REST_PATH/LICENSE. *
19  * If not, see http://www.gnu.org/licenses/. *
20  * For the list of contributors see $REST_PATH/CREDITS. *
21  *************************************************************************/
22 
44 
45 #include <TMath.h>
46 #include <TRestWimpUtils.h>
47 
53 const double TRestWimpUtils::GetRelativeNuclearCS(const double wimpMass, const double Anum) {
54  const double reducedMass = GetReducedMass(wimpMass, Anum);
55  const double reducedMassSingle = GetReducedMass(wimpMass, 1.);
56  return pow(Anum * GEV_PER_UMA * reducedMass / reducedMassSingle, 2.);
57 }
58 
63 const double TRestWimpUtils::GetReducedMass(const double wimpMass, const double Anum) {
64  // WIMP mass in GeV
65  return wimpMass * GEV_PER_UMA * Anum / (wimpMass + Anum * GEV_PER_UMA);
66 }
67 
73 const double TRestWimpUtils::GetHelmFormFactor(const double recoilEnergy, const double Anum) {
74  // Momentum transfer in keV
75  const double q = sqrt(2. * Anum * GEV_PER_UMA * 1E6 * recoilEnergy);
76  const double s = 0.9; // Femtometers-Skin thickness of the nucleus
77  const double qs = q * s / HC_KEV_FM;
78  // Parametrization of atomic nuclei
79  const double RN = sqrt(pow(1.23 * std::cbrt(Anum) - 0.60, 2) +
80  (7. / 3.) * pow(TMath::Pi(), 2) * 0.52 * 0.52 - 5. * s * s);
81  const double qR = q * RN / HC_KEV_FM;
82  // First Bessel function
83  const double bessel1 = sin(qR) / (qR * qR) - cos(qR) / qR;
84  // Form factor
85  double formFactor = 3. * bessel1 / qR * exp(-0.5 * qs * qs);
86 
87  return formFactor;
88 }
89 
95 const double TRestWimpUtils::GetVMin(const double wimpMass, const double Anum, const double recoilEnergy) {
96  const double reducedMass = GetReducedMass(wimpMass, Anum);
97  return sqrt(Anum * GEV_PER_UMA * recoilEnergy * 1E-6 / (2. * reducedMass * reducedMass)) * LIGHT_SPEED;
98 }
99 
104 const double TRestWimpUtils::GetVelocityDistribution(const double v, const double vLab, const double vRMS,
105  const double vEscape) {
106  const double vAdim = vRMS / vLab;
107  const double Nesc = erf(vAdim) - (2. / sqrt(TMath::Pi())) * (vAdim)*exp(-vAdim * vAdim);
108  const double xMax = std::min(1., (vEscape * vEscape - vLab * vLab - v * v) / (2. * vLab * v));
109  return v * Nesc / (vLab * vRMS * sqrt(TMath::Pi())) *
110  (exp(-(v - vLab) * (v - vLab) / (vRMS * vRMS)) -
111  exp(-(v * v + vLab * vLab + 2 * v * vLab * xMax) / (vRMS * vRMS)));
112 }
113 
121 const double TRestWimpUtils::GetDifferentialCrossSection(const double wimpMass, const double crossSection,
122  const double velocity, const double recoilEnergy,
123  const double Anum) {
124  const double cs = GetRelativeNuclearCS(wimpMass, Anum) * crossSection;
125  const double reducedMass = GetReducedMass(wimpMass, Anum);
126  const double Emax = 1E6 / LIGHT_SPEED / LIGHT_SPEED * 2. * reducedMass * reducedMass * velocity *
127  velocity / (Anum * GEV_PER_UMA);
128  const double formFactor = GetHelmFormFactor(recoilEnergy, Anum);
129 
130  return cs * formFactor * formFactor / Emax;
131 }
132 
138 const double TRestWimpUtils::GetRecoilRate(const double wimpMass, const double crossSection,
139  const double recoilEnergy, const double Anum, const double vLab,
140  const double vRMS, const double vEscape, const double wimpDensity,
141  const double abundance) {
142  const double vMin = GetVMin(wimpMass, Anum, recoilEnergy);
143  const double vMax = vEscape + vLab;
144  const double nNuclei = abundance * N_AVOGADRO * 1E3 / Anum; // Number of atoms
145 
146  if (vMin > vMax) return 0;
147 
148  double rate = 0;
149  const double velStep = 0.1; // km/s
150 
151  for (double v = vMin; v < vMax; v += velStep) {
152  const double flux = 1E5 * v * wimpDensity / wimpMass;
153  const double diffRate = flux *
154  GetDifferentialCrossSection(wimpMass, crossSection, v, recoilEnergy, Anum) *
155  GetVelocityDistribution(v, vLab, vRMS, vEscape);
156  rate += diffRate * velStep;
157  }
158 
159  return rate * SECONDS_PER_DAY * nNuclei;
160 }
161 
166 const double TRestWimpUtils::GetQuenchingFactor(const double recoilEnergy, const double Anum,
167  const double Znum) {
168  const double deltaE = 0.0001, Emin = 0.1, resolution = 0.1; // keV
169  double g, Er = recoilEnergy, Ev;
170 
171  do {
172  Er -= resolution;
173  g = 0.66 * pow(Znum, 5. / 18.) / sqrt(Anum) * pow(recoilEnergy, 1. / 6.);
174  } while ((Er / (1 + g) * g) > Emin);
175 
176  do {
177  Er += deltaE;
178  g = 0.66 * pow(Znum, 5. / 18.) / sqrt(Anum) * pow(Er, 1. / 6.);
179  Ev = (Er / (1 + g) * g);
180  } while (recoilEnergy > Ev);
181 
182  return (1 + g) / g;
183 }
constexpr double GEV_PER_UMA
Physics constants.
const double GetRelativeNuclearCS(const double wimpMass, const double Anum)
Generic functions for different calculations.