00001
00002
00003
00004
00005
00006
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
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
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
00064
00065
00066 void RCParticle::propagate() {
00067
00068
00069 m_maxStep = m_maxArcLen+.0001;
00070 setStatus( ALIVE );
00071
00072 while (status()==ALIVE)
00073 {
00074 const Medium * nextMedium=m_currentMedium;
00075
00076
00077
00078 Ray *m_segment=
00079 m_currentMedium->CreateRay( position(), momentum(), charge(), m_maxStep );
00080
00081
00082 m_segment->setFlag(m_stepcount);
00083
00084
00085
00086 m_step = m_currentMedium->distanceToLeave(*m_segment, nextMedium, m_maxStep);
00087 if (m_step < m_maxStep) {
00088 setStatus( ALIVE );
00089
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
00105 m_step = m_maxStep;
00106 nextMedium = m_currentMedium;
00107 }
00108
00109
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
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
00130 m_maxStep = m_maxArcLen+.0001;
00131 setStatus( ALIVE );
00132
00133
00134 while (status()==ALIVE)
00135 {
00136 const Medium * nextMedium=m_currentMedium;
00137
00138
00139
00140 Ray *m_segment=
00141 m_currentMedium->CreateRay( position(), momentum(), charge(), m_maxStep );
00142
00143
00144 m_segment->setFlag(m_stepcount);
00145
00146
00147
00148
00149 m_step = m_currentMedium->distanceToLeave(*m_segment, nextMedium, 100.);
00150 if (m_step < m_maxStep) {
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
00160 m_step = m_maxStep;
00161 nextMedium = m_currentMedium;
00162 }
00163
00164
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
00174 if(strcmp(stop_med_title, m_currentMedium->title()) == 0 ) {
00175 setStatus(DONE);
00176 return true;
00177 }
00178
00179
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 {
00214
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) {
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 {
00237
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 {
00254
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) {
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;
00270 float ms_sDst = s_distp*ms_Angle/1.7320508;
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 {
00281
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++){
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;
00297 float ms_sDst = s_dist*ms_Angle/1.7320508;
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 {
00307
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
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 }