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