mirror of
https://github.com/gwm17/PunchTable.git
synced 2024-11-22 10:18:51 -05:00
First commit
This commit is contained in:
commit
11cb738ce7
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
build/
|
||||||
|
bin/
|
||||||
|
lib/
|
||||||
|
include/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
*.o
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.a
|
||||||
|
*.dll
|
||||||
|
*.lib
|
||||||
|
*.root
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
|
||||||
|
!.gitignore
|
10
CMakeLists.txt
Normal file
10
CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(PunchTable)
|
||||||
|
|
||||||
|
set(CXX_STANDARD 17)
|
||||||
|
|
||||||
|
set(PUNCHTABLE_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin)
|
||||||
|
|
||||||
|
add_subdirectory(src/vendor/catima)
|
||||||
|
add_subdirectory(src)
|
2501
etc/mass.txt
Normal file
2501
etc/mass.txt
Normal file
File diff suppressed because it is too large
Load Diff
17
src/CMakeLists.txt
Normal file
17
src/CMakeLists.txt
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
add_executable(PunchTable)
|
||||||
|
target_include_directories(PunchTable PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
target_sources(PunchTable PRIVATE
|
||||||
|
CubicSpline.h
|
||||||
|
CubicSpline.cpp
|
||||||
|
MassLookup.h
|
||||||
|
MassLookup.cpp
|
||||||
|
PunchTable.h
|
||||||
|
PunchTable.cpp
|
||||||
|
GenerateTable.h
|
||||||
|
GenerateTable.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(PunchTable catima)
|
||||||
|
|
||||||
|
set_target_properties(PunchTable PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PUNCHTABLE_BINARY_DIR})
|
235
src/CubicSpline.cpp
Normal file
235
src/CubicSpline.cpp
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
CubicSpline.cpp
|
||||||
|
Class for generating cubic splines of data in tables or held in memory. Cubic splines are a form of interpolation,
|
||||||
|
somewhat more advanced than linear interpolation, but not so complicated that it significantly slows down a calculation.
|
||||||
|
For more information see Wikipedia or Num. Rec. in C.
|
||||||
|
|
||||||
|
Gordon M. May 2021
|
||||||
|
*/
|
||||||
|
#include "CubicSpline.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace PunchTable {
|
||||||
|
|
||||||
|
CubicSpline::CubicSpline() :
|
||||||
|
m_validFlag(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CubicSpline::CubicSpline(const std::string& filename) :
|
||||||
|
m_validFlag(false)
|
||||||
|
{
|
||||||
|
ReadFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
CubicSpline::CubicSpline(const std::vector<double>& x, const std::vector<double>& y) :
|
||||||
|
m_validFlag(false)
|
||||||
|
{
|
||||||
|
ReadData(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
CubicSpline::~CubicSpline() {}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Expected file format is a naked (no header) single space separated table:
|
||||||
|
x y\n
|
||||||
|
*/
|
||||||
|
void CubicSpline::ReadFile(const std::string& filename)
|
||||||
|
{
|
||||||
|
std::ifstream input(filename);
|
||||||
|
if(!input.is_open()) {
|
||||||
|
std::cerr<<"Unable to open input data at CubicSpline::ReadFile from filename: "<<filename<<std::endl;
|
||||||
|
m_validFlag = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string junk;
|
||||||
|
//std::getline(input, junk);
|
||||||
|
|
||||||
|
double x, y;
|
||||||
|
while(input>>x)
|
||||||
|
{
|
||||||
|
input>>y;
|
||||||
|
m_dataX.push_back(x);
|
||||||
|
m_dataY.push_back(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_dataX.size() != m_dataY.size())
|
||||||
|
{
|
||||||
|
std::cerr<<"Error in CubicSpline::ReadFile! Number of x points not equal to number of y points!"<<std::endl;
|
||||||
|
m_validFlag = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_validFlag = true;
|
||||||
|
|
||||||
|
input.close();
|
||||||
|
|
||||||
|
MakeSplines();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
After data is read in splines can be solved. Each data point is referred to as a knot. Endpoint conditions are
|
||||||
|
derivatives of neighbors must be equal and second derivatives must be zero (natural cubic splines). Solved using gaussian elimination.
|
||||||
|
*/
|
||||||
|
void CubicSpline::MakeSplines()
|
||||||
|
{
|
||||||
|
if(!m_validFlag)
|
||||||
|
{
|
||||||
|
std::cerr<<"Error at CubicSpline::MakeSplines! Unable to generate splines without first initializing data."<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int knots = m_dataX.size();
|
||||||
|
|
||||||
|
//Matrix and vector data init
|
||||||
|
double** a = new double*[knots];
|
||||||
|
for(int i=0; i<knots; i++)
|
||||||
|
a[i] = new double[knots];
|
||||||
|
double* b = new double[knots];
|
||||||
|
double* k = new double[knots];
|
||||||
|
|
||||||
|
Spline s;
|
||||||
|
m_splines.clear();
|
||||||
|
double x0, x1, x2;
|
||||||
|
double y0, y1, y2;
|
||||||
|
|
||||||
|
//Setup matrix eqn.
|
||||||
|
for(int i=0; i<knots; i++)
|
||||||
|
{
|
||||||
|
if(i == 0)
|
||||||
|
{
|
||||||
|
x1 = m_dataX[i];
|
||||||
|
x2 = m_dataX[i+1];
|
||||||
|
y1 = m_dataY[i];
|
||||||
|
y2 = m_dataY[i+1];
|
||||||
|
a[i][i] = 2.0/(x2-x1);
|
||||||
|
a[i][i+1] = 1.0/(x2-x1);
|
||||||
|
b[i] = 3.0*(y2-y1)/(std::pow((x2-x1), 2.0));
|
||||||
|
s.x1 = x1; s.x2 = x2;
|
||||||
|
s.y1 = y1; s.y2 = y2;
|
||||||
|
m_splines.push_back(s);
|
||||||
|
}
|
||||||
|
else if(i == (knots-1))
|
||||||
|
{
|
||||||
|
x0 = m_dataX[i-1];
|
||||||
|
x1 = m_dataX[i];
|
||||||
|
y0 = m_dataY[i-1];
|
||||||
|
y1 = m_dataY[i];
|
||||||
|
a[i][i-1] = 1.0/(x1-x0);
|
||||||
|
a[i][i] = 2.0/(x1-x0);
|
||||||
|
b[i] = 3.0*(y1-y0)/(std::pow((x1-x0), 2.0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x0 = m_dataX[i-1];
|
||||||
|
x1 = m_dataX[i];
|
||||||
|
x2 = m_dataX[i+1];
|
||||||
|
y0 = m_dataY[i-1];
|
||||||
|
y1 = m_dataY[i];
|
||||||
|
y2 = m_dataY[i+1];
|
||||||
|
a[i][i-1] = 1.0/(x1-x0);
|
||||||
|
a[i][i] = 2.0/(x1-x0)+2.0/(x2-x1);
|
||||||
|
a[i][i+1] = 1.0/(x2-x1);
|
||||||
|
b[i] = 3.0*(y1-y0)/(std::pow((x1-x0), 2.0))+3.0*(y2-y1)/(std::pow((x2-x1), 2.0));
|
||||||
|
s.x1 = x1; s.x2 = x2;
|
||||||
|
s.y1 = y1; s.y2 = y2;
|
||||||
|
m_splines.push_back(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//solve for curvature vector k using gaussian elimination
|
||||||
|
a[0][1] /= a[0][0];
|
||||||
|
b[0] /= a[0][0];
|
||||||
|
for(int i=1; i<(knots-1); i++)
|
||||||
|
{
|
||||||
|
a[i][i+1] /= a[i][i]-a[i][i-1]*a[i-1][i];
|
||||||
|
b[i] = (b[i] - a[i][i-1]*b[i-1])/(a[i][i]-a[i][i-1]*a[i-1][i]);
|
||||||
|
}
|
||||||
|
int g1 = knots-1;
|
||||||
|
int g2 = knots-2;
|
||||||
|
b[g1] = (b[g1]-a[g1][g2]*b[g2])/(a[g1][g1]-a[g1][g2]*a[g2][g1]);
|
||||||
|
|
||||||
|
k[g1] = b[g1];
|
||||||
|
for(int i=(knots-2); i>=0; i--)
|
||||||
|
k[i] = b[i] - a[i][i+1]*k[i+1];
|
||||||
|
|
||||||
|
//Fill the spline data
|
||||||
|
for(size_t i=0; i<m_splines.size(); i++)
|
||||||
|
{
|
||||||
|
m_splines[i].k1 = k[i];
|
||||||
|
m_splines[i].k2 = k[i+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
//deallocate
|
||||||
|
delete[] b;
|
||||||
|
delete[] k;
|
||||||
|
for(int i=0; i<knots; i++)
|
||||||
|
delete[] a[i];
|
||||||
|
delete[] a;
|
||||||
|
}
|
||||||
|
|
||||||
|
double CubicSpline::Evaluate(double x)
|
||||||
|
{
|
||||||
|
if(!m_validFlag)
|
||||||
|
{
|
||||||
|
std::cerr<<"Error at CubicSpline::Evaluate! Unable to evaluate without first generating splines."<<std::endl;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Spline s;
|
||||||
|
for(size_t i=0; i<m_splines.size(); i++)
|
||||||
|
{
|
||||||
|
auto& spline = m_splines[i];
|
||||||
|
if(x >= spline.x1 && x <= spline.x2)
|
||||||
|
{
|
||||||
|
s = spline;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (i == (m_splines.size() -1))
|
||||||
|
{
|
||||||
|
//std::cerr<<"Error at CubicSpline::Evaluate! Input x value: "<<x<<" is not within the spline range min: "<<splines[0].x1<<" max: "<<splines[splines.size()-1].x2<<std::endl;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double t = (x-s.x1)/(s.x2-s.x1);
|
||||||
|
double a = s.k1*(s.x2-s.x1)-(s.y2-s.y1);
|
||||||
|
double b = -s.k2*(s.x2-s.x1)+(s.y2-s.y1);
|
||||||
|
return (1.0-t)*s.y1+t*s.y2+t*(1.0-t)*((1.0-t)*a+t*b);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Purely for plotting in ROOT, do not use for caluculations.
|
||||||
|
double CubicSpline::EvaluateROOT(double* x, double* p)
|
||||||
|
{
|
||||||
|
if(!m_validFlag)
|
||||||
|
{
|
||||||
|
std::cerr<<"Error at CubicSpline::EvaluateROOT! Unable to evaluate without first generating splines."<<std::endl;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double xval = x[0];
|
||||||
|
Spline s;
|
||||||
|
for(size_t i=0; i<m_splines.size(); i++)
|
||||||
|
{
|
||||||
|
auto& spline = m_splines[i];
|
||||||
|
if(xval >= spline.x1 && xval <= spline.x2)
|
||||||
|
{
|
||||||
|
s = spline;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (i == (m_splines.size() -1))
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double t = (xval-s.x1)/(s.x2-s.x1);
|
||||||
|
double a = s.k1*(s.x2-s.x1)-(s.y2-s.y1);
|
||||||
|
double b = -s.k2*(s.x2-s.x1)+(s.y2-s.y1);
|
||||||
|
return (1.0-t)*s.y1+t*s.y2+t*(1.0-t)*((1.0-t)*a+t*b);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
55
src/CubicSpline.h
Normal file
55
src/CubicSpline.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
CubicSpline.h
|
||||||
|
Class for generating cubic splines of data in tables or held in memory. Cubic splines are a form of interpolation,
|
||||||
|
somewhat more advanced than linear interpolation, but not so complicated that it significantly slows down a calculation.
|
||||||
|
For more information see Wikipedia or Num. Rec. in C.
|
||||||
|
|
||||||
|
Gordon M. May 2021
|
||||||
|
*/
|
||||||
|
#ifndef CUBICSPLINE_H
|
||||||
|
#define CUBICSPLINE_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace PunchTable {
|
||||||
|
|
||||||
|
//struct holding final spline info
|
||||||
|
struct Spline
|
||||||
|
{
|
||||||
|
double y1=0, y2=0;
|
||||||
|
double x1=0, x2=0;
|
||||||
|
double k1=0, k2=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CubicSpline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CubicSpline();
|
||||||
|
CubicSpline(const std::string& filename);
|
||||||
|
CubicSpline(const std::vector<double>& x, const std::vector<double>& y);
|
||||||
|
~CubicSpline();
|
||||||
|
void ReadFile(const std::string& filename);
|
||||||
|
inline void ReadData(const std::vector<double>& x, const std::vector<double>& y)
|
||||||
|
{
|
||||||
|
m_dataX = x;
|
||||||
|
m_dataY = y;
|
||||||
|
m_validFlag=true;
|
||||||
|
MakeSplines();
|
||||||
|
}
|
||||||
|
bool IsValid() { return m_validFlag; }
|
||||||
|
double Evaluate(double x);
|
||||||
|
double EvaluateROOT(double* x, double* p); //for plotting as ROOT function
|
||||||
|
|
||||||
|
private:
|
||||||
|
void MakeSplines();
|
||||||
|
|
||||||
|
std::vector<double> m_dataX;
|
||||||
|
std::vector<double> m_dataY;
|
||||||
|
std::vector<Spline> m_splines;
|
||||||
|
|
||||||
|
bool m_validFlag;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
11
src/GenerateTable.cpp
Normal file
11
src/GenerateTable.cpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "GenerateTable.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace PunchTable {
|
||||||
|
|
||||||
|
void GenerateTable(const TableParameters& params)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
29
src/GenerateTable.h
Normal file
29
src/GenerateTable.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef GENERATE_TABLE_H
|
||||||
|
#define GENERATE_TABLE_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace PunchTable {
|
||||||
|
|
||||||
|
struct TableParameters
|
||||||
|
{
|
||||||
|
double minKE;
|
||||||
|
double maxKE;
|
||||||
|
double stepKE;
|
||||||
|
double minTheta;
|
||||||
|
double maxTheta;
|
||||||
|
double stepTheta;
|
||||||
|
int projectileZ;
|
||||||
|
int projectileA;
|
||||||
|
std::vector<std::vector<int>> targetZ;
|
||||||
|
std::vector<std::vector<int>> targetA;
|
||||||
|
std::vector<std::vector<int>> targetS;
|
||||||
|
double targetThickness;
|
||||||
|
std::string filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
void GenerateTable(const TableParameters& params);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
73
src/MassLookup.cpp
Normal file
73
src/MassLookup.cpp
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
MassLookup.h
|
||||||
|
Generates a map for isotopic masses using AMDC data; subtracts away
|
||||||
|
electron mass from the atomic mass by default. Creates a static global instance
|
||||||
|
of this map (MASS) for use throughout code it is included into.
|
||||||
|
|
||||||
|
Written by G.W. McCann Aug. 2020
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include "MassLookup.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace PunchTable {
|
||||||
|
|
||||||
|
MassLookup* MassLookup::s_instance = new MassLookup();
|
||||||
|
|
||||||
|
MassLookup::MassLookup()
|
||||||
|
{
|
||||||
|
std::ifstream massfile("etc/mass.txt");
|
||||||
|
if(massfile.is_open())
|
||||||
|
{
|
||||||
|
std::string junk, A, element;
|
||||||
|
int Z;
|
||||||
|
double atomicMassBig, atomicMassSmall, isotopicMass;
|
||||||
|
getline(massfile,junk);
|
||||||
|
getline(massfile,junk);
|
||||||
|
while(massfile>>junk)
|
||||||
|
{
|
||||||
|
massfile>>Z>>A>>element>>atomicMassBig>>atomicMassSmall;
|
||||||
|
isotopicMass = (atomicMassBig + atomicMassSmall*1e-6 - Z*electron_mass)*u_to_mev;
|
||||||
|
std::string key = "("+std::to_string(Z)+","+A+")";
|
||||||
|
massTable[key] = isotopicMass;
|
||||||
|
elementTable[Z] = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr<<"ERR -- Unable to open mass file, check etc directory"<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MassLookup::~MassLookup() {}
|
||||||
|
|
||||||
|
//Returns nuclear mass in MeV
|
||||||
|
double MassLookup::FindMass(int Z, int A)
|
||||||
|
{
|
||||||
|
std::string key = "("+std::to_string(Z)+","+std::to_string(A)+")";
|
||||||
|
auto data = massTable.find(key);
|
||||||
|
if(data == massTable.end())
|
||||||
|
{
|
||||||
|
std::cerr<<"WARN -- Unable to find mass of (Z,A)=("<<Z<<","<<A<<")."<<std::endl;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
//returns element symbol
|
||||||
|
std::string MassLookup::FindSymbol(int Z, int A)
|
||||||
|
{
|
||||||
|
auto data = elementTable.find(Z);
|
||||||
|
if(data == elementTable.end())
|
||||||
|
{
|
||||||
|
std::cerr<<"WARN -- Unable to find symbol of (Z,A)=("<<Z<<","<<A<<")."<<std::endl;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fullsymbol = std::to_string(A) + data->second;
|
||||||
|
return fullsymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
45
src/MassLookup.h
Normal file
45
src/MassLookup.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
MassLookup.h
|
||||||
|
Generates a map for isotopic masses using AMDC data; subtracts away
|
||||||
|
electron mass from the atomic mass by default. Creates a static global instance
|
||||||
|
of this map (MASS) for use throughout code it is included into.
|
||||||
|
|
||||||
|
Written by G.W. McCann Aug. 2020
|
||||||
|
|
||||||
|
Converted to true singleton to simplify usage -- Aug. 2021 GWM
|
||||||
|
*/
|
||||||
|
#ifndef MASS_LOOKUP_H
|
||||||
|
#define MASS_LOOKUP_H
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace PunchTable {
|
||||||
|
|
||||||
|
class MassLookup
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MassLookup();
|
||||||
|
~MassLookup();
|
||||||
|
double FindMass(int Z, int A);
|
||||||
|
double FindMassU(int Z, int A) { return FindMass(Z, A)/u_to_mev; }
|
||||||
|
std::string FindSymbol(int Z, int A);
|
||||||
|
|
||||||
|
inline static MassLookup& GetInstance() { return *s_instance; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static MassLookup* s_instance;
|
||||||
|
std::unordered_map<std::string, double> massTable;
|
||||||
|
std::unordered_map<int, std::string> elementTable;
|
||||||
|
|
||||||
|
//constants
|
||||||
|
static constexpr double u_to_mev = 931.4940954;
|
||||||
|
static constexpr double electron_mass = 0.000548579909;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
109
src/PunchTable.cpp
Normal file
109
src/PunchTable.cpp
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#include "PunchTable.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace PunchTable {
|
||||||
|
|
||||||
|
PunchTable::PunchTable() :
|
||||||
|
m_validFlag(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PunchTable::PunchTable(const std::string& filename) :
|
||||||
|
m_validFlag(false)
|
||||||
|
{
|
||||||
|
ReadFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
PunchTable::~PunchTable() {}
|
||||||
|
|
||||||
|
void PunchTable::ReadFile(const std::string& filename)
|
||||||
|
{
|
||||||
|
std::ifstream input(filename);
|
||||||
|
if(!input.is_open())
|
||||||
|
{
|
||||||
|
std::cerr<<"Unable to open table file named "<<filename<<"! Exiting."<<std::endl;
|
||||||
|
m_validFlag = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string junk;
|
||||||
|
double thickness;
|
||||||
|
double theta;
|
||||||
|
double value;
|
||||||
|
std::vector<double> energyIn, energyDep;
|
||||||
|
|
||||||
|
std::getline(input, junk);
|
||||||
|
input>>junk>>thickness;
|
||||||
|
input>>junk>>m_thetaMin>>junk>>m_thetaMax>>junk>>m_thetaStep;
|
||||||
|
std::getline(input, junk);
|
||||||
|
std::getline(input, junk);
|
||||||
|
std::getline(input, junk);
|
||||||
|
|
||||||
|
while(input>>junk)
|
||||||
|
{
|
||||||
|
if(junk == "begin_theta")
|
||||||
|
{
|
||||||
|
energyIn.clear();
|
||||||
|
energyDep.clear();
|
||||||
|
input>>theta;
|
||||||
|
while(input>>junk)
|
||||||
|
{
|
||||||
|
if(junk == "end_theta")
|
||||||
|
break;
|
||||||
|
energyDep.push_back(std::stod(junk));
|
||||||
|
input>>value;
|
||||||
|
energyIn.push_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!energyDep.empty())
|
||||||
|
m_splines.emplace_back(energyDep, energyIn);
|
||||||
|
else
|
||||||
|
m_splines.emplace_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr<<"Unexpected expression found when reading punch table: "<<junk<<std::endl;
|
||||||
|
m_validFlag = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_validFlag = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
double PunchTable::GetInitialKineticEnergy(double theta_incident, double e_deposited)
|
||||||
|
{
|
||||||
|
theta_incident /= s_deg2rad;
|
||||||
|
if(!m_validFlag)
|
||||||
|
{
|
||||||
|
std::cerr<<"PunchTable not initialized at GetInitialKineticEnergy()"<<std::endl;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
else if(theta_incident < m_thetaMin || theta_incident > m_thetaMax)
|
||||||
|
{
|
||||||
|
std::cerr<<"Theta incident outside of range of calculated values for PunchTable::GetInitialKineticEnergy"<<std::endl;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float thetaf_bin = (theta_incident - m_thetaMin)/m_thetaStep;
|
||||||
|
int theta_bin = (theta_incident - m_thetaMin)/m_thetaStep;
|
||||||
|
|
||||||
|
std::cout<<"theta bin: "<<theta_bin<<" theta_inc: "<<theta_incident<<std::endl;
|
||||||
|
|
||||||
|
if(m_splines[theta_bin].IsValid())
|
||||||
|
{
|
||||||
|
double initialE = m_splines[theta_bin].Evaluate(e_deposited);
|
||||||
|
if(initialE == 0.0) //Not in the spline, stopped completely
|
||||||
|
{
|
||||||
|
return e_deposited;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return initialE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return e_deposited;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
src/PunchTable.h
Normal file
30
src/PunchTable.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef PUNCHTABLE_H
|
||||||
|
#define PUNCHTABLE_H
|
||||||
|
|
||||||
|
#include "CubicSpline.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace PunchTable {
|
||||||
|
|
||||||
|
class PunchTable {
|
||||||
|
public:
|
||||||
|
PunchTable();
|
||||||
|
PunchTable(const std::string& filename);
|
||||||
|
~PunchTable();
|
||||||
|
void ReadFile(const std::string& filename);
|
||||||
|
double GetInitialKineticEnergy(double theta_incident, double e_deposited);
|
||||||
|
inline bool IsValid() const { return m_validFlag; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<CubicSpline> m_splines;
|
||||||
|
double m_thetaStep, m_thetaMin, m_thetaMax;
|
||||||
|
|
||||||
|
bool m_validFlag;
|
||||||
|
|
||||||
|
static constexpr double s_deg2rad = M_PI/180.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
111
src/main.cpp
Normal file
111
src/main.cpp
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
#include "MassLookup.h"
|
||||||
|
#include "PunchTable.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cmath>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string options = "";
|
||||||
|
if(argc == 2)
|
||||||
|
{
|
||||||
|
options = argv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int Zp = 1;
|
||||||
|
int Ap = 1;
|
||||||
|
|
||||||
|
float keStep = 0.01;
|
||||||
|
float thickness = 500.0 * 1e-4 * 2.3216 * 1e6; //1000 um thick times density of Si-> ug/cm^2
|
||||||
|
float deg2rad = M_PI/180.0;
|
||||||
|
float thetaStep = 0.1*deg2rad;
|
||||||
|
float precision = 1.0e-6;
|
||||||
|
|
||||||
|
std::vector<int> ZT(1), AT(1), ST(1);
|
||||||
|
ZT[0] = 14;
|
||||||
|
AT[0] = 28;
|
||||||
|
ST[0] = 1;
|
||||||
|
|
||||||
|
EnergyLoss energyLoss;
|
||||||
|
energyLoss.SetTargetComponents(ZT, AT, ST);
|
||||||
|
|
||||||
|
float keMin = 8.23f;
|
||||||
|
float keMax = 25.0f;
|
||||||
|
|
||||||
|
float thetaMin = 0.0f*deg2rad;
|
||||||
|
float thetaMax = 85.0f*deg2rad;
|
||||||
|
|
||||||
|
int nebins = int((keMax-keMin)/keStep);
|
||||||
|
int ntbins = int ((thetaMax-thetaMin)/thetaStep);
|
||||||
|
|
||||||
|
if(options == "--make-table" || options == "")
|
||||||
|
{
|
||||||
|
|
||||||
|
std::cout<<"nebins: "<<nebins<<" ntbins: "<<ntbins<<std::endl;
|
||||||
|
|
||||||
|
float keCur;
|
||||||
|
float thetaCur;
|
||||||
|
float energy;
|
||||||
|
|
||||||
|
std::vector<std::vector<float>> energy_dep(ntbins);
|
||||||
|
std::vector<std::vector<float>> energy_in(ntbins);
|
||||||
|
|
||||||
|
for(int i=0; i<ntbins; i++)
|
||||||
|
{
|
||||||
|
std::cout<<"\rWorking on theta bin "<<i+1<<" of "<<ntbins<<std::flush;
|
||||||
|
thetaCur = thetaMin + i*thetaStep;
|
||||||
|
for(int j=0; j<nebins; j++)
|
||||||
|
{
|
||||||
|
keCur = keMax - j*keStep;
|
||||||
|
energy = energyLoss.GetEnergyLoss(Zp, Ap, keCur, thickness / std::fabs(std::cos(thetaCur)));
|
||||||
|
if(std::fabs(energy-keCur) > precision)
|
||||||
|
{
|
||||||
|
energy_dep[i].push_back(energy);
|
||||||
|
energy_in[i].push_back(keCur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout<<std::endl;
|
||||||
|
|
||||||
|
std::ofstream output("tables/test.ptab");
|
||||||
|
output<<std::setprecision(5);
|
||||||
|
output<<"Material: ";
|
||||||
|
for(size_t i=0; i<ZT.size(); i++)
|
||||||
|
output<<MassLookup::GetInstance()->FindSymbol(ZT[i], AT[i]);
|
||||||
|
output<<std::endl;
|
||||||
|
output<<"Thickness: "<<thickness<<std::endl;
|
||||||
|
output<<"IncidentAngleRange(deg): "<<thetaMin/deg2rad<<" to "<<thetaMax/deg2rad<<" stepSize: "<<thetaStep/deg2rad<<std::endl;
|
||||||
|
output<<std::setw(16)<<"Energy Deposited"<<"|"<<std::setw(16)<<"Intial Energy"<<std::endl;
|
||||||
|
output<<"---------------------------------"<<std::endl;
|
||||||
|
for(int i=0; i<ntbins; i++)
|
||||||
|
{
|
||||||
|
thetaCur = thetaMin + i*thetaStep;
|
||||||
|
output<<"begin_theta "<<thetaCur/deg2rad<<std::endl;
|
||||||
|
for(unsigned int j=0; j<energy_dep[i].size(); j++)
|
||||||
|
{
|
||||||
|
output<<std::setw(16)<<energy_dep[i][j]<<" "<<std::setw(16)<<energy_in[i][j]<<std::endl;
|
||||||
|
}
|
||||||
|
output<<"end_theta"<<std::endl;
|
||||||
|
}
|
||||||
|
output.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options == "--test" || options == "")
|
||||||
|
{
|
||||||
|
std::cout<<"-------------Testing---------"<<std::endl;
|
||||||
|
PunchTable table("tables/test.ptab");
|
||||||
|
std::cout<<"Is the table valid? "<<table.IsValid()<<std::endl;
|
||||||
|
double ke_test = 14.5; //MeV
|
||||||
|
double theta_test = 35.0*deg2rad;
|
||||||
|
double ke_dep = energyLoss.GetEnergyLoss(Zp, Ap, ke_test, thickness/std::fabs(std::cos(theta_test)));
|
||||||
|
double recov_ke = table.GetInitialKineticEnergy(theta_test, ke_dep);
|
||||||
|
std::cout<<"For a "<<MassLookup::GetInstance()->FindSymbol(Zp, Ap)<<" with kinetic energy "<<ke_test<<" MeV "
|
||||||
|
<<" the percent error on recovery is "<<(ke_test-recov_ke)/ke_test*100.0<<" where the recovered energy is "<<recov_ke<<" MeV"
|
||||||
|
<<" and the deposited energy is "<<ke_dep<<" MeV"<<std::endl;
|
||||||
|
std::cout<<"-----------------------------"<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user