Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

PhotonFullFibreModel.cxx

Go to the documentation of this file.
00001 #include "PhotonFullFibreModel.h"
00002 #include "PhotonTransportMaker.h"
00003 #include "PhotonUtil.h"
00004 #include "MessageService/MsgService.h"
00005 #include "Conventions/Munits.h"
00006 #include <cmath>
00007 
00008 CVSID( "$Id: PhotonFullFibreModel.cxx,v 1.10 2006/12/01 19:59:25 rhatcher Exp $" );
00009 
00010 ClassImp(PhotonFullFibreModel)
00011 
00012 PhotonTransportMakerProxy<PhotonFullFibreModel>
00013         gPhotonFullFibreModelProxy("photonFullFibreModel"); 
00014 
00016 // Constructor
00017 PhotonFullFibreModel::PhotonFullFibreModel() :
00018   fFibreAbsorbTable("PHOTONFIBREABSORB"),
00019   fGreenSpectrumTable("PHOTONGREENSPECTRUM")
00020 {
00021   Configure(PhotonConfiguration());
00022     
00023   if (fFibreAbsorbTable.GetNumRows()<1) {
00024     MSG("Photon",Msg::kError) << "Can't find data for table PHOTONFIBREABSORB. Aborting!\n";
00025     assert(0);
00026   }
00027   if (fGreenSpectrumTable.GetNumRows()<1) {
00028     MSG("Photon",Msg::kError) << "Can't find data for table PHOTONFIBREABSORB. Aborting!\n";
00029     assert(0);
00030   }
00031 }
00032 
00034 // Configure the model.
00035 void 
00036 PhotonFullFibreModel::Configure( const Registry& r )
00037 {
00038   MSG("Photon",Msg::kDebug) << "Configuring FullFibreModel." << std::endl;
00039   double tmpd;
00040   if (r.Get("FibreRadius",tmpd))          fFibreRadius  = tmpd;
00041   if (r.Get("FibreCoreRadius",tmpd))      fFibreCoreRadius  = tmpd;
00042   if (r.Get("InnerCladdingRadius",tmpd))  fInnerCladdingRadius  = tmpd;
00043 
00044   if (r.Get("FibreFlurorDecayTime",tmpd)) fFibreFlurorDecayTime  = tmpd;
00045 
00046   if (r.Get("FibreIndex",tmpd))           fFibreIndex  = tmpd;
00047   if (r.Get("ScintIndex",tmpd))           fScintIndex  = tmpd;
00048   if (r.Get("OuterCladdingIndex",tmpd))   fOuterCladdingIndex  = tmpd;
00049   if (r.Get("InnerCladdingIndex",tmpd))   fInnerCladdingIndex  = tmpd;
00050 
00051   SetWlsPrescaleFactor(1.0); // No prescaling.
00052 }
00053 
00054 void 
00055 PhotonFullFibreModel::Reset( const VldContext& cx )
00056 {
00057   // Ensure tables are up-to-date.
00058   fFibreAbsorbTable.Reset(cx);
00059   fGreenSpectrumTable.Reset(cx);
00060 }
00061 
00063 Int_t
00064 PhotonFullFibreModel:: FindBlueAbsorptionPosition( const UgliStripHandle& inStrip,
00065                                                    DigiPhoton*            inBluePhoton,
00066                                                    TVector3&              outPos)
00067 {
00068   // Track the blue photon until it gets absorbed.
00069   // Return -ve number for a condition that shouldn't happen 
00070   // Return 0 if photon stopped
00071   // Return +ve number if photon escaped
00072 
00073   // Reset the blue photon coordinates so they're centered on our fibre.
00074   TVector3 x = inBluePhoton->GetPos();
00075   
00076   x -= TVector3(0,0,
00077                 inStrip.GetHalfThickness() - fFibreRadius);
00078   fBlue_Start = fBlue_Stop = fBlue_OuterHit = fBlue_InnerHit = x;
00079   
00080   TVector3 v = inBluePhoton->GetDir();
00081   
00082   // Interact with the outer cladding.
00083   int interact  = PhotonUtil::InteractWithCylinder( x,v,
00084                                                     fFibreRadius,
00085                                                     fScintIndex,
00086                                                     fOuterCladdingIndex);
00087   if(interact!=0) { 
00088     // It reflected, not refracted. How did this happen?
00089     fBlue_OuterHit = x + v*0.0001;
00090     MSG("Photon",Msg::kWarning) << "Didn't refract into fibre. Huh? x=(" 
00091                                 << x.x() << " " << x.y() << " " << x.z() << ") "
00092                                 << "v=(" << v.x() << " " << v.y() << " "  << v.z() <<")\n";
00093                                 
00094     return -2;
00095   } 
00096   // Interact with the inner cladding
00097   int inclad1 = PhotonUtil::InteractWithCylinder( x,v,
00098                                                    fInnerCladdingRadius,
00099                                                    fOuterCladdingIndex,                 
00100                                                    fInnerCladdingIndex );
00101 
00102   fBlue_OuterHit = x;
00103   if(inclad1!=0) { return 1; } // It got out.
00104 
00105   // Intersect with the core:
00106   int incore = PhotonUtil::InteractWithCylinder( x, v,
00107                                                  fFibreCoreRadius,
00108                                                  fInnerCladdingIndex,
00109                                                  fFibreIndex );
00110   fBlue_InnerHit = x;
00111   // Missed the core or reflected off it. Shucks.
00112   if(incore!=0) { return 2; };
00113   
00114   // Photon hit the core. See how far it could go.
00115   double d1, d2;
00116   incore = PhotonUtil::IntersectCylinder( x, v, fFibreCoreRadius, d1, d2 );
00117   
00118   // This shouldn't happen.. we've already said it hit the core.
00119   if(!incore) { return -3;}
00120 
00121   // Find wavelength of blue photon in nm.
00122   double wavelength = inBluePhoton->WaveLength()/Munits::nm;
00123   if(wavelength<=0) wavelength = 420; // Something reasonable.
00124   
00125   // Find absorption length of this photon in nm.
00126   double atten = fFibreAbsorbTable.Interpolate(wavelength);
00127   
00128   // find where the photon got absorbed.
00129   double d = d1 + fRandom->Exp(atten);
00130 
00131   // Compute the final postion.
00132   outPos = x + v*d; 
00133   fBlue_Stop = outPos;;
00134   if(d>d2) { return 3; } // the blue photon managed to escape through the other side.
00135   
00136   return 0;
00137 }
00138 
00140 DigiPhoton*
00141 PhotonFullFibreModel::MakeGreenPhoton(   DigiPhoton*            inBluePhoton,
00142                                          const TVector3&        inPos,
00143                                          StripEnd::StripEnd_t   inDirection
00144                                          )
00145 {
00146   // Choose a direction.
00147   double cosTheta  = 2.*fRandom->Rndm()-1.0;
00148   double sinTheta = TMath::Sin(TMath::ACos(cosTheta));
00149   double phi = 2.*TMath::Pi()*fRandom->Rndm();
00150   TVector3 dir( cosTheta, 
00151                 sinTheta*TMath::Cos(phi),
00152                 sinTheta*TMath::Sin(phi) );
00153   
00154   // Let's ensure it's going in the correct direction:
00155   switch(inDirection) {
00156   case StripEnd::kPositive:
00157     dir.SetX(fabs(dir.X()));
00158     break;
00159     
00160   case StripEnd::kNegative:
00161     dir.SetX(-fabs(dir.X()));
00162     break;
00163     
00164   default:
00165     // Do nothing.
00166     break;    
00167   }
00168 
00169   // Choose wavelength.
00170   double wavelength = fGreenSpectrumTable.Pick(fRandom->Rndm())*Munits::nm;
00171   
00172   double time = inBluePhoton->T() + fRandom->Exp(fFibreFlurorDecayTime);
00173 
00174   DigiPhoton* green =  new DigiPhoton( inBluePhoton->ParentHit(),
00175                                        wavelength,
00176                                        time,
00177                                        inPos,
00178                                        dir
00179                                        );
00180   return green;
00181 }
00182 
00184 Bool_t 
00185 PhotonFullFibreModel::IsGreenTrapped( DigiPhoton* inGreen )
00186 {
00187   TVector3 x   = inGreen->GetPos();
00188   TVector3 dir = inGreen->GetDir();
00189 
00190   // Special cases:
00191   if(dir.x()==0) return false; // Going sideways.
00192   if(fabs(dir.x())>=1.) return true; // Going straight down the pipe.
00193 
00194   fGreen_Start = x;
00195 
00196   int interact;
00197   // Interact with the inner/outer cladding interface.
00198   interact = PhotonUtil::InteractWithCylinder( x,dir,
00199                                                fFibreCoreRadius,
00200                                                fFibreIndex,
00201                                                fInnerCladdingIndex);
00202   if(interact==-1) {
00203     MSG("Photon",Msg::kError) << "Didn't hit inner wall IsGreenTrapped(). Huh?!?" << endl;
00204   };
00205   fGreen_InnerHit = x;
00206   if(interact==1) {
00207     // It reflected off the inner surface. Bonus.
00208     fGreen_OuterHit = x;
00209     return true;
00210   }
00211 
00212 
00213   // Interact with the outer cladding/scint interface. 
00214   interact = PhotonUtil::InteractWithCylinder( x,dir,
00215                                                fInnerCladdingRadius,
00216                                                fInnerCladdingIndex,
00217                                                fOuterCladdingIndex);  
00218   if(interact==-1) {
00219     MSG("Photon",Msg::kError) << "Didn't hit outer wall IsGreenTrapped(). Huh?!?" << endl;
00220   };
00221   fGreen_OuterHit = x;
00222 
00223   if(interact==0) return false; // Refracted out.
00224   return true; // Reflected in.
00225 }
00226 
00228 Bool_t 
00229 PhotonFullFibreModel::FibreHitToGreenPhoton( const UgliStripHandle& inStrip,
00230                                              StripEnd::StripEnd_t   inDirection,
00231                                              DigiPhoton*            inBluePhoton,
00232                                              DigiPhoton*            &outGreenPhoton
00233                                              )
00234 {
00235   // Return a contained green photon.
00236   // This contains the full photon simulation.
00237   // Blue photons are tracked through the cladding and into the core
00238   // where they are absorbed by the correct attenuation.
00239   fLastResult = -1;
00240 
00241   outGreenPhoton = NULL;
00242   if(!inBluePhoton) { return false; };
00243 
00244   TVector3 flashPos;
00245   fLastResult = FindBlueAbsorptionPosition( inStrip,
00246                                             inBluePhoton,
00247                                             flashPos );
00248 
00249   if(fLastResult !=0 ) return false;
00250 
00251   // Loop until we have a valid solution.
00252 
00253   // Find the new direction of the green photon.
00254   // Go in the forward or backward direction, depending on the 
00255   // given parameter.
00256   
00257   if(outGreenPhoton) delete outGreenPhoton;
00258   outGreenPhoton = MakeGreenPhoton( inBluePhoton, 
00259                                     flashPos,
00260                                     inDirection);
00261 
00262   if(!outGreenPhoton) return false; // Huh?
00263 
00264   if(IsGreenTrapped(outGreenPhoton)) return true;
00265   
00266   // else:
00267   return false; // No trapped photon!
00268 }
00269 
00270 
00271 

Generated on Mon Feb 15 11:07:22 2010 for loon by  doxygen 1.3.9.1