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

RCParticle.cxx

Go to the documentation of this file.
00001 //  $Id: RCParticle.cxx,v 1.1 2001/09/22 16:41:38 burnett Exp $
00002 //
00003 // This file is part of Gismo 2
00004 //
00005 //
00006 // Implemention of all RCParticle member functions
00007 
00008 #include "gismo/RCParticle.h"
00009 
00010 #include "gismo/Medium.h"
00011 #include "gismo/Material.h"
00012 #include "gismo/Detector.h"
00013 #include "gismo/Units.h"
00014 #include "gismo/PDT.h"
00015 #include "gismo/World.h"
00016 
00017 #include "geometry/Ray.h"
00018 #include "geometry/Volume.h"
00019 
00020 #include "facilities/error.h"
00021 #include <cassert>
00022 
00023 /********************************************************************
00024  *                RCParticle                                        *
00025  ********************************************************************/
00026 #ifdef DUMP_STEP // special debug output
00027 # include <fstream>
00028  static std::ofstream fout("dump_step.prn");
00029 #endif
00030 
00031 const Medium* RCParticle::s_world=0;
00032 
00033 RCParticle::RCParticle(Point x0, Vector t0, float dist = 0)
00034         : GParticle("e-")
00035         , m_maxArcLen(dist)
00036 {   
00037     setPosition(x0);
00038     setMomentum(t0);
00039 
00040     assert(s_world != 0);
00041 
00042     m_currentMedium = s_world->inside(x0);
00043     ini();
00044     if(dist > 0) { propagate();}
00045 }
00046 
00047 RCParticle::~RCParticle()
00048 { 
00049 }
00050 
00051 // Initializes RCParticle for propagation
00052 void RCParticle::ini()
00053 {
00054   m_arcLength = m_properTime = m_radLength = 0.;
00055   m_stepcount = 0;
00056   Medium::setLastMedium(0);
00057   m_lastMedium = m_currentMedium;
00058   while (m_stepList.size() > 0) {
00059       m_stepList.pop_back();
00060   }
00061 }
00062 
00063 //  RCParticle::propagate -- propagate the particle for a distance 
00064 //              specified by maxArcLen or until it leaves the World
00065 //
00066 void RCParticle::propagate() {
00067 
00068 // Set max-step here incase a continuation of previous projection
00069   m_maxStep = m_maxArcLen+.0001;
00070   setStatus( ALIVE );
00071 // Loop until we're out.... 
00072   while (status()==ALIVE)
00073   {
00074     const Medium * nextMedium=m_currentMedium;  // a temporary for new medium
00075 
00076         // return a Ray that estimates the trajectory (or a point)
00077 
00078         Ray *m_segment=
00079             m_currentMedium->CreateRay( position(), momentum(), charge(), m_maxStep );
00080 
00081         // flag this segment
00082         m_segment->setFlag(m_stepcount);
00083 
00084         // ask the Medium for a distance along that ray, (unless
00085         // the particle is at rest),and for possible detector
00086         m_step = m_currentMedium->distanceToLeave(*m_segment, nextMedium, m_maxStep);
00087         if (m_step < m_maxStep) {  // hit a boundary
00088             setStatus( ALIVE );
00089             //NEW CODE >>>>>> Cross the multiple shared surfaces..... 
00090             while(m_step < Volume::Surface_EPSILON && status()==ALIVE) {
00091                 if(m_currentMedium == nextMedium) setStatus (STUCK);
00092                 Medium::setLastMedium(m_currentMedium);
00093                 m_lastMedium = m_currentMedium;
00094                 m_currentMedium = nextMedium;
00095                 m_step = m_currentMedium->distanceToLeave(*m_segment, nextMedium, m_maxStep);
00096             }
00097         }       
00098         if (m_step == FLT_MAX || (m_step<=0 && m_currentMedium==nextMedium) )   {
00099             WARNING( "RCParticle::propagate -- we are lost or stuck!");
00100             setStatus( STUCK );
00101             break;
00102         }
00103         else if( m_step > m_maxStep) {
00104             // maxStep was ignored above: assume still in same medium
00105             m_step = m_maxStep;
00106             nextMedium = m_currentMedium;
00107         }
00108         
00109         // increment along trajectory by arclength step
00110         if(m_step > 0) {
00111             stepBy(m_step, *m_segment );
00112         }
00113     Medium::setLastMedium(m_currentMedium);
00114     m_lastMedium = m_currentMedium;
00115     delete m_segment; 
00116 
00117     // We've reached the boundary: update current medium and see if we've left
00118     if ( status()==ALIVE && (m_currentMedium=nextMedium)==0 ){ setStatus(LEFT);}
00119     else if( m_arcLength > m_maxArcLen)                      { setStatus(DONE);}
00120     else {
00121       m_stepcount ++;
00122       m_maxStep = m_maxArcLen - m_arcLength + .001;
00123     }
00124   }
00125 }
00126 
00127 bool RCParticle::propagate(const char * stop_med_title) {
00128 
00129 // Set max-step - done here incase a continuation of previous projection
00130   m_maxStep = m_maxArcLen+.0001;
00131   setStatus( ALIVE );
00132 
00133 // Loop until we're out.... 
00134   while (status()==ALIVE)
00135   {
00136     const Medium * nextMedium=m_currentMedium;  // a temporary for new medium
00137 
00138         // return a Ray that estimates the trajectory (or a point)
00139 
00140         Ray *m_segment= 
00141             m_currentMedium->CreateRay( position(), momentum(), charge(), m_maxStep );
00142 
00143        // flag this segment
00144         m_segment->setFlag(m_stepcount);
00145 
00146         // ask the Medium for a distance along that ray, (unless
00147         // the particle is at rest),and for possible detector
00148 
00149         m_step = m_currentMedium->distanceToLeave(*m_segment, nextMedium, 100.);
00150         if (m_step < m_maxStep) {  // hit a boundary
00151             setStatus( ALIVE );
00152         }       
00153         if (m_step == FLT_MAX || (m_step<=0 && m_currentMedium==nextMedium) )   {
00154             WARNING( "RCParticle::propagate -- we are lost or stuck!");
00155             setStatus( STUCK );
00156             break;
00157         }
00158         else if( m_step > m_maxStep) {
00159             // maxStep was ignored above: assume still in same medium
00160             m_step = m_maxStep;
00161             nextMedium = m_currentMedium;
00162         }
00163         
00164         // increment along trajectory by arclength step
00165         if(m_step > 0) {
00166             stepBy(m_step, *m_segment );
00167         }
00168 
00169     Medium::setLastMedium(m_currentMedium);
00170     m_lastMedium = m_currentMedium;
00171     delete m_segment;
00172 
00173     // At a boundary... check the current Medium is the stopping place
00174     if(strcmp(stop_med_title, m_currentMedium->title()) == 0 ) {
00175         setStatus(DONE);
00176         return true;
00177     } 
00178 
00179     // We've reached the boundary: update current medium and see if we've left
00180     if ( status()==ALIVE && (m_currentMedium=nextMedium)==0 ){ setStatus(LEFT);}
00181     else if( m_arcLength > m_maxArcLen)                      { setStatus(DONE);}
00182     else {
00183       m_stepcount ++;
00184       m_maxStep = m_maxArcLen - m_arcLength + .0001; 
00185     }
00186   }
00187   return false;
00188 }
00189 
00190 void
00191 RCParticle::stepBy(float step, Ray & path)
00192 {
00193     double paverage = momentum().mag();
00194 
00195     setPosition(path.position(step));
00196     path.setArcLength(step);
00197 
00198     m_arcLength  += step;
00199     if( paverage ) {
00200         m_properTime += step * mass() / paverage;
00201         setT( t() + step * e() / paverage);
00202     }
00203 
00204     float rad_len = m_currentMedium->material().radiationLength();
00205     float x0;
00206     if(rad_len > 1.e8 || rad_len < 1.e-4) { x0 = 0.;}
00207     else                                  { x0 = step / rad_len;}
00208     m_radLength += x0; 
00209     m_stepList.push_back(Step(m_currentMedium, path.position(0), path.direction(), step, x0));
00210 }
00211 
00212 float RCParticle::mScat_Angle(float momentum, float s) const
00213 {// method to sum up the multiple scattering contributions to the track angle 
00214  // over a distance s (s must be less than maxArcLen) 
00215   
00216   float scat_angle = 0.;
00217   float dist = 0.;
00218   int num_step = m_stepList.size();
00219   for(int i=0; i<num_step; i++){
00220           float x0s =    m_stepList[i].rad_len();
00221           float s_dist = m_stepList[i].length();
00222           if(dist+s_dist > s) { // pro-rate the last step
00223                   if(s_dist > 0) x0s *= (s - dist)/s_dist;
00224           }
00225           if(x0s > 0) {
00226               float ms_Angle = .014*sqrt(x0s)*(1+0.038*log(x0s))/momentum; 
00227               scat_angle += ms_Angle*ms_Angle;
00228           }
00229           dist += s_dist;
00230           if(dist >= s ) break;
00231   }
00232   return sqrt(scat_angle);       
00233 }
00234 
00235 float RCParticle::mScat_Angle(float momentum, int step_no) const
00236 {// method to sum up the multiple scattering contributions to the track angle 
00237  // up to and including step #step_no   
00238   
00239   float scat_angle = 0.;
00240   int num_step = m_stepList.size();
00241   if(num_step > step_no) num_step = step_no;
00242   for(int i=0; i<num_step; i++){
00243           float x0s = m_stepList[i].rad_len();
00244           if(x0s > 0) {
00245               float ms_Angle = .014*sqrt(x0s)*(1+0.038*log(x0s))/momentum; 
00246               scat_angle += ms_Angle*ms_Angle;
00247           }
00248   }
00249   return sqrt(scat_angle);       
00250 }
00251 
00252 float RCParticle::mScat_Dist(float momentum, float s) const
00253 {// method to sum up the multiple scattering contributions to the track 
00254  // displacement over a distance s (s must be less than maxArcLen) 
00255   
00256   float scat_dist = 0.;
00257   float dist = 0.;
00258   int num_step = m_stepList.size();
00259   for(int i=0; i<num_step; i++){
00260           float x0s = m_stepList[i].rad_len();
00261           float s_dist =m_stepList[i].length();
00262           float s_distp = s_dist;
00263           if(dist+s_dist > s) { // pro-rate the last step: s_distp
00264                   if(s_dist > 0) x0s *= (s - dist)/s_dist;
00265                   s_distp = s - dist; 
00266           }
00267           if(x0s != 0) {
00268               float ms_Angle = .014*sqrt(x0s)*(1+0.038*log(x0s))/momentum;
00269               float ms_Dist = (s - dist - s_distp)*ms_Angle;  // Disp. over remaining traj
00270                   float ms_sDst = s_distp*ms_Angle/1.7320508;     // Disp. within step
00271               scat_dist += (ms_Dist*ms_Dist) + (ms_sDst)*(ms_sDst);
00272           }
00273           dist += s_dist;
00274           if(dist >= s ) break;
00275   }
00276   return sqrt(scat_dist);        
00277 }
00278 
00279 float RCParticle::mScat_Dist(float momentum, int step_no) const
00280 {// method to sum up the multiple scattering contributions to the track angle up to 
00281  // and including step #step_no  
00282   
00283   float scat_dist = 0.;
00284   float dist = 0.;
00285   int num_step = m_stepList.size();
00286   if(num_step > step_no) num_step = step_no;
00287   float total_dist = 0;
00288   for(int j=0; j<num_step; j++){ // find total lever arm
00289           total_dist += m_stepList[j].length();
00290   }
00291   for(int i=0; i<num_step; i++){
00292           float x0s = m_stepList[i].rad_len();
00293           float s_dist =m_stepList[i].length();
00294           if(x0s > 0) {
00295               float ms_Angle = .014*sqrt(x0s)*(1+0.038*log(x0s))/momentum;
00296               float ms_Dist = (total_dist - dist - s_dist)*ms_Angle; // Disp. over remaining traj
00297                   float ms_sDst = s_dist*ms_Angle/1.7320508;             // Disp within step
00298               scat_dist += (ms_Dist*ms_Dist) + (ms_sDst)*(ms_sDst);
00299           }
00300           dist += s_dist;
00301   }
00302   return sqrt(scat_dist);        
00303 }
00304 
00305 int RCParticle::findMedium(const char * name) const
00306 {// Returns the index of the Step with the given name.
00307  // Returns -1 if name not found
00308   
00309   int step_no = -1;
00310   int num_step = m_stepList.size();
00311   for(int i=0; i<num_step; i++){
00312           step_no++;
00313           if(strcmp(name, m_stepList[i].place()->title()) == 0) break;
00314   }
00315   return step_no;        
00316 }
00317 
00318 void
00319 RCParticle::printOn(std::ostream& str )const
00320 {
00321   GParticle::printOn(str);
00322   str << " status: ";
00323   switch( m_status ) {
00324      case ALIVE:      str << "alive";    break;
00325      case LEFT:       str << "left";     break;
00326      case LOST:       str << "lost";     break;
00327      case STUCK:      str << "stuck";    break;
00328          case DONE:       str << "done";     break;
00329      default:         str << "unknown";  break;
00330         }
00331   str <<'\n';
00332   str <<" Total Step length: "<<m_arcLength<<"  Proper Time: "<<m_properTime<<'\n';
00333   str <<" Step Count: "<<m_stepcount<<'\n';
00334 
00335   int num_step = m_stepList.size();
00336   for(int i=0; i<num_step; i++){
00337           m_stepList[i].printOn(str);
00338   }
00339 }
00340 
00341 // Class methods for internal classStep
00342 RCParticle::Step::Step(const Medium * med, Point x, Vector t, float s, float x0)
00343       :  m_region(med)
00344       ,  m_pos(x)
00345       ,  m_dir(t)
00346       ,  m_step_length(s)
00347       ,  m_rad_length(x0)
00348 {}
00349 
00350 void RCParticle::Step::printOn(std::ostream& str )const
00351 {
00352         str<<" Region: "<<m_region->title()<<" Location:"<<m_pos<<" Direction:"<<m_dir<<'\n';
00353         str<<"         Step Length:"<<m_step_length<<" Radiation Length: "<<m_rad_length<<'\n';
00354 }

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