REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestAxionBufferGas.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
88
89#include "TRestAxionBufferGas.h"
90using namespace std;
91
92#include "TRestSystemOfUnits.h"
93using namespace REST_Units;
94
95ClassImp(TRestAxionBufferGas);
96
101
116TRestAxionBufferGas::TRestAxionBufferGas(const char* cfgFileName, string name) : TRestMetadata(cfgFileName) {
117 RESTDebug << "Entering TRestAxionBufferGas constructor( cfgFileName, name )" << RESTendl;
118
119 Initialize();
120
122}
123
128
133 SetSectionName(this->ClassName());
134 SetLibraryVersion(LIBRARY_VERSION);
135
136 fBufferGasName.clear();
137 fBufferGasDensity.clear();
138
139 fAbsEnergy.clear();
140 fGasAbsCoefficient.clear();
141
142 fFactorEnergy.clear();
143 fGasFormFactor.clear();
144}
145
150 this->Initialize();
151
152 auto gasDefinition = GetElement("gas");
153 while (gasDefinition) {
154 TString gasName = GetFieldValue("name", gasDefinition);
155 if (gasName.Contains("+")) {
156 TString gasDensity = GetFieldValue("density", gasDefinition);
157 SetGasMixture(gasName, gasDensity);
158 } else {
159 Double_t gasDensity = GetDblParameterWithUnits("density", gasDefinition);
160 SetGasDensity(gasName, gasDensity);
161 }
162 gasDefinition = GetNextElement(gasDefinition);
163 }
164
166}
167
173void TRestAxionBufferGas::SetGasDensity(TString gasName, Double_t density) {
174 Int_t gasIndex = FindGasIndex(gasName);
175
176 fBufferGasDensity[gasIndex] = density;
177}
178
190void TRestAxionBufferGas::SetGasMixture(TString gasMixture, TString gasDensities) {
191 Initialize();
192
193 std::vector<string> names = Split((string)gasMixture, "+");
194 std::vector<string> densities;
195 if (gasDensities == "0")
196 densities.clear();
197 else
198 densities = Split((string)gasDensities, "+");
199
200 if (!densities.empty() && names.size() == densities.size()) {
201 for (unsigned int n = 0; n < names.size(); n++) {
202 Double_t density = GetValueInRESTUnits(densities[n]);
203 SetGasDensity(names[n], density);
204 }
205 } else if (densities.empty()) {
206 for (unsigned int n = 0; n < names.size(); n++) {
207 SetGasDensity(names[n], 0);
208 }
209 } else {
210 this->SetError("SetGasMixture. Number of gases does not match the densities!");
211 }
212}
213
217Double_t TRestAxionBufferGas::GetGasDensity(TString gasName) {
218 Int_t gasIndex = FindGasIndex(gasName);
219
220 if (gasIndex < 0) {
221 RESTError << "TRestAxionBufferGas::GetGasDensity. Gas name : " << gasName << " not found!"
222 << RESTendl;
223 return 0;
224 }
225
226 return fBufferGasDensity[gasIndex];
227}
228
239void TRestAxionBufferGas::ReadGasData(TString gasName) {
240 TString factorFileName = SearchFile((string)gasName + ".nff");
241
242 RESTDebug << "TRestAxionBufferGas::ReadGasData. Reading factor file : " << factorFileName << RESTendl;
243
244 if (!TRestTools::fileExists((string)factorFileName)) {
245 RESTError << "TRestAxionBufferGas::ReadGasData( " << gasName << " )" << RESTendl;
246 RESTError << "Gas factor file not found : " << factorFileName << RESTendl;
247 exit(1);
248 }
249
250 /* {{{ Reading form factor values */
251 FILE* fin = fopen(factorFileName.Data(), "rt");
252
253 double en, value;
254
255 std::vector<Double_t> energyFactor;
256 std::vector<Double_t> factor;
257
258 // keV -- e/atom
259 while (fscanf(fin, "%lf\t%lf\n", &en, &value) != EOF) {
260 RESTDebug << "Energy : " << en << "keV -- Factor : " << value << RESTendl;
261
262 energyFactor.push_back(en);
263 factor.push_back(value);
264 }
265
266 RESTDebug << "Items read : " << energyFactor.size() << RESTendl;
267
268 fclose(fin);
269 /* }}} */
270
271 TString absFileName = SearchFile((string)gasName + ".abs");
272
273 RESTDebug << "TRestAxionBufferGas::ReadGasData. Reading factor file : " << absFileName << RESTendl;
274
275 if (!TRestTools::fileExists((string)absFileName)) {
276 RESTError << "TRestAxionBufferGas::ReadGasData( " << gasName << " )" << RESTendl;
277 RESTError << "Gas absorption file not found : " << absFileName << RESTendl;
278 exit(1);
279 }
280
281 /* {{{ Reading absorption values */
282 fin = fopen(absFileName.Data(), "rt");
283
284 std::vector<Double_t> energyAbs;
285 std::vector<Double_t> absorption;
286
287 // keV -- e/atom
288 while (fscanf(fin, "%lf\t%lf\n", &en, &value) != EOF) {
289 RESTDebug << "Energy : " << en << "keV -- Absorption : " << value << RESTendl;
290
291 energyAbs.push_back(en);
292 absorption.push_back(value);
293 }
294
295 RESTDebug << "Items read : " << energyAbs.size() << RESTendl;
296
297 fclose(fin);
298 /* }}} */
299
300 fBufferGasName.push_back(gasName);
301
302 fFactorEnergy.push_back(energyFactor);
303 fGasFormFactor.push_back(factor);
304
305 fAbsEnergy.push_back(energyAbs);
306 fGasAbsCoefficient.push_back(absorption);
307
308 fBufferGasDensity.push_back(0);
309}
310
316Double_t TRestAxionBufferGas::GetFormFactor(TString gasName, Double_t energy) {
317 // In case we are in vacuum
318 if (GetNumberOfGases() == 0) return 0;
319
320 Int_t gasIndex = FindGasIndex(gasName);
321 RESTDebug << "TRestAxionBufferGas::GetFormFactor. Gas index = " << gasIndex << RESTendl;
322
323 if (gasIndex == -1) {
324 ReadGasData(gasName);
325 gasIndex = FindGasIndex(gasName);
326 }
327
328 if (gasIndex == -1) {
329 RESTError << "TRestAxionBufferGas::GetFormFactor. Gas: " << gasName << " Not Found!" << RESTendl;
330 exit(1);
331 }
332
333 Int_t energyIndex = GetEnergyIndex(fFactorEnergy[gasIndex], energy);
334 RESTDebug << "Energy index : " << energyIndex << RESTendl;
335
336 if (energyIndex == -1) {
337 RESTError << "TRestAxionBufferGas::GetFormFactor. Energy (" << energy << " keV) out of range"
338 << RESTendl;
339 exit(1);
340 }
341
342 // Absorption coefficient
343 double y2 = fGasFormFactor[gasIndex][energyIndex + 1];
344 double y1 = fGasFormFactor[gasIndex][energyIndex];
345
346 // Normalized field
347 double x2 = fFactorEnergy[gasIndex][energyIndex + 1];
348 double x1 = fFactorEnergy[gasIndex][energyIndex];
349
350 double m = (y2 - y1) / (x2 - x1);
351 double n = y1 - m * x1;
352
353 if (m * energy + n < 0) {
354 RESTError << "TRestAxionBufferGas::GetAbsorptionCoefficient. Negative coefficient" << RESTendl;
355 cout << "y2 : " << y2 << " y1 : " << y1 << endl;
356 cout << "x2 : " << x2 << " x1 : " << x1 << endl;
357 cout << "m : " << m << " n : " << n << endl;
358 cout << "E : " << energy << " bin : " << energyIndex << endl;
359 GetChar();
360 }
361
362 return (m * energy + n);
363}
364
370 Double_t attLength = 0;
371 for (unsigned int n = 0; n < fBufferGasName.size(); n++)
372 attLength +=
374
375 return attLength;
376}
377
383 return cmToeV(GetPhotonAbsorptionLength(energy));
384}
385
389Double_t TRestAxionBufferGas::cmToeV(double l_Inv) // E in keV, P in bar ---> Gamma in cm-1
390{
391 return l_Inv / REST_Physics::PhMeterIneV / 0.01;
392}
393
399 Double_t photonMass = 0;
400
401 if (fBufferGasName.empty())
402 RESTError << "TRestAxionBufferGas::GetDensityForMass gas has not been defined!" << RESTendl;
403
404 for (unsigned int n = 0; n < fBufferGasName.size(); n++) {
405 Double_t W_value = 0;
406 if (fBufferGasName[n] == "H") W_value = 1.00794; // g/mol
407 if (fBufferGasName[n] == "He") W_value = 4.002; // g/mol
408 if (fBufferGasName[n] == "Ne") W_value = 20.179; // g/mol
409 if (fBufferGasName[n] == "Ar") W_value = 39.948; // g/mol
410 if (fBufferGasName[n] == "Xe") W_value = 131.293; // g/mol
411
412 if (W_value == 0) {
413 RESTError << "Gas name : " << fBufferGasName[n] << " is not implemented in TRestBufferGas!!"
414 << RESTendl;
415 RESTError << "W value must be defined in TRestAxionBufferGas::GetPhotonMass" << RESTendl;
416 RESTError << "This gas will not contribute to the calculation of the photon mass!" << RESTendl;
417 } else {
418 photonMass +=
419 fBufferGasDensity[n] * units("g/cm^3") * GetFormFactor(fBufferGasName[n], en) / W_value;
420 }
421 }
422
423 return 28.77 * TMath::Sqrt(photonMass);
424}
425
436Double_t TRestAxionBufferGas::GetDensityForMass(double m_gamma, double en) {
437 Double_t massDensity = 0;
438
439 if (fBufferGasName.empty())
440 RESTError << "TRestAxionBufferGas::GetDensityForMass gas has not been defined!" << RESTendl;
441
442 if (fBufferGasName.size() > 1)
443 RESTError << "TRestAxionBufferGas::GetDensityForMass gas this method is only for sinale gas mixtures!"
444 << RESTendl;
445
446 Double_t W_value = 0;
447 if (fBufferGasName[0] == "H") W_value = 1.00794; // g/mol
448 if (fBufferGasName[0] == "He") W_value = 4.002; // g/mol
449 if (fBufferGasName[0] == "Ne") W_value = 20.179; // g/mol
450 if (fBufferGasName[0] == "Ar") W_value = 39.948; // g/mol
451 if (fBufferGasName[0] == "Xe") W_value = 131.293; // g/mol
452
453 if (W_value == 0) {
454 RESTError << "Gas name : " << fBufferGasName[0] << " is not implemented in TRestAxionBufferGas!!"
455 << RESTendl;
456 RESTError << "W value must be defined in TRestAxionBufferGas::GetDensityForMass" << RESTendl;
457 RESTError << "This gas will not contribute to the calculation of the photon mass!" << RESTendl;
458
459 } else {
460 massDensity += pow(m_gamma, 2) * W_value / (GetFormFactor(fBufferGasName[0], en) * pow(28.77, 2));
461 }
462
463 return massDensity / units("g/cm^3");
464}
465
470Double_t TRestAxionBufferGas::GetAbsorptionCoefficient(TString gasName, Double_t energy) {
471 Int_t gasIndex = FindGasIndex(gasName);
472 RESTDebug << "TRestAxionBufferGas::GetAbsorptionCoefficient. Gas index = " << gasIndex << RESTendl;
473
474 if (gasIndex == -1) {
475 ReadGasData(gasName);
476 gasIndex = FindGasIndex(gasName);
477 }
478
479 if (gasIndex == -1) {
480 RESTError << "TRestAxionBufferGas::GetAbsorptionCoefficient. Gas: " << gasName << " Not Found!"
481 << RESTendl;
482 exit(1);
483 }
484
485 Int_t energyIndex = GetEnergyIndex(fAbsEnergy[gasIndex], energy);
486 RESTDebug << "Energy index : " << energyIndex << RESTendl;
487
488 if (energyIndex == -1) {
489 RESTError << "TRestAxionBufferGas::GetAbsorptionCoefficient. Energy out of range" << RESTendl;
490 exit(1);
491 }
492
493 // Absorption coefficient
494 double y2 = fGasAbsCoefficient[gasIndex][energyIndex + 1];
495 double y1 = fGasAbsCoefficient[gasIndex][energyIndex];
496
497 // Normalized field
498 double x2 = fAbsEnergy[gasIndex][energyIndex + 1];
499 double x1 = fAbsEnergy[gasIndex][energyIndex];
500
501 double m = (y2 - y1) / (x2 - x1);
502 double n = y1 - m * x1;
503
504 if (m * energy + n < 0) {
505 RESTError << "TRestAxionBufferGas::GetAbsorptionCoefficient. Negative coeffient" << RESTendl;
506 cout << "y2 : " << y2 << " y1 : " << y1 << endl;
507 cout << "x2 : " << x2 << " x1 : " << x1 << endl;
508 cout << "m : " << m << " n : " << n << endl;
509 cout << "E : " << energy << " bin : " << energyIndex << endl;
510 GetChar();
511 }
512
513 return (m * energy + n);
514}
515
519Int_t TRestAxionBufferGas::GetEnergyIndex(std::vector<Double_t> enVector, Double_t energy) {
520 for (unsigned int n = 0; n < enVector.size(); n++)
521 if (energy < enVector[n]) return n - 1;
522
523 return -1;
524}
525
529Int_t TRestAxionBufferGas::FindGasIndex(TString gasName) {
530 Int_t nGases = (Int_t)fBufferGasName.size();
531
532 for (int n = 0; n < nGases; n++)
533 if (fBufferGasName[n] == gasName) return n;
534
535 // If the gas is not found in the list we just force reading it from its gas datafile.
536 ReadGasData(gasName);
537
538 return FindGasIndex(gasName);
539}
540
546 Int_t gasIndex = FindGasIndex(gasName);
547
548 for (unsigned int n = 0; n < fAbsEnergy[gasIndex].size(); n++)
549 cout << "energy : " << fAbsEnergy[gasIndex][n]
550 << " -- abs coeff : " << fGasAbsCoefficient[gasIndex][n] << endl;
551}
552
558 Int_t gasIndex = FindGasIndex(gasName);
559
560 for (unsigned int n = 0; n < fAbsEnergy[gasIndex].size(); n++)
561 cout << "Energy : " << fFactorEnergy[gasIndex][n] << " -- Abs coeff : " << fGasFormFactor[gasIndex][n]
562 << endl;
563}
564
570
571 RESTMetadata << "Number of buffer gases defined : " << fBufferGasName.size() << RESTendl;
572 if (fBufferGasName.size() == 0) {
573 RESTMetadata << "Buffer medium is vacuum" << RESTendl;
574 } else {
575 RESTMetadata << "Photon mass at 4keV : " << this->GetPhotonMass(4.) << " eV" << RESTendl;
576 RESTMetadata << " " << RESTendl;
577 RESTMetadata << "Buffer gases inside mixture : " << RESTendl;
578 RESTMetadata << "---------------------------" << RESTendl;
579 for (unsigned int n = 0; n < fBufferGasName.size(); n++) {
580 RESTMetadata << " Gas name : " << fBufferGasName[n] << RESTendl;
581 RESTMetadata << " Gas density : " << fBufferGasDensity[n] * units("g/cm^3") << " g/cm3"
582 << RESTendl;
583 RESTMetadata << " Form factor energy range : ( " << fFactorEnergy[n][0] << ", "
584 << fFactorEnergy[n].back() << " ) keV" << RESTendl;
585 RESTMetadata << " Absorption energy range : ( " << fAbsEnergy[n][0] << ", "
586 << fAbsEnergy[n].back() << " ) keV" << RESTendl;
587 RESTMetadata << " " << RESTendl;
588 }
589 }
590
591 RESTMetadata << "+++++++++++++++++++++++++++++++++++++++++++++++++" << RESTendl;
592}
A metadata class to define the gas properties used in axion search calculations.
TRestAxionBufferGas()
Default constructor.
Int_t GetNumberOfGases()
It returns the number of gases in the mixture.
void Initialize()
Initialization of TRestAxionBufferGas members. It removes all gases.
void InitFromConfigFile()
Initialization of TRestAxionBufferGas field members through a RML file.
void PrintMetadata()
Prints on screen the information about the metadata members of TRestAxionBufferGas.
Double_t cmToeV(double l_Inv)
It transforms cm-1 to eV.
std::vector< std::vector< Double_t > > fGasFormFactor
Gas form factor.
void PrintFormFactorGasData(TString gasName)
Prints out the atomic form factors as function of the energy for the given gas component,...
std::vector< std::vector< Double_t > > fGasAbsCoefficient
Gas absorption coefficient in cm2/g.
Int_t GetEnergyIndex(std::vector< Double_t > enVector, Double_t energy)
It returns the vector element index, from enVector, that is just below the given input energy.
Double_t GetPhotonMass(double en)
It returns the equivalent photon mass (in eV) for the gas mixture at the given input energy expressed...
std::vector< std::vector< Double_t > > fFactorEnergy
Energy values for gas form factor in keV.
std::vector< Double_t > fBufferGasDensity
Gas density of the corresponding gasName in g/cm3.
Double_t GetGasDensity(TString gasName)
It returns the gas density - from the chosen gasName component - in g/cm3.
void ReadGasData(TString gasName)
It reads the data files from the corresponding gas component.
Double_t GetDensityForMass(double m_gamma, double en=4.2)
It returns the equivalent gas density for a given photon mass expressed in eV and a given axion energ...
void SetGasDensity(TString gasName, Double_t density)
It adds a new gas component to the mixture. If it already exists it will update its density.
Int_t FindGasIndex(TString gName)
It returns the internal index of the gas component given by gasName.
std::vector< TString > fBufferGasName
Name of the buffer gas (He, Ne, Ar, Xe, ..., etc )
void PrintAbsorptionGasData(TString gasName)
Prints out the absorption coefficients as function of the energy for the given gas component,...
Double_t GetPhotonAbsorptionLengthIneV(Double_t energy)
It returns the inverse of the absorption lenght, for the gas mixture, in eV, for the given energy in ...
void SetGasMixture(TString gasMixture, TString gasDensities="0")
It re-initializes the gas mixture to the one provided by argument.
std::vector< std::vector< Double_t > > fAbsEnergy
Energy values for gas absorption coefficient in keV.
Double_t GetAbsorptionCoefficient(TString gasName, Double_t energy)
It returns the absorption coefficient, in cm2/g, for the given gas component and energy in keV.
Double_t GetFormFactor(TString gasName, Double_t energy)
It returns the atomic form factor of the gasName component at the given energy.
Double_t GetPhotonAbsorptionLength(Double_t energy)
It returns the inverse of the absorption lenght, for the gas mixture, in cm-1, for the given energy i...
~TRestAxionBufferGas()
Default destructor.
A base class for any REST metadata class.
Definition: TRestMetadata.h:70
virtual void PrintMetadata()
Implemented it in the derived metadata class to print out specific metadata information.
endl_t RESTendl
Termination flag object for TRestStringOutput.
TiXmlElement * GetElement(std::string eleDeclare, TiXmlElement *e=nullptr)
Get an xml element from a given parent element, according to its declaration.
Int_t LoadConfigFromFile(const std::string &configFilename, const std::string &sectionName="")
Give the file name, find out the corresponding section. Then call the main starter.
void SetLibraryVersion(TString version)
Set the library version of this metadata class.
TRestStringOutput::REST_Verbose_Level GetVerboseLevel()
returns the verboselevel in type of REST_Verbose_Level enumerator
std::string GetFieldValue(std::string parName, TiXmlElement *e)
Returns the field value of an xml element which has the specified name.
void SetSectionName(std::string sName)
set the section name, clear the section content
std::string SearchFile(std::string filename)
Search files in current directory and directories specified in "searchPath" section.
std::string fConfigFileName
Full name of the rml file.
void SetError(std::string message="", bool print=true, int maxPrint=5)
A metadata class may use this method to signal that something went wrong.
TiXmlElement * GetNextElement(TiXmlElement *e)
Get the next sibling xml element of this element, with same eleDeclare.
@ REST_Info
+show most of the information for each steps
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
Definition: TRestTools.cxx:728
constexpr double PhMeterIneV
A meter in eV.
Definition: TRestPhysics.h:52
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
std::vector< std::string > Split(std::string in, std::string separator, bool allowBlankString=false, bool removeWhiteSpaces=false, int startPos=-1)
Split the input string according to the given separator. Returning a vector of fragments.
This namespace defines the unit conversion for different units which are understood by REST.
Double_t GetValueInRESTUnits(std::string in)
It scales a physics measurement with its units into a REST default units value.