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"
90 using namespace std;
91 
92 #include "TRestSystemOfUnits.h"
93 using namespace REST_Units;
94 
95 ClassImp(TRestAxionBufferGas);
96 
101 
116 TRestAxionBufferGas::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 
173 void TRestAxionBufferGas::SetGasDensity(TString gasName, Double_t density) {
174  Int_t gasIndex = FindGasIndex(gasName);
175 
176  fBufferGasDensity[gasIndex] = density;
177 }
178 
190 void 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 
217 Double_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 
239 void 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 
316 Double_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 +=
373  fBufferGasDensity[n] * units("g/cm^3") * GetAbsorptionCoefficient(fBufferGasName[n], energy);
374 
375  return attLength;
376 }
377 
383  return cmToeV(GetPhotonAbsorptionLength(energy));
384 }
385 
389 Double_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 
436 Double_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 
470 Double_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 
519 Int_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 
529 Int_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:74
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.