Skip to content

Commit 2da916d

Browse files
authored
Merge pull request #1 from rest-for-physics/optimization
Bug fixes and improvement of performance
2 parents 82ffdad + f1b3914 commit 2da916d

File tree

7 files changed

+201
-57
lines changed

7 files changed

+201
-57
lines changed

examples/WIMP.rml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<parameter name="rmsVelocity" value="220"/>
1010
<parameter name="escapeVelocity" value="544"/>
1111
<parameter name="exposure" value="116.8"/>
12-
<parameter name="backgroundLevel" value="1"/>
12+
<parameter name="background" value="1"/>
1313
<parameter name="energySpectra" value="(0,2)"/>
1414
<parameter name="energySpectraStep" value="0.01"/>
1515
<parameter name="energyRange" value="(0.1,1.1)"/>

inc/TRestWimpSensitivity.h

+24
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,35 @@ class TRestWimpSensitivity : public TRestMetadata {
7070
void ReadNuclei();
7171
const Double_t GetSensitivity(const double wimpMass);
7272
void CalculateQuenchingFactor();
73+
bool isEnergySpectraWideEnough();
7374
const std::string BuildOutputFileName(const std::string& extension = ".txt");
7475

7576
std::map<std::string, TH1D*> GetRecoilSpectra(const double wimpMass, const double crossSection);
7677
std::map<std::string, TH1D*> GetFormFactor();
7778
inline auto GetQuenchingFactor() { return quenchingFactor; }
79+
inline std::vector<TRestWimpNucleus>& GetNuclei() { return fNuclei; };
80+
inline auto GetEnergySpectra() { return fEnergySpectra; }
81+
inline auto GetEnergySpectraStep() { return fEnergySpectraStep; }
82+
inline auto GetEnergyRange() { return fEnergyRange; }
83+
inline auto GetWimpDensity() { return fWimpDensity; }
84+
inline auto GetLabVelocity() { return fLabVelocity; }
85+
inline auto GetEscapeVelocity() { return fEscapeVelocity; }
86+
inline auto GetRmsVelocity() { return fRmsVelocity; }
87+
inline auto GetExposure() { return fExposure; }
88+
inline auto GetBackground() { return fBackground; }
89+
inline auto GetUseQuenchingFactor() { return fUseQuenchingFactor; }
90+
91+
void SetNuclei(const std::vector<TRestWimpNucleus>& nuclei) { fNuclei = nuclei; }
92+
void SetEnergySpectra(const TVector2& energySpectra) { fEnergySpectra = energySpectra; }
93+
void SetEnergySpectraStep(const Double_t energySpectraStep) { fEnergySpectraStep = energySpectraStep; }
94+
void SetEnergyRange(const TVector2& energyRange) { fEnergyRange = energyRange; }
95+
void SetWimpDensity(const Double_t wimpDensity) { fWimpDensity = wimpDensity; }
96+
void SetLabVelocity(const Double_t labVelocity) { fLabVelocity = labVelocity; }
97+
void SetEscapeVelocity(const Double_t escapeVelocity) { fEscapeVelocity = escapeVelocity; }
98+
void SetRmsVelocity(const Double_t rmsVelocity) { fRmsVelocity = rmsVelocity; }
99+
void SetExposure(const Double_t exposure) { fExposure = exposure; }
100+
void SetBackground(const Double_t background) { fBackground = background; }
101+
void SetUseQuenchingFactor(const Bool_t useQuenchingFactor) { fUseQuenchingFactor = useQuenchingFactor; }
78102

79103
ClassDefOverride(TRestWimpSensitivity, 1);
80104
};

inc/TRestWimpUtils.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace TRestWimpUtils {
3131
/// Physics constants
3232
constexpr double GEV_PER_UMA = 0.93149432;
3333
constexpr double HC_KEV_FM = 197327.053;
34-
constexpr double LIGHT_SPEED = 300000.0; // km/s
34+
constexpr double LIGHT_SPEED = 299792.458; // km/s
3535
constexpr double SECONDS_PER_DAY = 86400;
3636
constexpr double N_AVOGADRO = 6.0221367E23;
3737
constexpr double MBARN_PER_GEVM2 = 0.38937966;
@@ -46,6 +46,8 @@ const double Bessel(const double x);
4646
const double GetVMin(const double wimpMass, const double Anum, const double recoilEnergy);
4747
const double GetVelocityDistribution(const double v, const double vLab, const double vRMS,
4848
const double vEscape);
49+
const double GetDifferentialCrossSectionNoHelmFormFactor(const double wimpMass, const double crossSection,
50+
const double velocity, const double Anum);
4951
const double GetDifferentialCrossSection(const double wimpMass, const double crossSection,
5052
const double velocity, const double recoilEnergy, const double Anum);
5153
const double GetRecoilRate(const double wimpMass, const double crossSection, const double recoilEnergy,

src/TRestWimpSensitivity.cxx

+131-40
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
/// <parameter name="rmsVelocity" value="220"/>
6262
/// <parameter name="escapeVelocity" value="544"/>
6363
/// <parameter name="exposure" value="116.8"/>
64-
/// <parameter name="backgroundLevel" value="1"/>
64+
/// <parameter name="background" value="1"/>
6565
/// <parameter name="energySpectra" value="(0,2)"/>
6666
/// <parameter name="energySpectraStep" value="0.01"/>
6767
/// <parameter name="energyRange" value="(0.1,1.1)"/>
@@ -177,6 +177,7 @@ void TRestWimpSensitivity::ReadNuclei() {
177177
///////////////////////////////////////////////
178178
/// \brief Get recoil spectra for a given WIMP
179179
/// mass and cross section
180+
/// Better performance version
180181
///
181182
std::map<std::string, TH1D*> TRestWimpSensitivity::GetRecoilSpectra(const double wimpMass,
182183
const double crossSection) {
@@ -188,16 +189,76 @@ std::map<std::string, TH1D*> TRestWimpSensitivity::GetRecoilSpectra(const double
188189
std::string histName = "RecoilSpc_" + std::string(nucl.fNucleusName);
189190
TH1D* recoilSpc =
190191
new TH1D(histName.c_str(), histName.c_str(), nBins, fEnergySpectra.X(), fEnergySpectra.Y());
191-
for (int i = 1; i < recoilSpc->GetNbinsX(); i++) {
192+
193+
// Build vector of tuples=(recoilEnergy, minimum velocity, rate) used in further calculations
194+
std::vector<std::tuple<double, double, double>> tEnergyVminRate;
195+
for (int i = 0; i < recoilSpc->GetNbinsX(); i++) {
196+
double E = recoilSpc->GetBinCenter(i);
197+
if (E <= 0) continue;
198+
tEnergyVminRate.push_back(
199+
std::make_tuple(E, TRestWimpUtils::GetVMin(wimpMass, nucl.fAnum, E), 0));
200+
}
201+
202+
const double nNuclei =
203+
nucl.fAbundance * TRestWimpUtils::N_AVOGADRO * 1E3 / nucl.fAnum; // Number of atoms
204+
const double vMin = std::get<1>(
205+
tEnergyVminRate.at(0)); // element 0 should be the lowest (positive) energy -> lowest vMin
206+
const double vMax = fEscapeVelocity + fLabVelocity;
207+
208+
// calculation of the rate for each recoil energy
209+
double rate{0}; // will contain integral from minimun vMin to vMax, idem integral_min(vMin)^vMax
210+
const double velStep = 0.1; // km/s
211+
int j = 0;
212+
double flux = 0, diffRate = 0, v = 0;
213+
// vMax+velStep to save the rate when v is in interval (vMax-velStep, vMax]
214+
for (v = vMin; v < vMax + velStep; v += velStep) {
215+
// save (in 3rd element of tEnergyVminRate tuples) the integral from minimun vMin to each vMin,
216+
// idem integral_min(vMin)^vMin
217+
while (j < (int)tEnergyVminRate.size()) {
218+
const double vmin = std::get<1>(tEnergyVminRate.at(j));
219+
if (vmin < v) {
220+
// std::get<2>(tEnergyVminRate.at(j)) = rate; //les precise
221+
std::get<2>(tEnergyVminRate.at(j)) = rate - diffRate * (v - vmin); // more precise
222+
j++;
223+
} else
224+
break;
225+
}
226+
flux = 1E5 * v * fWimpDensity / wimpMass;
227+
diffRate =
228+
flux *
229+
TRestWimpUtils::GetDifferentialCrossSectionNoHelmFormFactor(wimpMass, crossSection, v,
230+
nucl.fAnum) *
231+
TRestWimpUtils::GetVelocityDistribution(v, fLabVelocity, fRmsVelocity, fEscapeVelocity);
232+
rate += diffRate * velStep;
233+
}
234+
rate -=
235+
diffRate * (v - vMax); // substract last diffRate*(v - vMax) to obtain the rate from vMin to vMax
236+
237+
/*obtain the rate (integral from each vMin to vMax) by substracting integral from minimun vMin to each
238+
vMin to the integral from minimun vMin to vMax
239+
idem: integral_vMin^vMax = integral_min(vMin)^vMax - integral_min(vMin)^vMin */
240+
for (auto& [E, vmin, r] : tEnergyVminRate) {
241+
if (vmin > vMax) continue; // r=0
242+
const double formFactor = TRestWimpUtils::GetHelmFormFactor(E, nucl.fAnum);
243+
r = (rate - r) * formFactor * formFactor * TRestWimpUtils::SECONDS_PER_DAY * nNuclei;
244+
}
245+
246+
// copy results to recoilMap
247+
j = 0;
248+
for (int i = 0; i < recoilSpc->GetNbinsX(); i++) {
192249
const double recoilEnergy = recoilSpc->GetBinCenter(i);
193-
const double recoilRate =
194-
TRestWimpUtils::GetRecoilRate(wimpMass, crossSection, recoilEnergy, nucl.fAnum, fLabVelocity,
195-
fRmsVelocity, fEscapeVelocity, fWimpDensity, nucl.fAbundance);
196-
recoilSpc->SetBinContent(i, recoilRate);
250+
// const double recoilRate = std::get<2> (tEnergyVminRate.at(i));
251+
while (j < (int)tEnergyVminRate.size()) {
252+
if (recoilEnergy == std::get<0>(tEnergyVminRate.at(j))) {
253+
recoilSpc->SetBinContent(i, std::get<2>(tEnergyVminRate.at(j)));
254+
j++;
255+
} else
256+
break;
257+
}
197258
}
259+
198260
recoilMap[std::string(nucl.fNucleusName)] = recoilSpc;
199261
}
200-
201262
return recoilMap;
202263
}
203264

@@ -211,19 +272,48 @@ const Double_t TRestWimpSensitivity::GetSensitivity(const double wimpMass) {
211272

212273
if (fUseQuenchingFactor) CalculateQuenchingFactor();
213274

214-
const int nBins = (fEnergySpectra.Y() - fEnergySpectra.X()) / fEnergySpectraStep;
275+
if (!isEnergySpectraWideEnough()) {
276+
RESTError << "Energy spectra range is not wide enough to match the energy range given." << RESTendl;
277+
// return 0;
278+
}
279+
280+
double nMeas = 0;
215281

216-
TH1D recoilSpc("recoilSpc", "recoilSpc", nBins, fEnergySpectra.X(), fEnergySpectra.Y());
282+
const double crossSection = 1E-45;
283+
auto rSpc = GetRecoilSpectra(wimpMass, crossSection);
284+
285+
for (auto& nucl : fNuclei) {
286+
auto recoilSpc = rSpc[std::string(nucl.fNucleusName)];
287+
288+
for (int i = 1; i < recoilSpc->GetNbinsX(); i++) {
289+
double recoilEnergy = recoilSpc->GetBinCenter(i);
290+
const double recoilRate = recoilSpc->GetBinContent(i);
291+
292+
if (fUseQuenchingFactor)
293+
recoilEnergy *= quenchingFactor[std::string(nucl.fNucleusName)]->GetBinContent(i);
294+
295+
if (recoilEnergy < fEnergyRange.X() || recoilEnergy > fEnergyRange.Y()) continue;
296+
nMeas += recoilRate * fEnergySpectraStep;
297+
}
298+
}
217299

218300
double bckCounts = 0;
219301

220-
for (int i = 1; i < recoilSpc.GetNbinsX(); i++) {
221-
const double en = recoilSpc.GetBinCenter(i);
302+
auto recSpc = rSpc[std::string(fNuclei.front().fNucleusName)];
303+
for (int i = 1; i < recSpc->GetNbinsX(); i++) {
304+
const double en = recSpc->GetBinCenter(i);
222305
if (en < fEnergyRange.X() || en > fEnergyRange.Y()) continue;
223306
bckCounts += fBackground * fEnergySpectraStep;
224307
}
225308
bckCounts *= fExposure;
226309

310+
for (auto& [name, histo] : rSpc) delete histo;
311+
rSpc.clear();
312+
313+
RESTExtreme << "nMeas = " << nMeas << " c/kg/day" << RESTendl;
314+
RESTExtreme << "bckCounts = " << bckCounts << RESTendl;
315+
if (nMeas == 0) return 0;
316+
227317
double signalCounts = 0, prob = 0;
228318

229319
do {
@@ -237,35 +327,10 @@ const Double_t TRestWimpSensitivity::GetSensitivity(const double wimpMass) {
237327
signalCounts++;
238328
} while (fabs(prob - 0.1) > 0.01 && signalCounts < 1E6);
239329

240-
double nMeas = 0;
241-
const double crossSection = 1E-45;
242-
243-
for (auto& nucl : fNuclei) {
244-
recoilSpc.Reset();
245-
246-
for (int i = 1; i < recoilSpc.GetNbinsX(); i++) {
247-
const double recoilEnergy = recoilSpc.GetBinCenter(i);
248-
const double recoilRate =
249-
TRestWimpUtils::GetRecoilRate(wimpMass, crossSection, recoilEnergy, nucl.fAnum, fLabVelocity,
250-
fRmsVelocity, fEscapeVelocity, fWimpDensity, nucl.fAbundance);
251-
recoilSpc.SetBinContent(i, recoilRate);
252-
}
253-
254-
for (int i = 1; i < recoilSpc.GetNbinsX(); i++) {
255-
double recoilEnergy = recoilSpc.GetBinCenter(i);
256-
// const double recoilRate = recoilSpc.GetBinContent(i);
257-
if (fUseQuenchingFactor)
258-
recoilEnergy *= quenchingFactor[std::string(nucl.fNucleusName)]->GetBinContent(i);
259-
260-
if (recoilEnergy < fEnergyRange.X() || recoilEnergy > fEnergyRange.Y()) continue;
261-
nMeas += recoilSpc.GetBinContent(i) * fEnergySpectraStep;
262-
}
263-
}
264-
265-
if (nMeas == 0) return 0;
266-
267330
const double sensitivity = signalCounts * 1E-45 / (nMeas * fExposure);
268331

332+
RESTExtreme << "sigCounts = " << signalCounts << RESTendl;
333+
269334
return sensitivity;
270335
}
271336

@@ -274,7 +339,17 @@ const Double_t TRestWimpSensitivity::GetSensitivity(const double wimpMass) {
274339
/// stores in a map
275340
///
276341
void TRestWimpSensitivity::CalculateQuenchingFactor() {
277-
if (!quenchingFactor.empty()) return;
342+
// do not calculate if already calculated (with same energy spectra limits)
343+
if (!quenchingFactor.empty()) {
344+
bool same = true;
345+
for (auto& [name, histo] : quenchingFactor)
346+
if (histo->GetXaxis()->GetXmin() != fEnergySpectra.X() ||
347+
histo->GetXaxis()->GetXmax() != fEnergySpectra.Y()) {
348+
same = false;
349+
break;
350+
}
351+
if (same) return;
352+
}
278353

279354
std::cout << "Calculating quenching factor " << std::endl;
280355

@@ -296,6 +371,21 @@ void TRestWimpSensitivity::CalculateQuenchingFactor() {
296371
}
297372
}
298373

374+
bool TRestWimpSensitivity::isEnergySpectraWideEnough() {
375+
if (!fUseQuenchingFactor)
376+
return fEnergySpectra.X() <= fEnergyRange.X() && fEnergySpectra.Y() >= fEnergyRange.Y();
377+
378+
CalculateQuenchingFactor();
379+
for (auto& nucl : fNuclei) {
380+
auto qf = quenchingFactor[std::string(nucl.fNucleusName)];
381+
// assuming that Energy_nr * QF(Energy_nr) is a monotonically increasing function
382+
if (qf->GetBinContent(1) * qf->GetBinCenter(1) > fEnergyRange.X() ||
383+
qf->GetBinContent(qf->GetNbinsX() - 1) * qf->GetBinCenter(qf->GetNbinsX() - 1) < fEnergyRange.Y())
384+
return false;
385+
}
386+
return true;
387+
}
388+
299389
///////////////////////////////////////////////
300390
/// \brief Return output file format with different
301391
/// parameters used in the calculation.
@@ -309,6 +399,7 @@ const std::string TRestWimpSensitivity::BuildOutputFileName(const std::string& e
309399
ss << "WD_" << fWimpDensity << "_";
310400
ss << "Vel_" << fLabVelocity << "_" << fRmsVelocity << "_" << fEscapeVelocity << "_";
311401
ss << "Bck_" << fBackground << "_";
402+
ss << "Exp_" << fExposure << "_";
312403
ss << "RecEn_" << fEnergySpectra.X() << "_" << fEnergySpectra.Y() << "_" << fEnergySpectraStep << "_";
313404
ss << "EnRange_" << fEnergyRange.X() << "_" << fEnergyRange.Y() << "_";
314405

@@ -366,6 +457,6 @@ void TRestWimpSensitivity::PrintMetadata() {
366457
<< ") Step: " << fEnergySpectraStep << " keV" << RESTendl;
367458
RESTMetadata << "Sensitivity energy range: (" << fEnergyRange.X() << ", " << fEnergyRange.Y() << ") keV"
368459
<< RESTendl;
369-
RESTMetadata << "Use quenching factor: " << fUseQuenchingFactor << RESTendl;
460+
RESTMetadata << "Use quenching factor: " << (fUseQuenchingFactor ? "true" : "false") << RESTendl;
370461
RESTMetadata << "+++++" << RESTendl;
371462
}

0 commit comments

Comments
 (0)