TpcGas.cxx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. #include "TpcGas.h"
  2. #include <ostream>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <TRandom.h>
  6. #include "TError.h"
  7. //#include "ErrLogger/ErrLog.hh"
  8. TpcGas::TpcGas():_E(0),
  9. _B(0),
  10. _T(293.),
  11. _p(1024.),
  12. _VDrift(0),
  13. _Dl(0),
  14. _Dt(0),
  15. _k(0),
  16. _W(0),
  17. _CSD(0),
  18. _CSDNorm(0),
  19. _CSDEpol(0)
  20. {}
  21. TpcGas::TpcGas(double const E,
  22. double const B,
  23. double const T,
  24. double const p,
  25. double const VDrift,
  26. double const Dl,
  27. double const Dt,
  28. double const k,
  29. double const W,
  30. const std::vector<double>& CSD,
  31. double const CSDEpol):_E(E),
  32. _B(B),
  33. _T(T),
  34. _p(p),
  35. _VDrift(VDrift),
  36. _Dl(Dl),
  37. _Dt(Dt),
  38. _k(k),
  39. _W(W),
  40. _CSD(CSD),
  41. _CSDNorm(0),
  42. _CSDEpol(CSDEpol)
  43. {}
  44. TpcGas::TpcGas(const std::string& Filename, double const E)
  45. :_E(E)
  46. {
  47. //Reading the GasFile
  48. std::ifstream infile(Filename.c_str(), std::fstream::in);
  49. if (!infile.good())
  50. Fatal("TpcGas::TpcGas","Input File is not found");
  51. //ReadGasBegin returns the number of electric fields (and sets _T, _B, _p)
  52. int noent = ReadGasBegin(&infile);
  53. if (noent <= 0)
  54. Fatal("TpcGas::TpcGas","Number of electric fields nonpositive?\nCould not read File.\nExecution aborted.");
  55. double e[noent]; //E field in V/cm
  56. double vdrift[noent]; //e-drift velocity in cm/ns
  57. double dt[noent]; //transverse diffusion in sqrt(cm)
  58. double dl[noent]; //longitudinal diff. in sqrt(cm)
  59. double k[noent]; //attachment coefficient in 1/cm
  60. //ReadGasArrays returns the number of entries in cluster size distribution
  61. //and sets the values in the assigned arrays (and _W)
  62. int nCSDFile = ReadGasArrays(&infile, noent,
  63. e, vdrift, dt, dl, k);
  64. if (nCSDFile < 2)
  65. Fatal("TpcGas::TpcGas","Number of cluster sizes too small in File.\nExecution aborted.");
  66. //cluster size distribution: first entry is the rel. number of clusters with
  67. //1 electron,the last entry the rel. nr. of clusters with more than nCSDFile
  68. //so the last entry may not be transferred
  69. int _nCSD = nCSDFile-1; //omit the last
  70. _CSD.resize(_nCSD);
  71. _CSDNorm = 0;
  72. for (int i=0; i < _nCSD;i++) {
  73. infile >> _CSD[i];
  74. _CSDNorm += _CSD[i];
  75. }
  76. if (!infile.good())
  77. Fatal("TpcGas::TpcGas","Could not read cluster size distribution in File.\nExecution aborted.");
  78. infile.close();
  79. //file is read
  80. //Linear extrapolation to get the value at the right e field
  81. double inTable=GetPositionOfE(noent, e);
  82. /*The down rounded value of inTable is the index of the e field (in e)
  83. that is smaller than _E.
  84. (Exception: neg. Value , if _E is smaller than the smallest value in e)
  85. The decimal places render about the position between two entries in e*/
  86. if (inTable < 0 || inTable > noent -1)
  87. Warning("TpcGas::TpcGas","E field out of the range defined in input file");
  88. _VDrift = LinExpolation(inTable, vdrift, noent);
  89. _Dl = LinExpolation(inTable, dl, noent);
  90. _Dt = LinExpolation(inTable, dt, noent);
  91. _k = LinExpolation(inTable, k, noent);
  92. //Define the constant for the quadratic CSD extrapolation in such a way
  93. //that the csd is continous (the inverse quadratic approximation
  94. //is rather improper anyhow)
  95. _CSDEpol = _CSD[_nCSD-1]*(_nCSD-1)*(_nCSD-1);
  96. }
  97. TpcGas::~TpcGas(){}
  98. void TpcGas::operator=(const TpcGas& GasToCopy)
  99. {
  100. _VDrift = GasToCopy._VDrift;
  101. _Dl = GasToCopy._Dl;
  102. _Dt = GasToCopy._Dt;
  103. _k = GasToCopy._k;
  104. _W = GasToCopy._W;
  105. _CSDNorm= GasToCopy._CSDNorm;
  106. _CSDEpol= GasToCopy._CSDEpol;
  107. _E = GasToCopy._E;
  108. _B = GasToCopy._B;
  109. _T = GasToCopy._T;
  110. _p = GasToCopy._p;
  111. _CSD=GasToCopy._CSD;
  112. }
  113. // Use Uniform generator and correct bug with not properly normalized table
  114. int
  115. TpcGas::GetRandomCSUniform() const
  116. {
  117. double r = gRandom->Uniform();
  118. while (r > _CSDNorm )
  119. r = gRandom->Uniform();
  120. return GetRandomCS(r);
  121. }
  122. //return wrong number if r > overall sum
  123. int
  124. TpcGas::GetRandomCS(double const r) const {
  125. UInt_t i=0;
  126. double sum=_CSD[0];
  127. while(r>sum && ++i<_CSD.size()){
  128. sum+=_CSD[i];
  129. }
  130. if (_CSDEpol > 0)
  131. while(r>sum && i < 100)//sum could converge < 1
  132. {
  133. sum += _CSDEpol/i/i;
  134. i++;
  135. }
  136. return i + 1;
  137. }
  138. void
  139. TpcGas::SetCSD(const std::vector<double>& CSD)
  140. {
  141. _CSD=CSD;
  142. }
  143. std::ostream& operator<< (std::ostream& stream, const TpcGas& g)
  144. {
  145. stream << "--------------------------------------------------------\n"
  146. << "Tpc gas parameters: \n"
  147. << " drift velocity VDrift="<<g._VDrift<<"cm/ns \n"
  148. << " long.diffusion Dl ="<<g._Dl<<"sqrt(cm) \n"
  149. << " trans.diffusion Dt ="<<g._Dt<<"sqrt(cm) \n"
  150. << " attachment k ="<<g._k<<"1/cm\n"
  151. << " eff. ionisation W ="<<g._W<<"eV \n"
  152. << " ClusterSizeDistribution CSD:";
  153. for (int i=0; i<g.nCSD();i++)
  154. {
  155. if (i%3 == 0)
  156. stream<<"\n ";
  157. stream<<i+1<<": "<<g._CSD[i]<<" ";
  158. }
  159. stream << "\n"
  160. << " extrapol. const CSDEpol="<<g._CSDEpol
  161. << "\n"
  162. << "Gas parameters given for this environment: \n"
  163. << " drift field E="<<g._E<<"V/cm \n"
  164. << " magnetic field B="<<g._B<<"T \n"
  165. << " pressure p="<<g._p<<"mbar \n"
  166. << " temperature T="<<g._T<<"K \n"
  167. << "--------------------------------------------------------\n";
  168. return stream;
  169. }
  170. int
  171. TpcGas::ReadGasBegin(std::ifstream* const pinfile)
  172. {
  173. int noent = 0; //Nr. of E fields
  174. (*pinfile).ignore(256, '\n' );
  175. (*pinfile).ignore(256, '\n' );
  176. (*pinfile).ignore(256, '\n' );
  177. (*pinfile).ignore(256, ':');
  178. (*pinfile) >> _T; //temperature
  179. (*pinfile).ignore(256, ':');
  180. (*pinfile) >> _p; //pressure
  181. (*pinfile).ignore(256, ':');
  182. (*pinfile) >> _B; //b field
  183. (*pinfile).ignore(256, ':' );
  184. (*pinfile).ignore(256, ':');
  185. (*pinfile) >> noent;
  186. return(noent);
  187. }
  188. int
  189. TpcGas::ReadGasArrays(std::ifstream* const pinfile, int const noent,
  190. double* const e, double* const vdrift, double* const dt,
  191. double* const dl, double* const k)
  192. {
  193. int nCSDFile = 0; //Nr. of ClusterSizes
  194. for (int i=0; i < noent;i++)
  195. (*pinfile) >> e[i];
  196. (*pinfile).ignore(256, ':' );
  197. for (int i=0; i < noent;i++)
  198. (*pinfile) >> vdrift[i];
  199. (*pinfile).ignore(256, ':' );
  200. for (int i=0; i < noent;i++)
  201. (*pinfile) >> dt[i];
  202. (*pinfile).ignore(256, ':' );
  203. for (int i=0; i < noent;i++)
  204. (*pinfile) >> dl[i];
  205. (*pinfile).ignore(256, ':' );
  206. for (int i=0; i < noent;i++)
  207. (*pinfile) >> k[i];
  208. //ignore ion-mobility (in this version)
  209. (*pinfile).ignore(256, ':' );
  210. (*pinfile).ignore(256, '\n' );
  211. for (int i=0; i < noent;i++)
  212. (*pinfile).ignore(256, '\n' );
  213. //Cluster size distribution
  214. (*pinfile).ignore(512, ':' );
  215. (*pinfile) >> _W; //effective ionisation
  216. (*pinfile).ignore(512, ':');
  217. (*pinfile).ignore(256, ':');
  218. (*pinfile) >> nCSDFile;
  219. return(nCSDFile);
  220. }
  221. const double TpcGas::GetPositionOfE(int const noent, const double* const e)
  222. {
  223. double inTable = 0;
  224. for (int i = 0; i < noent; i++)
  225. {
  226. if (e[i] >= _E && i == 0)
  227. {
  228. if (noent > 1) inTable = i - (e[i]-_E)/(e[1]-e[0]); // FIX to prevent out of range
  229. break;
  230. }
  231. if (i == noent-1 || (e[i] >= _E && i != 0))
  232. {
  233. inTable = i - (e[i]-_E)/(e[i]-e[i-1]);
  234. break;
  235. }
  236. }
  237. return inTable;
  238. }
  239. const double TpcGas::LinExpolation(double const inTable, const double* const table,
  240. int const nTable)
  241. {
  242. if (nTable == 1)
  243. return(table[0]);
  244. else if (inTable <= 0)
  245. return(table[0] + inTable * (table[1]-table[0]));
  246. else if (inTable > nTable-1)
  247. return(table[nTable-1] +
  248. (inTable-nTable+1) * (table[nTable-1]-table[nTable-2]));
  249. else
  250. for (int i=1; i<nTable; i++)
  251. {
  252. if (i >= inTable)
  253. return(table[i] - (i-inTable) * (table[i]-table[i-1]));
  254. }
  255. return(0);//never reached; compiling without this I get an annoying warning
  256. }