1
0
Fork 0
mirror of https://github.com/gwm17/catima.git synced 2024-11-23 02:38:51 -05:00

Merge pull request #15 from hrosiak/material

material class change
This commit is contained in:
Andrej Prochazka 2017-12-14 15:36:28 +01:00 committed by GitHub
commit aff32c24bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 198 additions and 92 deletions

View File

@ -26,47 +26,41 @@ bool operator==(const Config &a, const Config&b){
double dedx(Projectile &p, double T, const Material &mat, const Config &c){ double dedx(Projectile &p, double T, const Material &mat, const Config &c){
double sum = 0; double sum = 0;
Target t;
double w=0; double w=0;
if(T<=0)return 0.0; if(T<=0)return 0.0;
for(int i=0;i<mat.ncomponents();i++){ for(int i=0;i<mat.ncomponents();i++){
auto res = mat.get_element(i); auto t = mat.get_element(i);
t = res.first; //struct of target w = mat.weight_fraction(i);
w = res.second; //number of atoms of the element
p.T = T; p.T = T;
sum += t.A*w*dedx(p,t); sum += w*dedx(p,t);
} }
return sum/mat.M(); return sum;
} }
double domega2dx(Projectile &p, double T, const Material &mat, const Config &c){ double domega2dx(Projectile &p, double T, const Material &mat, const Config &c){
double sum = 0; double sum = 0;
Target t;
double w=0; double w=0;
for(int i=0;i<mat.ncomponents();i++){ for(int i=0;i<mat.ncomponents();i++){
auto res = mat.get_element(i); auto t= mat.get_element(i);
t = res.first; //struct of target w = mat.weight_fraction(i);
w = res.second; //number of atoms of the element
p.T = T; p.T = T;
sum += t.A*w*dedx_variance(p,t); sum += w*dedx_variance(p,t);
} }
return sum/mat.M(); return sum;
} }
double da2dx(Projectile &p, double T, const Material &mat, const Config &c){ double da2dx(Projectile &p, double T, const Material &mat, const Config &c){
double sum = 0; double sum = 0;
Target t;
double w=0; double w=0;
for(int i=0;i<mat.ncomponents();i++){ for(int i=0;i<mat.ncomponents();i++){
auto res = mat.get_element(i); auto t = mat.get_element(i);
t = res.first; //struct of target w = mat.weight_fraction(i);
w = res.second; //number of atoms of the element
p.T = T; p.T = T;
sum += t.A*w*angular_scattering_variance(p,t); sum += w*angular_scattering_variance(p,t);
} }
return sum/mat.M(); return sum;
} }

View File

@ -19,6 +19,7 @@ cdef class Material:
if(elements and isinstance(elements[0],list)): if(elements and isinstance(elements[0],list)):
for e in elements: for e in elements:
self.cbase.add_element(e[0],e[1],e[2]) self.cbase.add_element(e[0],e[1],e[2])
self.cbase.calculate()
if(not thickness is None): if(not thickness is None):
self.thickness(thickness) self.thickness(thickness)
if(not density is None): if(not density is None):
@ -82,6 +83,8 @@ class material(IntEnum):
CMO2 = 218 CMO2 = 218
SUPRASIL = 219 SUPRASIL = 219
HAVAR = 220 HAVAR = 220
STEEL = 221
METHANE = 222
def get_material(int matid): def get_material(int matid):
res = Material() res = Material()
@ -93,14 +96,17 @@ def get_material(int matid):
cdef class Target: cdef class Target:
cdef catimac.Target cbase cdef catimac.Target cbase
def __cinit__(self,a,z): def __cinit__(self,a,z,stn):
self.cbase.A = a self.cbase.A = a
self.cbase.Z = z self.cbase.Z = z
self.cbase.stn = stn
def A(self): def A(self):
return self.cbase.A return self.cbase.A
def Z(self): def Z(self):
return self.cbase.Z return self.cbase.Z
def stn(self):
return self.cbase.stn
cdef class Layers: cdef class Layers:
cdef public: cdef public:
@ -440,7 +446,7 @@ def storage_info():
matter = [] matter = []
for j in range(data.m.ncomponents()): for j in range(data.m.ncomponents()):
e = data.m.get_element(j) e = data.m.get_element(j)
matter.append([e.first.A,e.first.Z,e.second]) matter.append([e.A,e.Z,e.stn])
res.append({"projectile":[data.p.A,data.p.Z],"matter":matter}) res.append({"projectile":[data.p.A,data.p.Z],"matter":matter})
return res return res

View File

@ -5,7 +5,6 @@
:licence: GNU Affero General Public License, see LICENCE for more details :licence: GNU Affero General Public License, see LICENCE for more details
""" """
from libcpp.pair cimport pair
from libcpp.vector cimport vector from libcpp.vector cimport vector
from libcpp cimport bool from libcpp cimport bool
@ -13,6 +12,7 @@ cdef extern from "catima/structures.h" namespace "catima":
cdef struct Target: cdef struct Target:
double A double A
int Z int Z
double stn
cdef struct Projectile: cdef struct Projectile:
double A double A
@ -39,13 +39,14 @@ cdef extern from "catima/structures.h" namespace "catima":
cdef cppclass Material: cdef cppclass Material:
Material() except + Material() except +
void add_element(double , int , double ) void add_element(double , int , double )
pair[Target,double] get_element(int) Target get_element(int)
int ncomponents() int ncomponents()
double M() double M()
double density() double density()
void density(double val) void density(double val)
double thickness() double thickness()
void thickness(double val) void thickness(double val)
void calculate()
cdef cppclass Layers: cdef cppclass Layers:
Layers() except + Layers() except +

View File

@ -2,7 +2,7 @@
#define CONSTANTS_H #define CONSTANTS_H
namespace catima { namespace catima {
constexpr double Ezero = 9E-4; // lowest E to calculate, below taken as 0 constexpr double Ezero = 9E-4; // lowest E to calculate, below taken as 0
constexpr double logEmin = -3; // log of minimum energy constexpr double logEmin = -3; // log of minimum energy
constexpr double logEmax = 5.0; // log of max energy constexpr double logEmax = 5.0; // log of max energy
@ -10,10 +10,12 @@ constexpr int max_datapoints = 500; // how many datapoints between logEmin and l
constexpr int max_storage_data = 50; // number of datapoints which can be stored in cache constexpr int max_storage_data = 50; // number of datapoints which can be stored in cache
/// required integration precision (relative units) /// required integration precision (relative units)
constexpr double int_eps_range = 0.01; /*
constexpr double int_eps_range_str = 0.01; constexpr double int_eps_range = 0.001;
constexpr double int_eps_range_str = 0.001;
constexpr double int_eps_ang_str = 0.01; constexpr double int_eps_ang_str = 0.01;
constexpr double int_eps_tof = 0.01; constexpr double int_eps_tof = 0.01;
*/
constexpr double thin_target_limit = 1 - 1e-3; constexpr double thin_target_limit = 1 - 1e-3;

View File

@ -37,8 +37,8 @@ void Data::Add(const Projectile &p, const Material &t, Config c){
#if(0) #if(0)
*index = dp; *index = dp;
index->range = calculate_range(p,t,c); index->range = calculate_range(p,t,c);
index->range_straggling = calculate_range_straggling(p,t,c); index->range_straggling = calculate_range_straggling(p,t,c);
index->angular_variance = calculate_angular_variance(p,t,c); index->angular_variance = calculate_angular_variance(p,t,c);
#else #else
*index = calculate_DataPoint(p,t,c); *index = calculate_DataPoint(p,t,c);
#endif #endif

View File

@ -1,5 +1,6 @@
#include "structures.h" #include "structures.h"
#include "catima/nucdata.h" #include "catima/nucdata.h"
#include <algorithm>
namespace catima{ namespace catima{
@ -17,7 +18,7 @@ bool operator==(const Material &a, const Material&b){
if(a.density() != b.density())return false; if(a.density() != b.density())return false;
if(a.ncomponents() != b.ncomponents())return false; if(a.ncomponents() != b.ncomponents())return false;
for(int i=0;i<a.ncomponents();i++){ for(int i=0;i<a.ncomponents();i++){
if(a.stn[i] != b.stn[i])return false; if(a.atoms[i].stn != b.atoms[i].stn)return false;
if(a.atoms[i].A != b.atoms[i].A)return false; if(a.atoms[i].A != b.atoms[i].A)return false;
if(a.atoms[i].Z != b.atoms[i].Z)return false; if(a.atoms[i].Z != b.atoms[i].Z)return false;
} }
@ -31,9 +32,13 @@ Material::Material(const std::array<double,2> &list){
*/ */
Material::Material(std::initializer_list<std::array<double,3>>list,double _density):rho(_density){ Material::Material(std::initializer_list<std::array<double,3>>list,double _density):rho(_density){
std::initializer_list<std::array<double,3>>::iterator it; std::initializer_list<std::array<double,3>>::iterator it;
atoms.reserve(list.size());
for ( it=list.begin(); it!=list.end(); ++it){ for ( it=list.begin(); it!=list.end(); ++it){
add_element( (*it)[0],(*it)[1],(*it)[2]); add_element((*it)[0],(*it)[1],(*it)[2]);
} }
calculate(); // calculate if needed, ie average molar mass
} }
Material::Material(double _a, int _z, double _rho, double _th):rho(_rho),th(_th){ Material::Material(double _a, int _z, double _rho, double _th):rho(_rho),th(_th){
@ -42,24 +47,20 @@ Material::Material(double _a, int _z, double _rho, double _th):rho(_rho),th(_th)
void Material::add_element(double _a, int _z, double _stn){ void Material::add_element(double _a, int _z, double _stn){
double a = (_a>0)?_a:element_atomic_weight(_z); double a = (_a>0)?_a:element_atomic_weight(_z);
stn.push_back(_stn); atoms.push_back({a,_z,_stn});
atoms.push_back({a,_z});
molar_mass += _stn*a; molar_mass += _stn*a;
} }
std::pair<Target,double> Material::get_element(int i) const{
return std::pair<Target,double>(atoms[i],stn[i]);
}
/*
void Material::calculate(){ void Material::calculate(){
molar_mass = 0; if(std::all_of(atoms.begin(),atoms.end(),[](const Target &t){return t.stn<1.0;})){
for(int i=0;i<ncomponents();i++){ double sum = 0;
molar_mass += stn[i]*a[i]; for(auto& e: atoms){
sum+= e.stn/e.A;
}
molar_mass = 1.0/sum;
} }
} }
*/
Layers& Layers::operator=(const Layers& other){ Layers& Layers::operator=(const Layers& other){

View File

@ -51,6 +51,7 @@ namespace catima{
struct Target{ struct Target{
double A=0; double A=0;
int Z=0; int Z=0;
double stn=1.0;
}; };
/** /**
@ -65,7 +66,6 @@ namespace catima{
double th=0; double th=0;
double molar_mass=0; double molar_mass=0;
std::vector<Target>atoms; std::vector<Target>atoms;
std::vector<double>stn;
public: public:
Material(){}; Material(){};
@ -91,6 +91,9 @@ namespace catima{
Material(std::initializer_list<std::array<double,3>>list,double _density=0.0); Material(std::initializer_list<std::array<double,3>>list,double _density=0.0);
//Material(const std::array<double,2> &list); //Material(const std::array<double,2> &list);
/**
* calculates internal variables if needed
*/
void calculate(); void calculate();
/** /**
@ -104,14 +107,20 @@ namespace catima{
/** /**
* returns i-th element of the Material as a std::pair of Target and corresponding stoichiometric number * returns i-th element of the Material as a std::pair of Target and corresponding stoichiometric number
* @param i - index of element to return * @param i - index of element to return
* @return std::pair of Target and corresponding stoichiometric number * @return Target class
*/ */
std::pair<Target,double> get_element(int i) const; Target get_element(int i) const {return atoms[i];};
/**
* return weight fraction of i-th element
* @return weight fraction
*/
double weight_fraction(int i) const {return (atoms[i].stn<1.0)?atoms[i].stn:atoms[i].stn*atoms[i].A/M();};
/** /**
* @return number of components in Material * @return number of components in Material
*/ */
int ncomponents() const {return stn.size();} int ncomponents() const {return atoms.size();}
/** /**
* @return returns Molar Mass of the Material * @return returns Molar Mass of the Material

View File

@ -1,9 +1,9 @@
#include "lest.hpp" #include "lest.hpp"
#include "testutils.h"
#include <math.h> #include <math.h>
using namespace std; using namespace std;
using catima::approx;
#include "catima/catima.h" #include "catima/catima.h"
using lest::approx;
bool rcompare(double a, double b,double eps){ bool rcompare(double a, double b,double eps){
if(fabs((a-b)/fabs(b))<eps){ if(fabs((a-b)/fabs(b))<eps){
return true; return true;
@ -333,9 +333,13 @@ const lest::test specification[] =
auto air = catima::get_material(catima::material::Air); auto air = catima::get_material(catima::material::Air);
air.thickness(0.500); air.thickness(0.500);
auto res = catima::calculate(p(350),air); auto res = catima::calculate(p(350),air);
EXPECT(res.Eout == approx(345.6).epsilon(1e-2)); EXPECT(res.Eout == approx(345.6).epsilon(1.0));
EXPECT(res.sigma_a == approx(0.0013).epsilon(1e-2)); EXPECT(res.sigma_a == approx(0.0013).epsilon(1e-4));
EXPECT(res.sigma_E == approx(0.12).epsilon(1e-2)); EXPECT(res.sigma_E == approx(0.12).epsilon(1e-3));
auto water = catima::get_material(catima::material::Water);
auto res2 = catima::calculate(p(600),water,600);
EXPECT(res2.dEdxi == approx(92.5).epsilon(2));
} }
}; };

View File

@ -44,8 +44,8 @@ double rdif(double v1, double v2){
void comp_dedx(catima::Projectile p, catima::Material t, double epsilon = 0.001, bool fout=false, const char* fname=""){ void comp_dedx(catima::Projectile p, catima::Material t, double epsilon = 0.001, bool fout=false, const char* fname=""){
double dif; double dif;
//struct atima_results results; //struct atima_results results;
int tz = t.get_element(0).first.Z; int tz = t.get_element(0).Z;
double ta = t.get_element(0).first.A; double ta = t.get_element(0).A;
bool res; bool res;
cout<<"-----------------------------"<<endl; cout<<"-----------------------------"<<endl;
cout<<"projectile: A = "<<p.A<<", Z = "<<p.Z<<endl; cout<<"projectile: A = "<<p.A<<", Z = "<<p.Z<<endl;

View File

@ -1,6 +1,8 @@
#include "lest.hpp" #include "lest.hpp"
#include "testutils.h"
#include <math.h> #include <math.h>
using namespace std; using namespace std;
using catima::approx;
#include "catima/catima.h" #include "catima/catima.h"
#include "catima/material_database.h" #include "catima/material_database.h"
@ -57,28 +59,25 @@ const lest::test specification[] =
CASE("Material automatic atomic weight"){ CASE("Material automatic atomic weight"){
catima::Material water({{0,1,2},{0,8,1}}); catima::Material water({{0,1,2},{0,8,1}});
catima::Material graphite(0,6); catima::Material graphite(0,6);
EXPECT(water.get_element(0).first.A == 1.00794); EXPECT(water.get_element(0).A == 1.00794);
EXPECT(water.get_element(1).first.A == 15.9994); EXPECT(water.get_element(1).A == 15.9994);
EXPECT(graphite.get_element(0).first.A == 12.0107); EXPECT(graphite.get_element(0).A == 12.0107);
EXPECT(water.M()>16); EXPECT(water.M()>16);
EXPECT(graphite.M()>12); EXPECT(graphite.M()>12);
}, },
CASE("default materials"){ CASE("default materials"){
catima::Material m = catima::get_material(6); catima::Material m = catima::get_material(6);
EXPECT(m.get_element(0).first.A == 12.0107); EXPECT(m.get_element(0).A == 12.0107);
EXPECT(m.get_element(0).first.Z == 6); EXPECT(m.get_element(0).Z == 6);
EXPECT(m.density() == 2.0); EXPECT(m.density() == 2.0);
EXPECT(m.M() == 12.0107); EXPECT(m.M() == 12.0107);
m = catima::get_material(catima::material::Water); m = catima::get_material(catima::material::Water);
EXPECT(m.get_element(0).first.A == 1.00794); EXPECT(m.get_element(0).A == 1.00794);
EXPECT(m.get_element(0).first.Z == 1); EXPECT(m.get_element(0).Z == 1);
EXPECT(m.get_element(1).first.A == 15.9994); EXPECT(m.get_element(1).A == 15.9994);
EXPECT(m.get_element(1).first.Z == 8); EXPECT(m.get_element(1).Z == 8);
EXPECT(m.density() == 1.0); EXPECT(m.density() == 1.0);
EXPECT(m.M() > 16.0);
}, },
CASE("Layers"){ CASE("Layers"){
catima::Material water2; catima::Material water2;
@ -102,10 +101,10 @@ const lest::test specification[] =
EXPECT(detector1[0].thickness()==1.0); EXPECT(detector1[0].thickness()==1.0);
EXPECT(detector1[1].density()==1.0); EXPECT(detector1[1].density()==1.0);
EXPECT(detector1[1].thickness()==2.0); EXPECT(detector1[1].thickness()==2.0);
EXPECT(detector1[0].get_element(0).first.Z == 6); EXPECT(detector1[0].get_element(0).Z == 6);
EXPECT(detector1[0].get_element(0).first.A == 12); EXPECT(detector1[0].get_element(0).A == 12);
EXPECT(detector1[1].get_element(0).first.A == 1); EXPECT(detector1[1].get_element(0).A == 1);
EXPECT(detector1[1].get_element(0).first.Z == 1); EXPECT(detector1[1].get_element(0).Z == 1);
EXPECT(detector1[2].density() == 1.8); EXPECT(detector1[2].density() == 1.8);
detector1[1].density(1.2); detector1[1].density(1.2);
EXPECT(detector1[1].density()==1.2); EXPECT(detector1[1].density()==1.2);
@ -163,43 +162,62 @@ const lest::test specification[] =
}); });
EXPECT(mat2.ncomponents()==1); EXPECT(mat2.ncomponents()==1);
EXPECT(mat3.ncomponents()==1); EXPECT(mat3.ncomponents()==1);
EXPECT(mat3.get_element(0).first.A==12.01); EXPECT(mat3.get_element(0).A==12.01);
EXPECT(mat4.ncomponents()==1); EXPECT(mat4.ncomponents()==1);
EXPECT(mat4.get_element(0).first.A==12.01); EXPECT(mat4.get_element(0).A==12.01);
EXPECT(mat5.ncomponents()==2); EXPECT(mat5.ncomponents()==2);
EXPECT(mat5.get_element(0).first.A==12.01); EXPECT(mat5.get_element(0).A==12.01);
EXPECT(mat5.get_element(0).first.Z==6); EXPECT(mat5.get_element(0).Z==6);
EXPECT(mat5.get_element(1).first.A==16.0); EXPECT(mat5.get_element(1).A==16.0);
EXPECT(mat5.get_element(1).second==2); EXPECT(mat5.get_element(1).stn==2);
catima::Material mat6; catima::Material mat6;
mat6 = mat5; mat6 = mat5;
EXPECT(mat5==mat6); EXPECT(mat5==mat6);
EXPECT(mat5.ncomponents()==mat6.ncomponents()); EXPECT(mat5.ncomponents()==mat6.ncomponents());
EXPECT(mat5.get_element(0).first.A==mat6.get_element(0).first.A); EXPECT(mat5.get_element(0).A==mat6.get_element(0).A);
EXPECT(mat5.get_element(1).first.A==mat6.get_element(1).first.A); EXPECT(mat5.get_element(1).A==mat6.get_element(1).A);
mat5.add_element(12,6,1); mat5.add_element(12,6,1);
EXPECT(mat5.ncomponents()==mat6.ncomponents()+1); EXPECT(mat5.ncomponents()==mat6.ncomponents()+1);
}, },
CASE("int and double stn check"){ CASE("fraction vs stn init"){
catima::Projectile p{1,1,1,1000}; catima::Projectile p{12,6};
catima::Material mat1({ catima::Material water1({
{12.01, 6, 1}, {0, 1, 0.111894},
{16.00, 8, 1} {0, 8, 0.888106}
}); });
catima::Material mat2({ catima::Material water2({
{12.01, 6, 0.5}, {0, 1, 2},
{16.00, 8, 0.5} {0, 8, 1}
}); });
mat1.thickness(1.0); water1.thickness(1.0);
mat2.thickness(1.0); water2.thickness(1.0);
auto res1 = catima::calculate(p(1000),mat1); auto res1 = catima::calculate(p(600),water1);
auto res2 = catima::calculate(p(1000),mat2); auto res2 = catima::calculate(p(600),water2);
EXPECT(res1.dEdxi == res2.dEdxi); EXPECT(res1.dEdxi == approx(res2.dEdxi,0.001));
EXPECT(res1.range == res2.range); EXPECT(res1.range == approx(res2.range).R(1e-2));
EXPECT(res1.sigma_a == res2.sigma_a); EXPECT(res1.sigma_a == approx(res2.sigma_a).R(1e-2));
EXPECT(res1.sigma_r == res2.sigma_r); EXPECT(res1.sigma_r == approx(res2.sigma_r).R(1e-2));
},
CASE("fraction calculation"){
catima::Material water1({
{0, 1, 0.111894},
{0, 8, 0.888106}
});
catima::Material water2({
{0, 1, 2},
{0, 8, 1}
});
EXPECT(water1.weight_fraction(0)==0.111894);
EXPECT(water2.weight_fraction(0)==approx(water1.weight_fraction(0)).R(1e-3));
EXPECT(water1.weight_fraction(1)==0.888106);
EXPECT(water2.weight_fraction(1)==approx(water1.weight_fraction(1)).R(1e-3));
EXPECT(water2.M()==approx(18).epsilon(0.1));
EXPECT(water1.M()==approx(6.0,0.1));
EXPECT(water2.M()==approx(18,0.1));
} }
}; };

71
tests/testutils.h Normal file
View File

@ -0,0 +1,71 @@
namespace catima{
class approx
{
public:
explicit approx ( double magnitude, double eps=1.0)
: epsilon_ { eps }
, magnitude_{ magnitude } {}
approx( approx const & other ) = default;
approx operator()( double magnitude, double eps = 1.0 )
{
approx approx ( magnitude, eps);
return approx;
}
double magnitude() const { return magnitude_; }
approx & epsilon( double epsilon ) { epsilon_ = epsilon; return *this; }
approx & R( double relative ) { epsilon_ = relative*magnitude_; return *this; }
friend bool operator == ( double lhs, approx const & rhs )
{
return std::abs( lhs - rhs.magnitude_) < rhs.epsilon_;
}
friend bool operator == ( approx const & lhs, double rhs ) { return operator==( rhs, lhs ); }
friend bool operator != ( double lhs, approx const & rhs ) { return !operator==( lhs, rhs ); }
friend bool operator != ( approx const & lhs, double rhs ) { return !operator==( rhs, lhs ); }
friend bool operator <= ( double lhs, approx const & rhs ) { return lhs < rhs.magnitude_ || lhs == rhs; }
friend bool operator <= ( approx const & lhs, double rhs ) { return lhs.magnitude_ < rhs || lhs == rhs; }
friend bool operator >= ( double lhs, approx const & rhs ) { return lhs > rhs.magnitude_ || lhs == rhs; }
friend bool operator >= ( approx const & lhs, double rhs ) { return lhs.magnitude_ > rhs || lhs == rhs; }
//private:
double epsilon_;
double magnitude_;
};
std::ostream & operator<<(std::ostream &os, approx const &a){
using lest::to_string;
return os<<to_string(a.magnitude_)<<" +- "<<a.epsilon_;
}
bool rdiff(double a, double b,double eps){
if(fabs((a-b)/fabs(b))<eps){
return true;
}
else{
std::cout<<"\033[1;31m"<<a<<" == "<<b<<"\033[0m"<<std::endl;
return false;
}
}
bool diff(double a, double b,double eps){
if(fabs((a-b))<eps){
return true;
}
else{
std::cout<<"\033[1;31m"<<a<<" == "<<b<<"\033[0m"<<std::endl;
return false;
}
}
}