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