GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
TNucleus.cxx
Go to the documentation of this file.
1// g++ -c -fPIC Nucleus.cc -I./ `root-config --cflags`
2
3#include "Globals.h"
4
5#include "TNucleus.h"
6#include <algorithm>
7#include <cstring>
8#include <sstream>
9
10#include <TClass.h>
11#include <TGraph.h>
12
13static double amu = 931.494043;
14
15std::string& TNucleus::Massfile()
16{
17 static std::string output = std::string(getenv("GRSISYS")) + "/libraries/TAnalysis/SourceData/mass.dat";
18 return output;
19}
20
21TNucleus::TNucleus(const char* name)
22{
23 // Creates a nucleus based on symbol (ex. 26Na OR Na26) and sets all parameters from mass.dat
24 int number = 0;
25 std::string symbol;
26 std::string element;
27 int z = 0;
28 int n = 0;
29 std::string sym_name;
30 double mass = 0.;
31 bool found = false;
32 std::string line;
33 std::ifstream infile;
34 std::string massFile;
35 ParseName(name, symbol, number, element);
36 try {
37 massFile = Massfile();
38 infile.open(massFile.c_str());
39 while(!getline(infile, line).fail()) {
40 if(line.length() < 1) {
41 continue;
42 }
43 std::istringstream ss(line);
44 ss >> n;
45 ss >> z;
46 ss >> sym_name;
47 ss >> mass;
48 if(strcasecmp(element.c_str(), sym_name.c_str()) == 0) {
49 found = true;
50 break;
51 }
52 }
53 } catch(std::out_of_range&) {
54 std::cout << "Could not parse element " << name << std::endl
55 << "Nucleus not Set!" << std::endl;
56 return;
57 }
58 if(!found) {
59 std::cout << "Warning: Element " << element << " not found in the mass table " << massFile << "." << std::endl
60 << "Nucleus not set!" << std::endl;
61 return;
62 }
63 infile.close();
64 SetZ(z);
65 SetN(n);
66 SetMassExcess(mass / 1000.0);
67 SetMass();
68 SetSymbol(symbol.c_str());
69 SetName();
71}
72
73TNucleus::TNucleus(int charge, int neutrons, double mass, const char* symbol)
74 : fN(neutrons), fZ(charge), fMass(mass), fSymbol(symbol)
75{
76 /// Creates a nucleus with Z, N, mass, and symbol
77 SetName();
79}
80
81TNucleus::TNucleus(int charge, int neutrons, const char* MassFile)
82 : fN(neutrons), fZ(charge)
83{
84 /// Creates a nucleus with Z, N using mass table (default MassFile = "mass.dat")
85 if(MassFile == nullptr) {
86 MassFile = Massfile().c_str();
87 }
88 int i = 0;
89 int n = 0;
90 int z = 0;
91 double emass = 0.;
92 std::string tmp;
93 std::ifstream mass_file;
94 mass_file.open(MassFile, std::ios::in);
95 while(!mass_file.bad() && !mass_file.eof() && i < 3008) {
96 mass_file >> n;
97 mass_file >> z;
98 mass_file >> tmp;
99 mass_file >> emass;
100 if(n == fN && z == fZ) {
101 fMassExcess = emass / 1000.;
102 fSymbol = tmp;
103#ifdef debug
104 std::cout << "Symbol " << fSymbol << " tmp " << tmp << std::endl;
105#endif
106 SetMass();
107 SetSymbol(fSymbol.c_str());
108 break;
109 }
110 i++;
111 mass_file.ignore(256, '\n');
112 }
113
114 mass_file.close();
115 std::string name = fSymbol;
116 std::string number = name.substr(0, name.find_first_not_of("0123456789 "));
117
118 name = name.substr(name.find_first_not_of("0123456789 "));
119 name.append(number);
120
121 SetName();
122 LoadTransitionFile();
123}
124
125void TNucleus::SetName(const char*)
126{
127 std::string name = GetSymbol();
128 name.append(std::to_string(GetA()));
129 TNamed::SetName(name.c_str());
130}
131
137
138void TNucleus::ParseName(std::string name, std::string& symbol, int& number, std::string& element)
139{
140 /// Strips any non-alphanumeric character from input, parses rest as number and symbol.
141 /// E.g. turns "na26" into "Na" and 26 or " 152 EU... " into "Eu" and 152.
142 /// Only uses the first number and first letter, so "na26 eu152" would be turned into "Na" and 26,
143 /// but "na26 152eu" would be turned into "Na" and 26152, and "26na 152eu" would be turned into "Na152eu" and 26.
144 /// Special inputs are "p" for "H" and 1, "d" for "H" and 2, "t" for "H" and 3, and "a" for "He" and 4.
145 /// element simply is the combined string of number and element.
146
147 // remove any characters that aren't alphanumeric
148 name.erase(std::remove_if(name.begin(), name.end(), [](char c) { return std::isalnum(c) == 0; }), name.end());
149
150 // special single letter cases
151 if(name.length() == 1) {
152 switch(name[0]) {
153 case 'p':
154 symbol.assign("H");
155 return;
156 case 'd':
157 symbol.assign("H");
158 return;
159 case 't':
160 symbol.assign("H");
161 return;
162 case 'a':
163 symbol.assign("He");
164 return;
165 default:
166 std::cout << "error, type numbersymbol, or symbolnumber, i.e. 30Mg oder Mg30, not " << name << std::endl;
167 return;
168 };
169 }
170
171 size_t firstDigit = name.find_first_of("0123456789");
172 size_t firstLetter = name.find_first_not_of("0123456789");
173 if(firstDigit > firstLetter) {
174 number = atoi(name.substr(firstDigit).c_str());
175 symbol.append(name.substr(firstLetter, firstDigit - firstLetter));
176 } else {
177 number = atoi(name.substr(firstDigit, firstLetter - firstDigit).c_str());
178 symbol.append(name.substr(firstLetter));
179 }
180 // make certain the symbol starts with upper case and rest is lower case by first transforming everything to lower case and then the first character to upper case.
181 std::transform(symbol.begin(), symbol.end(), symbol.begin(), ::tolower);
182 symbol[0] = toupper(symbol[0]);
183 element.append(std::to_string(number));
184 element.append(symbol);
185}
186
187std::string TNucleus::SortName(std::string input)
188{
189 /// Strips any non-alphanumeric character from input, parses rest as number and symbol.
190 /// E.g. turns "na26" into "26Na" or " 152 EU... " into "152Eu".
191 /// Special inputs are "p" for "1H", "d" for "2H", "t" for "2H", and "a" for "4He".
192 int number = 0;
193 std::string symbol;
194 std::string element;
195 ParseName(std::move(input), symbol, number, element);
196
197 return element;
198}
199
200void TNucleus::SetZ(int charge)
201{
202 // Sets the Z (# of protons) of the nucleus
203 fZ = charge;
204}
205void TNucleus::SetN(int neutrons)
206{
207 // Sets the N (# of neutrons) of the nucleus
208 fN = neutrons;
209}
210void TNucleus::SetMassExcess(double mass_ex)
211{
212 // Sets the mass excess of the nucleus (in MeV)
213 fMassExcess = mass_ex;
214}
215
216void TNucleus::SetMass(double mass)
217{
218 // Sets the mass manually (in MeV)
219 fMass = mass;
220}
221
223{
224 // Sets the mass based on the A and mass excess of nucleus (in MeV)
225 fMass = amu * GetA() + GetMassExcess();
226}
227
228void TNucleus::SetSymbol(const char* symbol)
229{
230 // Sets the atomic symbol for the nucleus
231 fSymbol = symbol;
232}
233
235{
236 // Figures out the Z of the nucleus based on the atomic symbol
237 std::array<std::array<char, 3>, 105> symbols = {{{"H"}, {"HE"}, {"LI"}, {"BE"}, {"B"}, {"C"}, {"N"}, {"O"}, {"F"}, {"NE"}, {"NA"}, {"MG"}, {"AL"}, {"SI"}, {"P"}, {"S"}, {"CL"}, {"AR"}, {"K"}, {"CA"}, {"SC"}, {"TI"}, {"V"}, {"CR"}, {"MN"}, {"FE"}, {"CO"}, {"NI"}, {"CU"}, {"ZN"}, {"GA"}, {"GE"}, {"AS"}, {"SE"}, {"BR"}, {"KR"}, {"RB"}, {"SR"}, {"Y"}, {"ZR"}, {"NB"}, {"MO"}, {"TC"}, {"RU"}, {"RH"}, {"PD"}, {"AG"}, {"CD"}, {"IN"}, {"SN"}, {"SB"}, {"TE"}, {"F"}, {"XE"}, {"CS"}, {"BA"}, {"LA"}, {"CE"}, {"PR"}, {"ND"}, {"PM"}, {"SM"}, {"EU"}, {"GD"}, {"TB"}, {"DY"}, {"HO"}, {"ER"}, {"TM"}, {"YB"}, {"LU"}, {"HF"}, {"TA"}, {"W"}, {"RE"}, {"OS"}, {"IR"}, {"PT"}, {"AU"}, {"HG"}, {"TI"}, {"PB"}, {"BI"}, {"PO"}, {"AT"}, {"RN"}, {"FR"}, {"RA"}, {"AC"}, {"TH"}, {"PA"}, {"U"}, {"NP"}, {"PU"}, {"AM"}, {"CM"}, {"BK"}, {"CF"}, {"ES"}, {"FM"}, {"MD"}, {"NO"}, {"LR"}, {"RF"}, {"HA"}}};
238 size_t length = strlen(symbol);
239 auto* search = new char[length + 1];
240 for(size_t i = 0; i < length; i++) {
241 search[i] = toupper(symbol[i]); // make sure symbol is in uppercase
242 }
243 search[length] = '\0';
244 for(int i = 0; i < 105; i++) {
245 if(strcmp(search, symbols[i].data()) == 0) {
246 delete[] search;
247 SetZ(i + 1);
248 return i + 1;
249 }
250 }
251
252 delete[] search;
253 SetZ(0);
254 return 0;
255}
256
258{
259 // Gets the radius of the nucleus (in fm).
260 // The radius is calculated using 1.12*A^1/3 - 0.94*A^-1/3
261 return 1.12 * pow(GetA(), 1. / 3.) - 0.94 * pow(GetA(), -1. / 3.);
262}
263
264void TNucleus::AddTransition(Double_t energy, Double_t intensity, Double_t energy_uncertainty,
265 Double_t intensity_uncertainty)
266{
267 auto* tran = new TTransition();
268 tran->SetEnergy(energy);
269 tran->SetEnergyUncertainty(energy_uncertainty);
270 tran->SetIntensity(intensity);
271 tran->SetIntensityUncertainty(intensity_uncertainty);
272
273 AddTransition(tran);
274}
275
277{
279 auto* tran2 = new TTransition(*tran);
280 tran2->SetCompareIntensity(false);
281 fTransitionListByEnergy.Add(tran2);
282}
283
285{
286 auto* tran = static_cast<TTransition*>(fTransitionListByIntensity.At(idx));
287 if(tran == nullptr) {
288 std::cout << "Out of Range" << std::endl;
289 }
290
291 return tran;
292}
293
295{
296 auto* tran = static_cast<TTransition*>(fTransitionListByEnergy.At(idx));
297 if(tran == nullptr) {
298 std::cout << "Out of Range" << std::endl;
299 }
300
301 return tran;
302}
303
304void TNucleus::Print(Option_t*) const
305{
306 // Prints out the Name of the nucleus, as well as the numerated transition list
307 std::cout << "Nucleus: " << GetName() << std::endl;
308 TIter next(&fTransitionListByIntensity);
309 int counter = 0;
310 while(auto* tran = static_cast<TTransition*>(next())) {
311 std::cout << "\t" << counter++ << "\t";
312 tran->Print();
313 }
314}
315
316void TNucleus::WriteSourceFile(const std::string& outfilename)
317{
318 if(outfilename.length() > 0) {
319 std::ofstream sourceout;
320 sourceout.open(outfilename.c_str());
321 for(int i = 0; i < fTransitionListByIntensity.GetSize(); i++) {
322 std::string transtr = (static_cast<TTransition*>(fTransitionListByIntensity.At(i)))->PrintToString();
323 sourceout << transtr.c_str();
324 sourceout << std::endl;
325 }
326 sourceout << std::endl;
327 sourceout.close();
328 }
329}
330
332{
333 if(fTransitionListByIntensity.GetSize() != 0) {
334 return false;
335 }
336 std::string filename;
337 filename = std::string(getenv("GRSISYS")) + "/libraries/TAnalysis/SourceData/";
338 std::string symbol = GetSymbol();
339 std::transform(symbol.begin(), symbol.end(), symbol.begin(), ::tolower);
340 filename.append(symbol);
341 filename.append(std::to_string(GetA()));
342 filename.append(".sou");
343 std::ifstream transfile;
344 transfile.open(filename.c_str());
345 if(!transfile.is_open()) {
346 std::cout << "failed to open source file: " << filename.c_str() << std::endl;
347 return false;
348 }
349
350 std::string line;
351
352 while(!getline(transfile, line).fail()) {
353 if(line.compare(0, 2, "//") == 0) {
354 continue;
355 }
356 if(line.compare(0, 1, "#") == 0) {
357 continue;
358 }
359 double temp = 0.;
360 auto* tran = new TTransition;
361 std::istringstream str(line);
362 int counter = 0;
363 while(!(str >> temp).fail()) {
364 counter++;
365 if(counter == 1) {
366 tran->SetEnergy(temp);
367 } else if(counter == 2) {
368 tran->SetEnergyUncertainty(temp);
369 } else if(counter == 3) {
370 tran->SetIntensity(temp);
371 } else if(counter == 4) {
372 tran->SetIntensityUncertainty(temp);
373 } else {
374 break;
375 }
376 }
377 AddTransition(tran);
378 }
379
381
382 return true;
383}
384
385double TNucleus::GetEnergyFromBeta(double beta) const
386{
387 double gamma = 1 / std::sqrt(1 - beta * beta);
388 return fMass * (gamma - 1);
389}
390
391double TNucleus::GetBetaFromEnergy(double energy_MeV) const
392{
393 double gamma = energy_MeV / fMass + 1;
394 double beta = std::sqrt(1 - 1 / (gamma * gamma));
395 return beta;
396}
static double amu
Definition TNucleus.cxx:13
void SetMass()
Sets the mass based on the A and mass excess of nucleus (in MeV)
Definition TNucleus.cxx:222
TSortedList fTransitionListByIntensity
Definition TNucleus.h:102
int GetA() const
Gets the A (Z + N) of the nucleus.
Definition TNucleus.h:63
void SetName(const char *name="") override
Definition TNucleus.cxx:125
double fMassExcess
Mass excess (in MeV)
Definition TNucleus.h:99
void SetZ(int)
Sets the Z (# of protons) of the nucleus.
Definition TNucleus.cxx:200
void AddTransition(Double_t energy, Double_t intensity, Double_t energy_uncertainty=0.0, Double_t intensity_uncertainty=0.0)
Definition TNucleus.cxx:264
TTransition * GetTransitionByIntensity(Int_t idx)
Definition TNucleus.cxx:284
void Print(Option_t *opt="") const override
Definition TNucleus.cxx:304
double fMass
Mass (in MeV)
Definition TNucleus.h:98
TNucleus()=default
Should not be used, here so we can write things to a root file.
double GetEnergyFromBeta(double beta) const
Definition TNucleus.cxx:385
bool LoadTransitionFile()
Definition TNucleus.cxx:331
double GetBetaFromEnergy(double energy_MeV) const
Definition TNucleus.cxx:391
int fN
Number of neutrons (N)
Definition TNucleus.h:96
int fZ
Number of protons (Z)
Definition TNucleus.h:97
void SetN(int)
Sets the N (# of neutrons) of the nucleus.
Definition TNucleus.cxx:205
double GetRadius() const
Definition TNucleus.cxx:257
void SetSymbol(const char *)
Sets the atomic symbol for the nucleus.
Definition TNucleus.cxx:228
TTransition * GetTransitionByEnergy(Int_t idx)
Definition TNucleus.cxx:294
static std::string & Massfile()
Returns the massfile to be used, which includes Z, N, atomic symbol, and mass excess.
Definition TNucleus.cxx:15
static void ParseName(const char *name, std::string &symbol, int &number, std::string &element)
Definition TNucleus.h:40
void WriteSourceFile(const std::string &outfilename="")
Definition TNucleus.cxx:316
static std::string SortName(const char *input)
Definition TNucleus.h:45
TSortedList fTransitionListByEnergy
Definition TNucleus.h:103
double GetMassExcess() const
Gets the mass excess of the nucleus (in MeV)
Definition TNucleus.h:64
void SetMassExcess(double)
Sets the mass excess of the nucleus (in MeV)
Definition TNucleus.cxx:210
std::string fSymbol
Atomic symbol (ex. Ba, C, O, N)
Definition TNucleus.h:100
const char * GetSymbol() const
Gets the atomic symbol of the nucleus.
Definition TNucleus.h:66
int GetZfromSymbol(char *)
Definition TNucleus.cxx:234