00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "gismo/Material.h"
00022
00023 #include "gismo/Units.h"
00024 #include "facilities/error.h"
00025 #include <math.h>
00026 #include <cstdio>
00027
00028
00029 #include <strstream>
00030 #include <fstream>
00031 #include <iomanip>
00032
00033
00034
00035 Material* Material::firstMaterial=0;
00036 Material* Material::vacuum = 0;
00037
00038
00039
00040 #ifndef DEFPEGS4PATH
00041 # define DEFPEGS4PATH "PEGS4"
00042 #endif
00043
00044 static std::string* defaultPath()
00045 {
00046 std::string defPath(DEFPEGS4PATH);
00047
00048 char *penv = getenv("PEGS4PATH");
00049 std::string *path;
00050 if (penv != NULL && strlen(penv) > 0) {
00051 path = new std::string(penv);
00052 if (defPath.length() > 0) *path += ':';
00053 }
00054 else
00055 path = new std::string;
00056
00057 *path += defPath;
00058 return path;
00059 }
00060
00061 std::string *Material::s_dataPath = defaultPath();
00062
00063
00064 void Material::dataPath(const char* path)
00065 {
00066 if ( s_dataPath ) delete s_dataPath;
00067 s_dataPath = new std::string(path);
00068 }
00069
00070 void Material::addPath(const char* path)
00071 {
00072 *s_dataPath = std::string(path) + ':' + *s_dataPath;
00073 }
00074
00075 const char *Material::getDataPath()
00076 {
00077 return s_dataPath->c_str();
00078 }
00079
00080 static std::istream * OpenReadFile(const std::string & fileName)
00081 {
00082 std::ifstream * is;
00083
00084
00085 if ( fileName[0] == '/' ) {
00086 is = new std::ifstream(fileName.c_str(), std::ios::in);
00087 if ( ! is->is_open() )
00088 {
00089 FATAL((std::string("Material description file '")+fileName+std::string("' does not exist.")).c_str());
00090 delete is;
00091 }
00092 return is;
00093 }
00094
00095
00096
00097 std::string fullFileName;
00098 std::istrstream path(Material::getDataPath());
00099 char directory[256];
00100
00101
00102 while ( path ) {
00103 path.getline(directory, 256, ':');
00104 fullFileName = std::string(directory) + '/' + fileName;
00105 is = new std::ifstream(fullFileName.c_str(), std::ios::in);
00106 if ( is->is_open() )
00107 return is;
00108 else
00109 delete is;
00110 }
00111
00112
00113
00114 is = new std::ifstream(fileName.c_str(), std::ios::in);
00115 if ( is->is_open() )
00116 return is;
00117 else delete is;
00118
00119
00120 FATAL((std::string("PEGS4 file '") + fileName + std::string("' not found.\nPath was ")
00121 + std::string(Material::getDataPath())).c_str() );
00122 return is;
00123 }
00124
00125
00126 Material*
00127 Material::hatch(const char* name)
00128 {
00129 if( vacuum==0) vacuum = new Material();
00130 std::string sname(name);
00131 if( sname.length()==0
00132 || sname == "vacuum" )
00133 return vacuum;
00134
00135
00136
00137 Material * m = firstMaterial;
00138 for(; m; m = m->nextMaterial)
00139 if( std::string(name) == m->m_fileName)
00140 return m;
00141
00142 std::string nameExt = sname + ".mat";
00143 std::istream* fin = OpenReadFile(nameExt);
00144
00145
00146
00147 m = new Material(*fin, name);
00148 delete fin;
00149
00150 if( firstMaterial ){
00151 Material* mat;
00152 for( mat=firstMaterial; mat->nextMaterial; mat = mat->nextMaterial);
00153 mat->nextMaterial = m;
00154 }
00155 else {
00156 firstMaterial = m;
00157 }
00158 m->nextMaterial = 0;
00159
00160 return m;
00161 }
00162
00163 Material::Material(std::istream& fin, const char* fname)
00164 : m_fileName(fname)
00165 , energyLoss1(0)
00166 {
00167
00168
00169
00170
00171
00172
00173
00174
00175 char linebuf[90], type[7];
00176
00177 fin.getline(linebuf,90);
00178
00179 sscanf(linebuf, " %6s=%15[^,]", type, materialName);
00180 if( strcmp("MEDIUM",type) != 0) {
00181 std::ostrstream message;
00182 message << "Material file format for " << m_fileName << " is unrecognizable: should start MEDIUM=\n";
00183 message << "But first line was: '" << linebuf << "'\0";
00184 FATAL( message.str() );
00185 }
00186 int nne=0;
00187
00188 fin.getline(linebuf,90);
00189 sscanf(linebuf, " %4s,RHO=%f,NE=%i", type, &rho, &nne);
00190 if( nne<0 || nne > 10 ) {
00191 std::ostrstream message;
00192 message << "Material file format problem: bad number of elements\n";
00193 message << "data line: '" << linebuf << "'\0";
00194 FATAL( message.str() );
00195 }
00196
00197
00198 #if 1
00199 std::cout << "Material name: " << materialName
00200 << ", Type: "<< type
00201 << ", rho=" << rho
00202 << ", # elements: " << nne << '\n';
00203 #endif
00204
00205
00206
00207 float pznorm = 0;
00208 zeff = aeff = 0;
00209
00210 for (int ie = 0; ie<nne; ie++) {
00211 fin.getline(linebuf,90);
00212 AtomicElement* ae = addElement(linebuf);
00213 pznorm += ae->pz;
00214 zeff += ae->pz * ae->z;
00215 aeff += ae->pz * ae->a;
00216
00217 #if 1
00218 std::cout << "\tElement#" << (ie+1) << ": " << ae->name
00219 << ", Z=" << ae->z
00220 << ", A=" << ae->a
00221 << ", pz=" << ae->pz
00222 << ", rhoz=" << ae->rhoz << '\n';
00223 #endif
00224 }
00225
00226 zeff /= pznorm;
00227 aeff /= pznorm;
00228
00229
00230
00231
00232
00233 fin >> rlc;
00234
00235
00236
00237
00238 MatData_list * vaclist = &vacuum->matDataList;
00239
00240 for( MatData_list::iterator it=vaclist->begin(); it<vaclist->end(); ++it){
00241 MatData* mdv = *it;
00242 MatData* md = mdv->copy();
00243 md->read( fin, *this );
00244 matDataList.push_back( md );
00245 }
00246
00247 }
00248
00249
00250
00251 Material::AtomicElement*
00252 Material::addElementData(char* name, float Z,
00253 float A, float fraction, float density)
00254 {
00255 AtomicElement* ae = new AtomicElement(name,Z,A,fraction,density);
00256 elementList.push_back(ae);
00257 return ae;
00258
00259 }
00260
00261
00262 Material::AtomicElement*
00263 Material::addElement(const char* buffer)
00264 {
00265 char name[3];
00266 float Z,A,f,d;
00267 sscanf(buffer, " ASYM=%2c, Z=%f, A=%f, PZ=%f, RHOZ=%f",
00268 name, &Z, &A, &f, &d);
00269 name[2] = '\0';
00270 return addElementData(name,Z,A,f,d);
00271 }
00272
00273
00274
00275
00276
00277
00278 float Material::dedx(float beta, float eta) const
00279 {
00280
00281 if( !energyLoss1 ) {
00282 Material* This = const_cast<Material*>(this);
00283 This->energyLoss1= Units::fromMeV(0.3071f) * Z()/A() * density();
00284 if( Z()>1 ) This->IP = 16. * pow((Z()), 0.9F);
00285 else This->IP = 19.2f;
00286
00287 This->energyLoss2= 1.022e6 / IP ;
00288 This->energyLoss3= log(IP/(28.816*sqrt(density())));
00289 }
00290
00291
00292 float arg2, arg1 = eta*eta * energyLoss2*beta;
00293 if(arg1 > 1) arg2 = log(arg1)- beta*beta
00294 -0.5*density_correction(eta);
00295 else arg2 = 1.;
00296 if(arg2 < 0.) arg2 = 1.;
00297
00298 return energyLoss1/(beta*beta) *arg2;
00299
00300 }
00301
00302 float Material::density_correction(float eta) const {
00303 float x0,x1;
00304 float cc = 1.0+ 2.0*energyLoss3;
00305
00306 if(density() > 0.05)
00307
00308 {
00309 if(IP < 100.){ x0 = (cc<3.681) ? 0.2 : 0.326*cc-1.; x1=2.;}
00310 else { x0 = (cc<5.215) ? 0.2 : 0.326*cc-1.5; x1=3.;}
00311
00312 }else{
00313
00314 if(cc<12.25){
00315 int i=int((cc-10)/0.5)+1;
00316 if(i<0)i=0;
00317 if(i>4)i=4;
00318 x0=1.6+0.1*i; x1=4.;
00319 }else{
00320 if(cc < 13.804){
00321 x0=2.;x1=5.;
00322 }else{
00323 x0=0.326*cc-2.5; x1=5;
00324 }
00325 }
00326 }
00327
00328 float xa = cc/4.606; float xm = 3.;
00329 float aa = 4.606*(xa-x0)/pow(x1-x0,xm);
00330 float x = log10(eta);
00331 float delta = 0;
00332 if(x>x0){
00333 delta=4.606*x-cc;
00334 if(x<x1)delta+=aa*pow(x1-x,xm);
00335 }
00336
00337 return delta;
00338
00339 }
00340
00341
00342
00343
00344 unsigned
00345 Material::declareMatData(MatData* mdnew)
00346 {
00347 if( Material::vacuum ==0 )
00348 Material::vacuum = new Material();
00349
00350 if( firstMaterial )
00351 FATAL("Material: cannot add new matdata object after a call to hatch");
00352
00353 vacuum->matDataList.push_back(mdnew);
00354 return vacuum->matDataList.size()-1;
00355 }
00356
00357
00358
00359 Material::AtomicElement::AtomicElement(char* pname, float pZ, float pA, float f, float den)
00360 : z(pZ)
00361 , a(pA)
00362 , pz(f)
00363 , rhoz(den)
00364 {
00365 strncpy(name, pname, 3);
00366 }
00367
00368 void
00369 Material::printAll(std::ostream& out)
00370 {
00371 out << "\n\t===========List of defined materials======================";
00372
00373 Material * mat = Material::firstMaterial;
00374 if( ! mat ) {
00375 out << "\n====================\n"
00376 << "No materials defined\n"
00377 << "====================\n";
00378 return;
00379 }
00380 unsigned i, n = mat->matDataList.size();
00381
00382
00383 out<< '\n' << std::setw (36) << " ";
00384 for(i=0; i< n ; i++ )
00385 mat->matDataList[i]->printHead1(out);
00386
00387
00388 out << '\n' <<std::setw(36) << " name Z A density ";
00389
00390 for(i=0; i< n ; i++ )
00391 mat->matDataList[i]->printHead2(out);
00392
00393 out << '\n';
00394
00395 while (mat ) {
00396 mat->printOn(out);
00397 mat = mat->nextMaterial;
00398 }
00399 }
00400 void
00401 Material::printOn(std::ostream& out)
00402 {
00403 out << std::setw(16) << m_fileName.c_str()
00404 << std::setw(6) << std::setprecision(3) << Z()
00405 << std::setw(6) << std::setprecision(3) << A()
00406 << std::setw(8) << density();
00407 for(unsigned i=0; i< matDataList.size() ; i++ )
00408 matDataList[i]->printOn(out);
00409
00410 out << '\n';
00411 }
00412
00413 Material::~Material()
00414 {
00415
00416 unsigned i, n = matDataList.size();
00417
00418 for(i=0; i< n ; i++ )
00419 delete matDataList[i];
00420
00421 if( this==vacuum) return;
00422
00423 Element_list::iterator eit = elementList.begin();
00424 while (eit != elementList.end() )
00425 delete (*eit++);
00426
00427 }
00428
00429 void Material::deleteAll()
00430 {
00431 Material * mat = Material::firstMaterial;
00432
00433 while (mat ) {
00434 Material* next = mat->nextMaterial;
00435 delete mat;
00436 mat = next;
00437 }
00438 delete s_dataPath;
00439 s_dataPath=0;
00440 delete vacuum;
00441 }