#include #include #include #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" #ifdef REACTIONS #include "catima/reactions.h" #endif 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; } double dedx(Projectile &p, const Material &mat, const Config &c){ double sum = 0; if(p.T<=0)return 0.0; sum += dedx_n(p,mat); double se=0; if(p.T<=10){ se = sezi_dedx_e(p,mat,c ); } else if(p.T>10 && p.T<30){ double factor = 0.05 * ( p.T - 10.0 ); se = (1-factor)*sezi_dedx_e(p,mat,c) + factor*bethek_dedx_e(p,mat,c); } else { se = bethek_dedx_e(p,mat,c); } sum+=se; return sum; } double domega2dx(Projectile &p, double T, const Material &mat, const Config &c){ double sum = 0; for(int i=0;i dedx_from_range(Projectile &p, const std::vector &T, const Material &t, const Config &c){ 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); std::vector dedx; dedx.reserve(T.size()); for(auto e:T){ if(e100)return -1; } return -1; } double energy_out(Projectile &p, const Material &t, const Config &c){ 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); return energy_out(p.T,t.thickness(),range_spline); } std::vector energy_out(Projectile &p, const std::vector &T, const Material &t, const Config &c){ 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); std::vector eout; eout.reserve(T.size()); for(auto e:T){ if(e0){ //auto tofdata = calculate_tof(p,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); } } res.sigma_r = sqrt(range_straggling_spline(T)); res.Eloss = (res.Ein - res.Eout)*p.A; auto fx2 = [&](double x)->double{ double range = range_spline(T); double tt = range - range_spline(x); double t0 = std::min(range, t.thickness()); return (tt-t0)*(tt-t0)*da2dx(p,x, t, c); }; auto fx2p = [&](double x)->double{ double range = range_spline(T); double e =energy_out(T,x*t.density(),range_spline); double t0 = std::min(range/t.density(), t.thickness_cm()); return (t0-x)*(t0-x)*da2dx(p,e, t, c)*t.density(); }; //res.sigma_x = integrator_adaptive.integrate(fx2,res.Eout, res.Ein,1e-3, 1e-3,4)/t.density(); res.sigma_x = integrator_adaptive.integrate(fx2p,0, t.thickness_cm(),1e-3, 1e-3,4); res.sigma_x = sqrt(res.sigma_x); auto fx1 = [&](double x)->double{ double range = range_spline(T); double tt = range - range_spline(x); double t0 = std::min(range, t.thickness()); return (t0-tt)*da2dx(p,x, t, c); }; auto fx1p = [&](double x)->double{ double range = range_spline(T); double e =energy_out(T,x*t.density(),range_spline); double t0 = std::min(range/t.density(), t.thickness_cm()); return (t0-x)*da2dx(p,e, t, c)*t.density(); }; //res.cov = integrator_adaptive.integrate(fx1,res.Eout, res.Eout, 1e-6, 1e-3,4); res.cov = integrator_adaptive.integrate(fx1p,0, t.thickness_cm(), 1e-6, 1e-3,4); p.T = T; #ifdef REACTIONS res.sp = nonreaction_rate(p,t,c); #endif return res; } MultiResult calculate(Projectile &p, const Layers &layers, const Config &c){ MultiResult res; double e = p.T; res.total_result.Ein = e; res.results.reserve(layers.num()); double z = 0; double cov = 0; for(auto&m:layers.get_materials()){ z += m.thickness_cm(); Result r = calculate(p,m,e,c); e = r.Eout; res.total_result.Eloss += r.Eloss; res.total_result.sigma_E += r.sigma_E*r.sigma_E; res.total_result.tof += r.tof; res.total_result.Eout = r.Eout; double a2 = res.total_result.sigma_a; 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; //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; #ifdef REACTIONS res.total_result.sp = (r.sp>=0.0)?res.total_result.sp*r.sp:-1; #endif 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); res.total_result.sigma_x = sqrt(res.total_result.sigma_x); } else{ res.total_result.sigma_a = 0.0; res.total_result.sigma_E = 0.0; res.total_result.sigma_x = sqrt(res.total_result.sigma_x); } 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); } std::vector calculate_tof(Projectile p, const Material &t, const Config &c){ double res; std::vector 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;idouble{ return 1.0/dedx(p(x),t,c); }; auto fomega = [&](double x)->double{ //return 1.0*domega2dx(p,x,t)/pow(dedx(p(x),t),3); return domega2dx(p,x,t,c)/catima::power(dedx(p(x),t,c),3); }; double res; //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; dp.range[0] = 0.0; res = da2dx(p,energy_table(0),t)*res; dp.angular_variance[0] = 0.0; //res = integrator.integrate(fomega,Ezero,energy_table(0)); //res = p.A*res; dp.range_straggling[0]=0.0; for(int i=1;idouble{ return 1.0/dedx(p(x),t,c); }; auto fomega = [&](double x)->double{ return domega2dx(p,x,t,c)/catima::power(dedx(p(x),t,c),3); }; //double res=0.0; //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; 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; //p.T = energy_table(0); for(int i=1;idouble{return 1.0/(dedx(p(x),t,c)*beta_from_T(x));}; res = integrator.integrate(function,Eout,p.T); res = res*10.0*p.A/(c_light*t.density()); return res; } std::pair w_magnification(Projectile p, double Ein, const Material &t, const Config &c){ std::pair res{1.0,1.0}; if(t.density()<= 0.0 || t.thickness()<=0){ return res; } std::vector energies{0.99*Ein, Ein, 1.01*Ein}; auto eres = energy_out(p,energies,t,c); if(eres[0]>0.0 && eres[1]>0.0 && eres[2]>0.0){ 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) ) ); } else { res.first = 0.0; res.second = 0.0; } return res; } } // end of atima namespace