2017-07-25 12:19:11 -04:00
|
|
|
#include <iostream>
|
|
|
|
#include <math.h>
|
|
|
|
#include <algorithm>
|
|
|
|
#include "catima/catima.h"
|
|
|
|
#include "catima/constants.h"
|
|
|
|
#include "catima/data_ionisation_potential.h"
|
|
|
|
#include "catima/data_atima.h"
|
|
|
|
#include "catima/integrator.h"
|
|
|
|
#include "catima/storage.h"
|
|
|
|
#include "catima/nucdata.h"
|
|
|
|
#include "catima/calculations.h"
|
2018-07-31 11:40:25 -04:00
|
|
|
#ifdef REACTIONS
|
2018-07-30 19:41:44 -04:00
|
|
|
#include "catima/reactions.h"
|
|
|
|
#endif
|
2017-07-25 12:19:11 -04:00
|
|
|
|
|
|
|
namespace catima{
|
|
|
|
|
|
|
|
Config default_config;
|
|
|
|
|
|
|
|
bool operator==(const Config &a, const Config&b){
|
|
|
|
if(std::memcmp(&a,&b,sizeof(Config)) == 0){
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
double dedx(const Projectile &p, const Material &mat, const Config &c){
|
2017-07-25 12:19:11 -04:00
|
|
|
double sum = 0;
|
2019-05-13 14:51:09 -04:00
|
|
|
if(p.T<=0)return 0.0;
|
2018-01-29 07:38:54 -05:00
|
|
|
sum += dedx_n(p,mat);
|
|
|
|
double se=0;
|
|
|
|
if(p.T<=10){
|
2020-08-03 10:49:21 -04:00
|
|
|
se = sezi_dedx_e(p,mat,c );
|
2018-01-29 07:38:54 -05:00
|
|
|
}
|
|
|
|
else if(p.T>10 && p.T<30){
|
|
|
|
double factor = 0.05 * ( p.T - 10.0 );
|
2020-08-03 10:49:21 -04:00
|
|
|
se = (1-factor)*sezi_dedx_e(p,mat,c) + factor*bethek_dedx_e(p,mat,c);
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
2018-01-29 07:38:54 -05:00
|
|
|
else {
|
|
|
|
se = bethek_dedx_e(p,mat,c);
|
|
|
|
}
|
|
|
|
sum+=se;
|
|
|
|
|
2017-12-14 09:29:23 -05:00
|
|
|
return sum;
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
double domega2dx(const Projectile &p, const Material &mat, const Config &c){
|
2017-07-25 12:19:11 -04:00
|
|
|
double sum = 0;
|
|
|
|
|
|
|
|
for(int i=0;i<mat.ncomponents();i++){
|
2017-12-14 09:29:23 -05:00
|
|
|
auto t= mat.get_element(i);
|
2019-10-14 05:21:38 -04:00
|
|
|
double w = mat.weight_fraction(i);
|
2018-10-09 07:02:49 -04:00
|
|
|
sum += w*dedx_variance(p,t,c);
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
2017-12-14 09:29:23 -05:00
|
|
|
return sum;
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
double range(const Projectile &p, const Material &t, const Config &c){
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
//Interpolator range_spline(energy_table.values,data.range.data(),energy_table.num);
|
|
|
|
spline_type range_spline = get_range_spline(data);
|
2019-05-13 14:51:09 -04:00
|
|
|
return range_spline(p.T);
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
double dedx_from_range(const Projectile &p, const Material &t, const Config &c){
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
//Interpolator range_spline(energy_table.values,data.range.data(),energy_table.num);
|
|
|
|
spline_type range_spline = get_range_spline(data);
|
2019-05-13 14:51:09 -04:00
|
|
|
return p.A/range_spline.derivative(p.T);
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
std::vector<double> dedx_from_range(const Projectile &p, const std::vector<double> &T, const Material &t, const Config &c){
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
//Interpolator range_spline(energy_table.values,data.range.data(),energy_table.num);
|
|
|
|
spline_type range_spline = get_range_spline(data);
|
2018-02-14 05:53:56 -05:00
|
|
|
std::vector<double> dedx;
|
|
|
|
dedx.reserve(T.size());
|
|
|
|
for(auto e:T){
|
|
|
|
if(e<catima::Ezero){
|
|
|
|
dedx.push_back(0.0);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
dedx.push_back(p.A/range_spline.derivative(e));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return dedx;
|
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
double range_straggling(const Projectile &p, double T, const Material &t, const Config &c){
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
//Interpolator range_straggling_spline(energy_table.values,data.range_straggling.data(),energy_table.num);
|
|
|
|
spline_type range_straggling_spline = get_range_straggling_spline(data);
|
2017-07-25 12:19:11 -04:00
|
|
|
return sqrt(range_straggling_spline(T));
|
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
double range_variance(const Projectile &p, double T, const Material &t, const Config &c){
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
//Interpolator range_straggling_spline(energy_table.values,data.range_straggling.data(),energy_table.num);
|
|
|
|
spline_type range_straggling_spline = get_range_straggling_spline(data);
|
2017-07-25 12:19:11 -04:00
|
|
|
return range_straggling_spline(T);
|
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
double domega2de(const Projectile &p, double T, const Material &t, const Config &c){
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
//Interpolator range_straggling_spline(energy_table.values,data.range_straggling.data(),energy_table.num);
|
|
|
|
spline_type range_straggling_spline = get_range_straggling_spline(data);
|
2017-07-25 12:19:11 -04:00
|
|
|
return range_straggling_spline.derivative(T);
|
|
|
|
}
|
2021-01-12 15:50:15 -05:00
|
|
|
double da2dx(const Projectile &p, const Material &mat, const Config &c){
|
|
|
|
double Es2 = 198.81;
|
|
|
|
double f = 1.0;
|
|
|
|
if(c.scattering == scattering_types::dhighland)Es2 = 15*15;
|
|
|
|
if(c.scattering == scattering_types::fermi_rossi)Es2 = 15*15;
|
|
|
|
return f*angular_scattering_power(p,mat, Es2);
|
|
|
|
}
|
|
|
|
|
2020-12-16 16:53:44 -05:00
|
|
|
/*
|
2020-08-05 12:20:16 -04:00
|
|
|
double da2de(const Projectile &p, double T, const Material &t, const Config &c){
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
//Interpolator angular_variance_spline(energy_table.values,data.angular_variance.data(),energy_table.num);
|
|
|
|
spline_type angular_variance_spline = get_angular_variance_spline(data);
|
2017-07-25 12:19:11 -04:00
|
|
|
return angular_variance_spline.derivative(T);
|
|
|
|
}
|
2020-12-16 16:53:44 -05:00
|
|
|
*/
|
|
|
|
|
2021-01-12 15:50:15 -05:00
|
|
|
double da2de(const Projectile &p, const Material &mat, const Config &c){
|
|
|
|
return da2dx(p,mat,c)/dedx(p,mat,c);
|
|
|
|
}
|
|
|
|
|
|
|
|
double Tfr(const Projectile &p, double X, double Es2){
|
|
|
|
if(p.T<=0)return 0.0;
|
|
|
|
double _p = p_from_T(p.T,p.A);
|
|
|
|
double beta = _p/((p.T+atomic_mass_unit)*p.A);
|
|
|
|
return Es2 /(X*pow(_p*beta,2));
|
|
|
|
}
|
|
|
|
|
|
|
|
double angular_variance(Projectile p, const Material &t, const Config &c, int order){
|
2020-12-16 16:53:44 -05:00
|
|
|
const double T = p.T;
|
2021-01-12 15:50:15 -05:00
|
|
|
|
|
|
|
const double p1 = p_from_T(T,p.A);
|
|
|
|
const double beta1 = p1/((T+atomic_mass_unit)*p.A);
|
2020-12-16 16:53:44 -05:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
spline_type range_spline = get_range_spline(data);
|
2021-01-12 15:50:15 -05:00
|
|
|
double range = range_spline(T);
|
|
|
|
|
|
|
|
double rrange = std::min(range/t.density(), t.thickness_cm()); // residual range, in case of stopping inside material
|
|
|
|
double X0 = radiation_length(t);
|
|
|
|
double Es2 = 198.81;
|
|
|
|
if(c.scattering == scattering_types::dhighland)Es2 = 15*15;
|
|
|
|
if(c.scattering == scattering_types::fermi_rossi)Es2 = 15*15;
|
|
|
|
|
2020-12-16 16:53:44 -05:00
|
|
|
auto fx0p = [&](double x)->double{
|
2021-01-12 15:50:15 -05:00
|
|
|
double e =energy_out(T,x*t.density(),range_spline);
|
|
|
|
double d = std::pow((rrange-x),order);
|
|
|
|
double ff = 1;
|
|
|
|
if(c.scattering == scattering_types::dhighland){
|
|
|
|
double l = x*t.density()/X0;
|
|
|
|
double lnl = log(l);
|
|
|
|
ff = 0.97*(1+lnl/20.7)*(1+lnl/22.7);
|
|
|
|
}
|
|
|
|
//return d*ff*da2dx(p(e), t, c);
|
|
|
|
return d*ff*Tfr(p(e),1, 1.0);
|
2020-12-16 16:53:44 -05:00
|
|
|
};
|
2021-01-12 15:50:15 -05:00
|
|
|
|
|
|
|
auto fx0p_2 = [&](double x)->double{
|
|
|
|
double e =energy_out(T,x*t.density(),range_spline);
|
|
|
|
double d = std::pow((rrange-x),order);
|
|
|
|
return d*angular_scattering_power_xs(p(e),t,p1,beta1);
|
|
|
|
};
|
|
|
|
|
|
|
|
// corrections
|
|
|
|
if(c.scattering == scattering_types::gottschalk){
|
|
|
|
return integrator.integrate(fx0p_2,0, rrange)*t.density();
|
|
|
|
}
|
|
|
|
return integrator.integrate(fx0p,0, rrange)*t.density()*pow(p.Z,2)*Es2/X0;
|
2020-12-16 16:53:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
double angular_straggling(Projectile p, const Material &t, const Config &c){
|
|
|
|
return sqrt(angular_variance(p,t,c));
|
|
|
|
}
|
2017-07-25 12:19:11 -04:00
|
|
|
|
2020-12-16 16:53:44 -05:00
|
|
|
double angular_straggling_from_E(const Projectile &p, double T, double Tout, Material t, const Config &c){
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
2020-12-16 16:53:44 -05:00
|
|
|
spline_type range_spline = get_range_spline(data);
|
|
|
|
double th = range_spline(T)-range_spline(Tout);
|
|
|
|
t.thickness(th);
|
|
|
|
return angular_straggling(p,t,c);
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
double energy_straggling_from_E(const Projectile &p, double T, double Tout,const Material &t, const Config &c){
|
2021-01-12 15:50:15 -05:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
2018-10-21 16:08:16 -04:00
|
|
|
spline_type range_spline = get_range_spline(data);
|
|
|
|
spline_type range_straggling_spline = get_range_straggling_spline(data);
|
2017-07-25 12:19:11 -04:00
|
|
|
double dEdxo = p.A/range_spline.derivative(Tout);
|
|
|
|
return dEdxo*sqrt(range_straggling_spline(T) - range_straggling_spline(Tout))/p.A;
|
|
|
|
}
|
|
|
|
|
2018-10-21 16:08:16 -04:00
|
|
|
double energy_out(double T, double thickness, const Interpolator &range_spline){
|
2017-07-25 12:19:11 -04:00
|
|
|
int counter = 0;
|
|
|
|
double range;
|
|
|
|
double dedx;
|
|
|
|
double e,r;
|
|
|
|
|
|
|
|
range = range_spline(T);
|
|
|
|
dedx = 1.0/range_spline.derivative(T);
|
|
|
|
if(range<= thickness) return 0.0;
|
|
|
|
|
|
|
|
e = T - (thickness*dedx);
|
|
|
|
while(1){
|
|
|
|
r = range - range_spline(e) - thickness;
|
2019-11-24 14:12:56 -05:00
|
|
|
if(fabs(r)<Eout_epsilon)return e;
|
2019-10-14 05:21:38 -04:00
|
|
|
double step = -r*dedx;
|
2017-07-25 12:19:11 -04:00
|
|
|
e = e-step;
|
|
|
|
if(e<Ezero)return 0.0;
|
2018-02-14 06:08:12 -05:00
|
|
|
dedx = 1.0/range_spline.derivative(e);
|
2017-07-25 12:19:11 -04:00
|
|
|
counter++;
|
2019-11-24 14:12:56 -05:00
|
|
|
assert(counter<=100);
|
|
|
|
if(counter>100)return -1;
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
double energy_out(const Projectile &p, const Material &t, const Config &c){
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
//Interpolator range_spline(energy_table.values,data.range.data(),energy_table.num);
|
|
|
|
spline_type range_spline = get_range_spline(data);
|
2019-05-13 14:51:09 -04:00
|
|
|
return energy_out(p.T,t.thickness(),range_spline);
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
std::vector<double> energy_out(const Projectile &p, const std::vector<double> &T, const Material &t, const Config &c){
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
//Interpolator range_spline(energy_table.values,data.range.data(),energy_table.num);
|
|
|
|
spline_type range_spline = get_range_spline(data);
|
2018-02-14 05:53:56 -05:00
|
|
|
|
|
|
|
std::vector<double> eout;
|
|
|
|
eout.reserve(T.size());
|
|
|
|
for(auto e:T){
|
|
|
|
if(e<catima::Ezero){
|
|
|
|
eout.push_back(0.0);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
eout.push_back(energy_out(e,t.thickness(),range_spline));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return eout;
|
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
std::vector<double> calculate_tof(Projectile p, const Material &t, const Config &c){
|
|
|
|
double res;
|
|
|
|
std::vector<double> values;
|
|
|
|
values.reserve(max_datapoints);
|
|
|
|
auto function = [&](double x)->double{return 1.0/(dedx(p(x),t,c)*beta_from_T(x));};
|
|
|
|
res = integrator.integrate(function,Ezero,energy_table(0));
|
|
|
|
res = res*10.0*p.A/(c_light*t.density());
|
|
|
|
values.push_back(res);
|
|
|
|
for(int i=1;i<max_datapoints;i++){
|
|
|
|
res = integrator.integrate(function,energy_table(i-1),energy_table(i));
|
|
|
|
res = res*10.0*p.A/(c_light*t.density());
|
|
|
|
res += values[i-1];
|
|
|
|
values.push_back(res);
|
|
|
|
}
|
|
|
|
return values;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result calculate(Projectile p, const Material &t, const Config &c){
|
2017-07-25 12:19:11 -04:00
|
|
|
Result res;
|
|
|
|
double T = p.T;
|
2018-01-29 07:38:54 -05:00
|
|
|
if(T<catima::Ezero && T<catima::Ezero-catima::numeric_epsilon){return res;}
|
2018-10-21 16:08:16 -04:00
|
|
|
auto& data = _storage.Get(p,t,c);
|
|
|
|
|
2020-12-16 16:53:44 -05:00
|
|
|
bool use_angular_spline = false;
|
|
|
|
if(c.scattering == scattering_types::atima_scattering){
|
|
|
|
use_angular_spline = true;
|
|
|
|
}
|
|
|
|
|
2018-10-21 16:08:16 -04:00
|
|
|
//Interpolator range_spline(energy_table.values,data.range.data(),energy_table.num);
|
|
|
|
spline_type range_spline = get_range_spline(data);
|
2020-12-16 16:53:44 -05:00
|
|
|
spline_type range_straggling_spline = get_range_straggling_spline(data);
|
2017-07-25 12:19:11 -04:00
|
|
|
|
|
|
|
res.Ein = T;
|
|
|
|
res.range = range_spline(T);
|
2020-12-16 16:53:44 -05:00
|
|
|
res.dEdxi = p.A/range_spline.derivative(T);
|
|
|
|
res.sigma_r = sqrt(range_straggling_spline(T));
|
2017-07-25 12:19:11 -04:00
|
|
|
|
2020-12-16 16:53:44 -05:00
|
|
|
if(t.thickness()==0){
|
|
|
|
res.dEdxo = res.dEdxi;
|
2021-01-15 17:15:18 -05:00
|
|
|
res.Eout = res.Ein;
|
2020-12-16 16:53:44 -05:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
res.Eout = energy_out(T,t.thickness(),range_spline);
|
|
|
|
res.Eloss = (res.Ein - res.Eout)*p.A;
|
|
|
|
|
2017-07-25 12:19:11 -04:00
|
|
|
if(res.Eout<Ezero){
|
|
|
|
res.dEdxo = 0.0;
|
|
|
|
res.sigma_a = 0.0;
|
|
|
|
res.tof = 0.0;
|
|
|
|
res.sigma_E = 0.0;
|
2020-12-16 16:53:44 -05:00
|
|
|
}
|
|
|
|
else{
|
|
|
|
spline_type angular_variance_spline = get_angular_variance_spline(data);
|
2020-07-29 19:37:20 -04:00
|
|
|
res.dEdxo = p.A/range_spline.derivative(res.Eout);
|
2017-07-25 12:19:11 -04:00
|
|
|
#ifdef THIN_TARGET_APPROXIMATION
|
|
|
|
if(thin_target_limit*res.Ein<res.Eout){
|
2020-12-16 16:53:44 -05:00
|
|
|
double edif = (res.Ein-res.Eout);
|
2017-07-25 12:19:11 -04:00
|
|
|
double s1 = range_straggling_spline.derivative(T);
|
|
|
|
double s2 = range_straggling_spline.derivative(res.Eout);
|
|
|
|
res.sigma_E = res.dEdxo*sqrt(edif*0.5*(s1+s2))/p.A;
|
2020-12-16 16:53:44 -05:00
|
|
|
if(use_angular_spline){
|
|
|
|
s1 = angular_variance_spline.derivative(T);
|
|
|
|
s2 = angular_variance_spline.derivative(res.Eout);
|
|
|
|
res.sigma_a = sqrt(0.5*(s1+s2)*edif);
|
|
|
|
}
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
|
|
|
else{
|
2020-07-29 19:37:20 -04:00
|
|
|
res.sigma_E = res.dEdxo*sqrt(range_straggling_spline(T) - range_straggling_spline(res.Eout))/p.A;
|
2020-12-16 16:53:44 -05:00
|
|
|
if(use_angular_spline){
|
|
|
|
res.sigma_a = sqrt(angular_variance_spline(T) - angular_variance_spline(res.Eout));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-07-25 12:19:11 -04:00
|
|
|
#else
|
|
|
|
res.sigma_E = res.dEdxo*sqrt(range_straggling_spline(T) - range_straggling_spline(res.Eout))/p.A;
|
2020-12-16 16:53:44 -05:00
|
|
|
if(use_angular_spline){
|
|
|
|
res.sigma_a = sqrt(angular_variance_spline(T) - angular_variance_spline(res.Eout));
|
|
|
|
}
|
2017-07-25 12:19:11 -04:00
|
|
|
#endif
|
2020-12-16 16:53:44 -05:00
|
|
|
if( (!use_angular_spline) && res.range>t.thickness()){ // do not calculate angle scattering when stopped inside material
|
|
|
|
res.sigma_a = angular_straggling(p(T),t,c);
|
|
|
|
}
|
|
|
|
//Interpolator tof_spline(energy_table.values, tofdata.data(), energy_table.num,interpolation_t::linear);
|
|
|
|
//res.tof = tof_spline(res.Ein) - tof_spline(res.Eout);
|
|
|
|
res.tof = calculate_tof_from_E(p,res.Eout,t);
|
|
|
|
|
|
|
|
} //end of else for non stopped case
|
2020-08-05 19:28:19 -04:00
|
|
|
|
2021-01-12 15:50:15 -05:00
|
|
|
// position straggling in material
|
2021-01-12 15:56:29 -05:00
|
|
|
double rrange = std::min(res.range/t.density(), t.thickness_cm());
|
2021-01-12 15:50:15 -05:00
|
|
|
res.sigma_x = angular_variance(p(T),t,c,2);
|
2020-08-03 19:44:00 -04:00
|
|
|
res.sigma_x = sqrt(res.sigma_x);
|
2020-08-04 11:35:33 -04:00
|
|
|
|
2021-01-12 15:50:15 -05:00
|
|
|
rrange = std::min(res.range/t.density(), t.thickness_cm());
|
2021-01-12 15:56:29 -05:00
|
|
|
// position vs angle covariance, needed later for final position straggling
|
2021-01-12 15:50:15 -05:00
|
|
|
res.cov = angular_variance(p(T),t,c,1);
|
2020-12-16 16:53:44 -05:00
|
|
|
|
2018-07-31 11:40:25 -04:00
|
|
|
#ifdef REACTIONS
|
2018-07-31 09:34:41 -04:00
|
|
|
res.sp = nonreaction_rate(p,t,c);
|
2018-07-30 19:41:44 -04:00
|
|
|
#endif
|
2017-07-25 12:19:11 -04:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
MultiResult calculate(const Projectile &p, const Layers &layers, const Config &c){
|
2017-07-25 12:19:11 -04:00
|
|
|
MultiResult res;
|
|
|
|
double e = p.T;
|
|
|
|
res.total_result.Ein = e;
|
|
|
|
res.results.reserve(layers.num());
|
|
|
|
for(auto&m:layers.get_materials()){
|
|
|
|
Result r = calculate(p,m,e,c);
|
2020-08-04 11:35:33 -04:00
|
|
|
e = r.Eout;
|
2017-07-25 12:19:11 -04:00
|
|
|
res.total_result.Eloss += r.Eloss;
|
|
|
|
res.total_result.sigma_E += r.sigma_E*r.sigma_E;
|
|
|
|
res.total_result.tof += r.tof;
|
2020-08-04 11:35:33 -04:00
|
|
|
res.total_result.Eout = r.Eout;
|
|
|
|
double a2 = res.total_result.sigma_a;
|
2020-08-04 19:10:03 -04:00
|
|
|
res.total_result.sigma_x += (2*m.thickness_cm()*res.total_result.cov)
|
|
|
|
+ (a2*m.thickness_cm()*m.thickness_cm())
|
|
|
|
+ r.sigma_x*r.sigma_x;
|
2020-08-04 11:35:33 -04:00
|
|
|
//res.total_result.sigma_x += (a2*m.thickness_cm()*m.thickness_cm()) + r.sigma_x*r.sigma_x;
|
|
|
|
res.total_result.cov += a2*m.thickness_cm() + r.cov;
|
|
|
|
res.total_result.sigma_a += r.sigma_a*r.sigma_a;
|
2018-07-31 11:40:25 -04:00
|
|
|
#ifdef REACTIONS
|
2018-07-30 19:41:44 -04:00
|
|
|
res.total_result.sp = (r.sp>=0.0)?res.total_result.sp*r.sp:-1;
|
|
|
|
#endif
|
2017-07-25 12:19:11 -04:00
|
|
|
res.results.push_back(r);
|
|
|
|
}
|
|
|
|
if(e>Ezero){
|
|
|
|
res.total_result.sigma_a = sqrt(res.total_result.sigma_a);
|
|
|
|
res.total_result.sigma_E = sqrt(res.total_result.sigma_E);
|
2020-07-29 19:37:20 -04:00
|
|
|
res.total_result.sigma_x = sqrt(res.total_result.sigma_x);
|
|
|
|
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
|
|
|
else{
|
|
|
|
res.total_result.sigma_a = 0.0;
|
|
|
|
res.total_result.sigma_E = 0.0;
|
2020-08-03 19:44:00 -04:00
|
|
|
res.total_result.sigma_x = sqrt(res.total_result.sigma_x);
|
2017-07-25 12:19:11 -04:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result calculate(double pa, int pz, double T, double ta, double tz, double thickness, double density){
|
|
|
|
Projectile p(pa,pz);
|
|
|
|
Material m(ta,tz,density,thickness);
|
|
|
|
return calculate(p(T),m);
|
|
|
|
}
|
|
|
|
|
2018-10-21 16:08:16 -04:00
|
|
|
DataPoint calculate_DataPoint(Projectile p, const Material &t, const Config &c){
|
|
|
|
DataPoint dp(p,t,c);
|
|
|
|
dp.range.resize(max_datapoints);
|
|
|
|
dp.range_straggling.resize(max_datapoints);
|
|
|
|
dp.angular_variance.resize(max_datapoints);
|
|
|
|
auto fdedx = [&](double x)->double{
|
2019-05-13 14:51:09 -04:00
|
|
|
return 1.0/dedx(p(x),t,c);
|
2018-10-21 16:08:16 -04:00
|
|
|
};
|
|
|
|
auto fomega = [&](double x)->double{
|
2020-08-05 12:20:16 -04:00
|
|
|
return domega2dx(p(x),t,c)/catima::power(dedx(p(x),t,c),3);
|
2018-10-21 16:08:16 -04:00
|
|
|
};
|
2020-12-16 16:53:44 -05:00
|
|
|
auto ftheta = [&](double x)->double{
|
|
|
|
return da2de(p(x),t,c);
|
|
|
|
};
|
2018-10-21 16:08:16 -04:00
|
|
|
|
2019-10-14 05:21:38 -04:00
|
|
|
//double res=0.0;
|
2018-10-21 16:08:16 -04:00
|
|
|
//calculate 1st point to have i-1 element ready for loop
|
|
|
|
//res = integrator.integrate(fdedx,Ezero,energy_table(0));
|
|
|
|
//res = p.A*res;
|
|
|
|
//dp.range[0] = res;
|
2019-10-14 05:21:38 -04:00
|
|
|
|
2018-10-21 16:08:16 -04:00
|
|
|
dp.range[0] = 0.0;
|
|
|
|
dp.angular_variance[0] = 0.0;
|
|
|
|
|
|
|
|
//res = integrator.integrate(fomega,Ezero,energy_table(0));
|
|
|
|
//res = p.A*res;
|
|
|
|
dp.range_straggling[0]=0.0;
|
2020-12-16 16:53:44 -05:00
|
|
|
//p.T = energy_table(0);
|
2018-10-21 16:08:16 -04:00
|
|
|
for(int i=1;i<max_datapoints;i++){
|
2019-10-14 05:21:38 -04:00
|
|
|
double res = p.A*integrator.integrate(fdedx,energy_table(i-1),energy_table(i));
|
2018-10-21 16:08:16 -04:00
|
|
|
dp.range[i] = res + dp.range[i-1];
|
2020-12-16 16:53:44 -05:00
|
|
|
//res = da2dx(p(energy_table(i)),t)*res;
|
|
|
|
//dp.angular_variance[i] = res + dp.angular_variance[i-1];
|
|
|
|
dp.angular_variance[i] = p.A*integrator.integrate(ftheta,energy_table(i-1),energy_table(i))
|
|
|
|
+ dp.angular_variance[i-1];
|
2018-10-21 16:08:16 -04:00
|
|
|
|
|
|
|
res = integrator.integrate(fomega,energy_table(i-1),energy_table(i));
|
|
|
|
res = p.A*res;
|
|
|
|
dp.range_straggling[i] = res + dp.range_straggling[i-1];
|
|
|
|
}
|
|
|
|
return dp;
|
|
|
|
}
|
2017-07-25 12:19:11 -04:00
|
|
|
|
|
|
|
double calculate_tof_from_E(Projectile p, double Eout, const Material &t, const Config &c){
|
|
|
|
double res;
|
2019-05-13 14:51:09 -04:00
|
|
|
auto function = [&](double x)->double{return 1.0/(dedx(p(x),t,c)*beta_from_T(x));};
|
2017-12-14 09:07:54 -05:00
|
|
|
res = integrator.integrate(function,Eout,p.T);
|
2017-07-25 12:19:11 -04:00
|
|
|
res = res*10.0*p.A/(c_light*t.density());
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2020-08-05 12:20:16 -04:00
|
|
|
std::pair<double,double> w_magnification(const Projectile &p, double Ein, const Material &t, const Config &c){
|
2018-02-16 10:13:09 -05:00
|
|
|
std::pair<double, double> res{1.0,1.0};
|
2018-02-14 09:04:49 -05:00
|
|
|
if(t.density()<= 0.0 || t.thickness()<=0){
|
|
|
|
return res;
|
|
|
|
}
|
2018-02-16 10:13:09 -05:00
|
|
|
std::vector<double> energies{0.99*Ein, Ein, 1.01*Ein};
|
2018-02-14 09:04:49 -05:00
|
|
|
auto eres = energy_out(p,energies,t,c);
|
|
|
|
if(eres[0]>0.0 && eres[1]>0.0 && eres[2]>0.0){
|
2018-02-16 10:13:09 -05:00
|
|
|
res.first = energies[1]*(eres[2]-eres[0])/(eres[1]*(energies[2]-energies[0]));
|
|
|
|
res.second = p_from_T(energies[1],p.A)*(p_from_T(eres[2],p.A)-p_from_T(eres[0],p.A))/( p_from_T(eres[1],p.A)*( p_from_T(energies[2],p.A)-p_from_T(energies[0],p.A) ) );
|
2018-02-14 09:04:49 -05:00
|
|
|
}
|
|
|
|
else {
|
2018-02-16 10:13:09 -05:00
|
|
|
res.first = 0.0;
|
|
|
|
res.second = 0.0;
|
2018-02-14 09:04:49 -05:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2017-07-25 12:19:11 -04:00
|
|
|
} // end of atima namespace
|