Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Material.cxx

Go to the documentation of this file.
00001 // $Id: Material.cxx,v 1.2 2001/08/08 05:51:11 chehtman Exp $
00002 //
00003 // This file is part of Gismo 2
00004 //
00005 // Contents ----------------------------------------------------------------
00006 //
00007 //  Material::hatch
00008 //  Material::Material(std::istream& fin, int iray)
00009 //  void Material::addElement(char* name, float Z,
00010 //     float Material::dedx(float beta, float eta)
00011 //
00012 //  AtomicElement::AtomicElement(char* pname, float pZ, float pA, float f,
00013 //      float den, AtomicElement* pnext)
00014 
00015 // Description
00016 //
00017 //   implementation of class Material and struct Material::AtomicElement
00018 //
00019 // End --------------------------------------------------------------------
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 // ----------------allocate static variables ----------------------------
00035 Material* Material::firstMaterial=0;
00036 Material* Material::vacuum = 0;
00037 
00038 
00039 //--------------------------- path manipulation code, data ---------------------
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 //---------------------- function OpenReadFile --------------------------
00080 static std::istream * OpenReadFile(const std::string & fileName)
00081 {
00082     std::ifstream * is;
00083   // check for absolute pathname
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     // next, see if we can find it in the search path
00096 
00097     std::string fullFileName;
00098     std::istrstream path(Material::getDataPath());
00099     char directory[256];                // should be FILENAME_MAX, but gcc stdio.h
00100                                 // for a Sun does not have it.
00101 
00102     while ( path ) {
00103          path.getline(directory, 256, ':');     //THB: changed get to getline
00104          fullFileName = std::string(directory) + '/' + fileName;
00105          is = new std::ifstream(fullFileName.c_str(), std::ios::in);
00106          if ( is->is_open() )  //note standard library form
00107             return is;
00108          else
00109             delete is;
00110     }
00111 
00112     // maybe it is in the current directory
00113 
00114     is = new std::ifstream(fileName.c_str(), std::ios::in);
00115     if ( is->is_open() )  //note standard library form
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 // -----------------member function Material::hatch ----------------------
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     // check to see if the material has been hatched already
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     // create a new Material and link it into the list of Materials
00146     // (should now use a map: THB)
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 // ------------constructor Material::Material, from stream --------------
00163 Material::Material(std::istream& fin, const char* fname)
00164 : m_fileName(fname)
00165 , energyLoss1(0)
00166 {
00167         // start reading file, in PEGS4 format, example follows
00168 /*
00169  MEDIUM=Liquid Argon            ,STERNCID=LIQUID ARGON
00170  ELEM,RHO= 1.4000E+00,NE= 1
00171  ASYM=Ar,Z=18.,A=   39.948,PZ= 1.00000E+00,RHOZ= 3.99480E+01
00172     1.39648E+01   1.50000E+00   1.00000E-01   1.00000E+05   1.00000E+05
00173      0   63    0  150    0    0    0    0    0
00174 */
00175     char linebuf[90], type[7];
00176 
00177     fin.getline(linebuf,90);
00178 //    sscanf(linebuf, " %6s=%15s", type, materialName);
00179     sscanf(linebuf, " %6s=%15[^,]", type, materialName); //materialName up to comma
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   // here loop over nne
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   // the first quantitiy after the atomic element data is the radiation length. This is used
00231   // to calculate multiple scattering and must be done if egs is not loaded
00232 
00233     fin >> rlc;
00234 
00235   // finally, read all the cross section data, using copies of
00236   // mat data objects in Vacuum
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 // -------------member functions Material::addElement ---------------
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 // ASYM=Ar,Z=18.,A=   39.948,PZ= 1.00000E+00,RHOZ= 3.99480E+01
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 // -----------------member function Material::dedx ---------------------
00274 
00275 // This formula,and the calculations of the constants,
00276 // are adapted from the PDG section on Passage of Particle through Matter
00277 
00278 float Material::dedx(float beta, float eta) const
00279 {
00280 
00281     if( !energyLoss1 ) {
00282         Material* This = const_cast<Material*>(this); // cast from const
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;   // for H2 gas: 21.8 for liquid
00286 
00287         This->energyLoss2= 1.022e6 / IP ;  // const is 2 * me in eV
00288     This->energyLoss3= log(IP/(28.816*sqrt(density()))); //density correction
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 // condensed material   
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 // gas
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 // -------------static member function Material::declareMatData----------
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   // add this object to the list attached to Vacuum
00353   vacuum->matDataList.push_back(mdnew);
00354   return vacuum->matDataList.size()-1;
00355 }
00356 
00357 // ---------------- constructor AtomicElement::AtomicElement ----------
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 // -------------static member function Material::printAll----------
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     // first header line:
00383     out<< '\n' << std::setw (36) << "                                    ";
00384     for(i=0; i< n ; i++ )
00385         mat->matDataList[i]->printHead1(out);
00386 
00387     // second header line:
00388     out << '\n' <<std::setw(36) <<  "            name    Z    A   density  ";
00389     //                          12345678901234567890123456789012345678
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() //title()
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 }

Generated at Mon Nov 26 18:18:33 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000