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

ScintPhoton.cxx

Go to the documentation of this file.
00001 
00002 // A class to track photons in the scintillator of the
00003 //MINOS far detector.  
00004 //
00006 #include <iostream>
00007 #include <TMath.h>
00008 #include <TRandom.h>
00009 
00010 #include "ScintPhoton.h"
00011 
00012 #include "Conventions/Munits.h"
00013 #include "UgliGeometry/UgliStripHandle.h"
00014 #include "MessageService/MsgService.h"
00015 
00016 CVSID( " $Id: ScintPhoton.cxx,v 1.8 2006/12/01 20:12:11 rhatcher Exp $" );
00017 
00018   // define the scintillator surfaces as follows
00019   //
00020   //                 I
00021   //        -------------------          ^ z
00022   //       |         O         |         |
00023   //    IV |          \        | II      |
00024   //       |           fiber   |         ---> y  
00025   //        -------------------     x out of page.
00026   //                III
00027   //
00028   // Surface V is positive end (towards us)
00029   // Surface VI is negative end (away from us)
00030   // Surface VII is the fibre cladding.
00031   //
00032   //coordinate system: (0,0,0) at center of strip
00033   //                    x-axis along long axis
00034   //                    z-axis up
00035   //                    y-axis to make right handed system
00036 
00037 ClassImp(ScintPhoton)
00038  
00039 // Static members.
00040 Double_t ScintPhoton::fsOuterCladdingIndex = 1.42;  //index of fraction of outer cladding
00041 Double_t ScintPhoton::fsInnerCladdingIndex = 1.49;  //index of fraction of outer cladding
00042 Double_t ScintPhoton::fsFibreIndex = 1.59;      //index of refraction of fiber
00043 Double_t ScintPhoton::fsFibreRadius = 0.6 * Munits::mm;  //radius of the WLS fiber (m)
00044 Double_t ScintPhoton::fsScintIndex = 1.6;      //index of refraction of fiber
00045 Double_t ScintPhoton::fsScintAttenLength = 0.33; // attenuation length in scintillator
00046 Double_t ScintPhoton::fsTiO2ReflecDiffuse  = 0.93; // <tuned> diffuse reflection coefficient of TiO2
00047 Double_t ScintPhoton::fsGrooveReflecCoeff = 0.5; // reflection coefficinet of the groove material
00048 Double_t ScintPhoton::fsGrooveHalfWidth = 0.7 * Munits::mm; // 
00049 Double_t ScintPhoton::fsReflectorScintReflec = 0.0; // Based upon guess from Leon
00050 Int_t    ScintPhoton::fsLambertianReflection = 1; // 1= lambert, 0= isotropic.
00051 
00052 const double kTooLong = 999. * Munits::meter; // "Fa, a long long way to run...."
00053                                               // (God help me, I can't believe I just put that in my comments.)
00054 
00055 //----------------------------------------------------------------------
00056 //default constructor 
00057 ScintPhoton::ScintPhoton() : 
00058   DigiPhoton(),
00059   fRandom(gRandom),
00060   fStart(0.,0.,0.),
00061   fStartT(0.),
00062   fStartV(0.,0.,1.),
00063   fHalfHeight(0.005),
00064   fHalfLength(4.00),
00065   fHalfWidth(0.02083),
00066   fHitSurface(0),
00067   fInFibre(false),
00068   fSpecularReflected(false),
00069   fDiffuseReflected(false),
00070   fAttenuated(false),
00071   fAbsorbed(false),
00072   fGeomError(false),
00073   fBounces(0),
00074   fTrackLength(0.),
00075   fNormal(0,0,0),
00076   fScintAttenLength(fsScintAttenLength),
00077   fTiO2ReflecDiffuse(fsTiO2ReflecDiffuse)
00078 {
00079 }
00080 
00081 //----------------------------------------------------------------------
00082 //real constructor
00083 ScintPhoton::ScintPhoton(TRandom* random,
00084                          const DigiScintHit* hit,
00085                          const UgliStripHandle& ush,
00086                          const TVector3& startPos, 
00087                          Double_t t,
00088                          const TVector3& startDir) : DigiPhoton()
00089 {
00090   Reset( random, hit, ush, startPos, t, startDir );
00091 }
00092 
00093 
00094 //----------------------------------------------------------------------
00095 //real constructor
00096 ScintPhoton::ScintPhoton(TRandom* random,
00097                          const DigiScintHit* hit,
00098                          const UgliStripHandle& ush,
00099                          const TVector3& startPos, Double_t t) : DigiPhoton()
00100 {
00101   TVector3 startDir(0,0,0);
00102   Reset( random, hit, ush, startPos, t, startDir );
00103 }
00104 
00105 
00106 //----------------------------------------------------------------------
00107 //real constructor
00108 ScintPhoton::ScintPhoton(TRandom* random,
00109                          const DigiScintHit* hit,
00110                          const UgliStripHandle& ush,
00111                          Double_t x, Double_t y, Double_t z, Double_t t,
00112                          Double_t u, Double_t v, Double_t w ) : DigiPhoton()
00113 {
00114   TVector3 startPos(x,y,z);
00115   TVector3 startDir(u,v,w);
00116   Reset( random, hit, ush, startPos, t, startDir );
00117 }
00118 
00119 
00120 
00121 
00122 //----------------------------------------------------------------------
00123 //Resetter.
00124 void ScintPhoton::Reset(TRandom* random,
00125                         const DigiScintHit* hit,
00126                         const UgliStripHandle& ush,
00127                         const TVector3& startPos, Double_t t,
00128                         const TVector3& startDir)
00129 {
00130   
00131   if(random) fRandom = random;
00132   else       fRandom = gRandom;
00133 
00134   SetParentHit(hit);
00135 
00136   fUgliStrip = ush;
00137   if(fUgliStrip.IsValid()) {
00138     fHalfHeight = fUgliStrip.GetHalfThickness();
00139     fHalfLength = fUgliStrip.GetHalfLength();
00140     fHalfWidth  = fUgliStrip.GetHalfWidth();
00141   } else {
00142     // Hardwired defaults, just in case.
00143     fHalfHeight=(0.005);
00144     fHalfLength=(4.00);
00145     fHalfWidth=(0.02083);
00146   }
00147 
00148   fHitSurface = 0;
00149   fInFibre = false;
00150   fSpecularReflected = false;
00151   fDiffuseReflected = false;
00152   fAttenuated = false;
00153   fAbsorbed = false; 
00154   fGeomError = false; 
00155   fBounces = 0;        // 
00156   fTrackLength = 0;
00157 
00158   fStart = startPos;
00159   fStartT = t;
00160 
00161   if(startDir.Mag2()==0) {
00162     // Roll a starting direction.
00163     double cosTheta = 1. - 2.*fRandom->Rndm();
00164     double sinTheta = TMath::Sin(TMath::ACos(cosTheta));
00165     double phi = 2.*TMath::Pi()*fRandom->Rndm();
00166     
00167     fStartV.SetXYZ( sinTheta*TMath::Cos(phi), 
00168                     sinTheta*TMath::Sin(phi),
00169                     cosTheta );
00170   } 
00171 
00172   // Set up the DigiPhoton.
00173   fPos =  fStart ;
00174   fDir =  fStartV;
00175   fT   =  fStartT;
00176 
00177   // Configuration.
00178   fScintAttenLength =fsScintAttenLength;
00179   fTiO2ReflecDiffuse =fsTiO2ReflecDiffuse;
00180 }
00181 
00182 
00183 
00184 //---------------------------------------------------------------------
00185 ScintPhoton::~ScintPhoton()
00186 {
00187 }
00188 
00189 void ScintPhoton::Configure( const Registry& r )
00190 {
00191   //
00192   // Override any defaults with external configuration parameters.
00193   //
00194   Double_t tmpd;
00195   if (r.Get("ScintIndex",tmpd))   fsScintIndex  = tmpd;
00196   if (r.Get("FibreIndex",tmpd))   fsFibreIndex  = tmpd;
00197   if (r.Get("OuterCladdingIndex",tmpd))       fsOuterCladdingIndex  = tmpd;
00198   if (r.Get("InnerCladdingIndex",tmpd))       fsInnerCladdingIndex  = tmpd;
00199   
00200   if (r.Get("FibreRadius",tmpd))          fsFibreRadius  = tmpd;
00201   if (r.Get("ScintAttenLength",tmpd))     fsScintAttenLength  = tmpd;
00202   if (r.Get("TiO2ReflecDiffuse",tmpd))   fsTiO2ReflecDiffuse   = tmpd;
00203   if (r.Get("GrooveReflecCoeff",tmpd))    fsGrooveReflecCoeff  = tmpd;
00204   if (r.Get("GrooveHalfWidth",tmpd))      fsGrooveHalfWidth  = tmpd;
00205   if (r.Get("ReflectorScintReflec",tmpd))      fsReflectorScintReflec  = tmpd;   
00206 
00207   Int_t tmpi;
00208   if (r.Get("LambertianReflection",tmpi))      fsLambertianReflection  = tmpi;   
00209 }
00210 
00211 
00212 
00213 Bool_t ScintPhoton::PropagateOneLeg()
00214 {
00215   // Propagate a ScintPhoton through the scintillator
00216   // to the next surface and evaluate if it survives.
00217 
00218   // Return true if everything is OK.
00219 
00220   fAttenuated = false;
00221   fSpecularReflected = false;
00222   fDiffuseReflected = false;
00223   fAttenuated = false;     // Caught in scintillator.
00224   fAbsorbed = false;       // Caught on wall.
00225   fGeomError = false;      // Too tricky for our stupid little code
00226 
00227 
00228   bool bounceOk = FindNextSurface(); // Propagate to next boundary.
00229   if(!bounceOk) {
00230     MSG("Photon",Msg::kWarning) << "Bounce failed." << endl;
00231     fGeomError = true;
00232     return false;
00233   }
00234     
00235   // See if the photon survived this leg.
00236   Attenuate();
00237   Move();
00238   
00239   if(fAttenuated) return true;
00240 
00241   // Interact with the surface.
00242   InteractAtSurface();
00243   
00244   // See if the photon made it to the scintillator
00245   if(fInFibre) return true;
00246   if(fAbsorbed) return true;
00247  
00248   // It got reflected, so compute the next bounce direction.
00249   if(fSpecularReflected || fDiffuseReflected) {
00250     FindReflectedDirection();
00251     return true;
00252   }
00253   
00254   return false;
00255 }
00256 
00257 
00258 Bool_t ScintPhoton::Propagate()
00259 {
00260   // Propagate a ScintPhoton through the scintillator
00261   // until it is absorbed, attenuated, or hits the fibre.
00262   // Return false if the photon fails for some reason: indication
00263   // that the caller should not count this trial.
00264 
00265   fBounces = 0;
00266   while(true) {
00267 
00268     PropagateOneLeg();
00269     if(fGeomError) return false;
00270     if(fAttenuated) return true;
00271     if(fAbsorbed) return true;
00272     if(fInFibre) return true;
00273 
00274     // We got bounced.
00275 
00276     fBounces++;
00277   }
00278   
00279   return false;
00280 }
00281 
00282 
00283 void ScintPhoton::Print(Option_t* ) const
00284 {
00285   cout << "ScintPhoton: (Units in cm)" << endl;
00286   cout << "  Started:  " << fStart.X() << "\t" << fStart.Y() << "\t" << fStart.Z() << endl;
00287   cout << "  StartDir: " << fStartV.X() << "\t" << fStartV.Y() << "\t" << fStartV.Z() << endl;
00288 
00289   cout << "  Pos:     " << X() << "\t" << Y() << "\t" << Z() << endl;
00290   cout << "  Dir After:  " << fDir.X() << "\t" << fDir.Y() << "\t" << fDir.Z() << endl;
00291   cout << "  Hit surface: " << fHitSurface << "\t Track length: " << fTrackLength << endl;
00292   if(fInFibre) cout << " In fibre. ";
00293   if(fSpecularReflected) cout << " SpecReflec. ";
00294   if(fDiffuseReflected) cout << " DiffuseReflec. ";
00295   if(fAttenuated) cout << " Attenuated. ";
00296   if(fAbsorbed) cout << " Absorbed. ";
00297   if(fGeomError) cout << " GeomError. ";
00298   cout << endl;
00299 }
00300 
00301 
00302 //---------------------------------------------------------------------
00303 Bool_t ScintPhoton::FindNextSurface()
00304 {
00305   //the photon cannot start off in the fiber or the groove as they dont
00306   //scintillate - for now let the groove be the same as the fiber - it 
00307   //basically is anyway.
00308   /*
00309     // let's ignore this.
00310     // it's a small correction... 
00311     // instead, we'll simply only allow incoming fibre hits, not outgoing
00312     // fibre hits.
00313   if((TMath::Power(fStartY,2.)
00314       +TMath::Power((fStartZ-(fHalfHeight-fsFibreRadius)),2.))<=TMath::Power(fsFibreRadius,2.)
00315      ){
00316     fInFibre = false;
00317     return false;
00318   }
00319   else if(TMath::Abs(fStartY)<=fsFibreRadius && fStartZ>=fHalfHeight-2.*fsFibreRadius){
00320     fInFibre = false;
00321     return false;
00322   }
00323   */
00324 
00325   //find which surface the photon would hit
00326   fTrackLength = kTooLong; // The distance to the nearest surface.
00327   fHitSurface = 0;
00328   double lengths[8];
00329   lengths[1] = DistanceToSurfaceI();
00330   lengths[2] = DistanceToSurfaceII();
00331   lengths[3] = DistanceToSurfaceIII();
00332   lengths[4] = DistanceToSurfaceIV();
00333   lengths[5] = DistanceToSurfaceV();
00334   lengths[6] = DistanceToSurfaceVI();
00335   lengths[7] = DistanceToFibre();
00336   
00337   for(int isurface = 1; isurface<=7; isurface++) {
00338     if( ( lengths[isurface] < fTrackLength ) && (lengths[isurface]>=0) ){
00339       fHitSurface = isurface;
00340       fTrackLength = lengths[isurface];
00341     }
00342   }
00343   
00344   if(fHitSurface == 0) {
00345     MSG("Photon",Msg::kWarning) << "Photon hit no surface!" << endl;
00346     fGeomError = true;
00347     return false;
00348   }
00349  
00350   return true;
00351 }
00352 
00353 
00355 Bool_t ScintPhoton::Attenuate()
00356 {
00357   // Compute if photon was absorbed on this leg.
00358 
00359   // Figure out how far we go before being absorbed.
00360   // Doing it this way has the nice property that we
00361   // actually know where it stopped.
00362   double distance = fRandom->Exp(fScintAttenLength);
00363 
00364   if(distance < fTrackLength) {
00365     // Photon didn't make it.
00366     fAttenuated = true;
00367     // compute how far the photon DID make it.
00368     fTrackLength = distance;
00369   }
00370 
00371   return fAttenuated;
00372 }
00373 
00374 
00376 Bool_t ScintPhoton::Move()
00377 {
00378   fPos += fDir*fTrackLength;
00379   fT += TimeOfFlight(fTrackLength);
00380   return true;
00381 }
00382 
00384 Double_t ScintPhoton::TimeOfFlight( Double_t distance )
00385 {
00386   // Time for a photon to travel a distance in scintillator.
00387   return distance * fsScintIndex / Munits::c_light;
00388 }
00389 
00390 
00392 Bool_t ScintPhoton::InteractAtSurface()
00393 {
00394   // 
00395   // Deals with whatever process happens at the surface.
00396   //
00397   // Sets the interaction flags and the surface normal.
00398   // Returns false if tracking error.
00399 
00400   fNormal.SetXYZ(0,0,0);
00401   
00402   // Fibre interaction:
00403 
00404   if(fHitSurface == 7) {
00405   // If the photon hit the fibre cladding, find out if it reflected or got absorbed.
00406     
00407     // The normal to the fibre surface is the norm of (y,z)-(fy,fz)
00408     // Surface normals at interaction point.
00409     fNormal.SetXYZ(0, 
00410                    Y(),  
00411                    Z()- (fHalfHeight-fsFibreRadius));
00412     fNormal.SetMag(1.0);
00413 
00414     // Dot product of direction vector and surface normal:
00415     double n_dot_v = fNormal.Dot(fDir);
00416 
00417     //the condition for reflection back into the scintillator is
00418     //if incident angle is > sin(n_2/n_1) where n_1 is the index of
00419     //refraction of the scintillator and n_2 is that for the fiber outer cladding
00420     //because the index for the inner cladding is greater than that for the outer
00421     //cladding, there can be no total reflection between outer and inner.
00422     
00423     // -ve sign because n points outwards.
00424   
00425     double incidentAngle = TMath::ACos(- n_dot_v);
00426     if(incidentAngle<TMath::ASin(fsOuterCladdingIndex/fsScintIndex)){
00427         
00428       //the photon made it into the fiber and that should be enough
00429       //for it to wavelength shift to a green photon - the mean free 
00430       //path of a photon in the fiber is of order microns and the 
00431       //WLS core of the fiber is 1.128 mm in diameter, or about 3 orders
00432       //of magnitude greater than the mean free path
00433       fInFibre = true;      
00434 
00435     } else {
00436       fSpecularReflected = true;      
00437     }
00438 
00439     return true;
00440   } // end surface == 7;
00441 
00442 
00443   // Was it a wall?
00444   if( ( fHitSurface >=1 ) && (fHitSurface <=4) ) {
00445     if( fHitSurface == 1 ) {
00446       // hit the top
00447       fNormal.SetXYZ(0,0,-1);
00448       
00449       // Check to see if it hit the groove.
00450       if( (TMath::Abs(Y()) < fsGrooveHalfWidth) ) { // In the groove. 
00451         if(fRandom->Rndm()>fsGrooveReflecCoeff)
00452           fSpecularReflected = true;
00453         else
00454           fAbsorbed = true;      
00455         return true;
00456       }
00457     } else if ( fHitSurface == 2 ) {
00458       fNormal.SetXYZ(0,-1,0);
00459     } else if ( fHitSurface == 3 ) {
00460       fNormal.SetXYZ(0,0,1);
00461     } else if ( fHitSurface == 4 ) {
00462       fNormal.SetXYZ(0,1,0);
00463     }
00464 
00465     // It hit TiO2 wall.
00466     double rand = fRandom->Rndm();
00467     if(rand < fTiO2ReflecDiffuse) {
00468       fDiffuseReflected = true;
00469     } else {
00470       fAbsorbed = true;
00471     }
00472 
00473     return true;
00474   }
00475 
00476   
00477   // Check to see if it hit an end.
00478   if( (fHitSurface == 5) || (fHitSurface == 6)) {
00479 
00480     // It hit the end. Was the end mirrored?
00481     //if( fHitSurface == 5 ):
00482     StripEnd::StripEnd_t end = StripEnd::kPositive;
00483     fNormal.SetXYZ(-1,0,0);   
00484 
00485     if( fHitSurface == 6 ) {
00486       fNormal.SetXYZ(1,0,0);
00487       end = StripEnd::kNegative;      
00488     }
00489 
00490     if( fUgliStrip.IsMirrored(end) ) {
00491       if(fRandom->Rndm()<=fsReflectorScintReflec) 
00492         fSpecularReflected = true;
00493       else 
00494         fAbsorbed = true;
00495     } else {
00496       fAbsorbed = true; // Flies off into the darkness of the pigtail.
00497     }
00498     
00499     return true;
00500   }
00501 
00502   MSG("Photon",Msg::kError) << "Error in InteractAtSurface: surface unrecognized." << endl;
00503   return false;
00504 }
00505 
00507 void ScintPhoton::FindReflectedDirection()
00508 {
00509   // New direction after a bounce.
00510   
00511   // FIXME: specular reflection only.
00512   double n_dot_v = fNormal.Dot(fDir);
00513   
00514   if(fSpecularReflected) {
00515     fDir = fDir - 2.0*n_dot_v*fNormal;
00516     return;
00517   } 
00518 
00519   if(fDiffuseReflected) {
00520     // Find a second vector, b, at right angles to the normal.
00521     // Cheat here: we know all normals are either along X or perp to X
00522     
00523     TVector3 a = fNormal.Orthogonal();
00524     TVector3 b = fNormal.Cross(a);
00525 
00526     double cosTheta;
00527     if(fsLambertianReflection==0) {
00528       cosTheta = fRandom->Rndm(); // 0 to 1
00529     } else {
00530       cosTheta = sqrt(fRandom->Rndm());
00531     }
00532     double phi = 2.*TMath::Pi()*fRandom->Rndm(); // 0 to 2pi
00533     double sinTheta = TMath::Sqrt(1.0-cosTheta*cosTheta);
00534     double sinPhi = TMath::Sin(phi);
00535     double cosPhi = TMath::Cos(phi);
00536     
00537     fDir = fNormal*cosTheta 
00538       + a*sinTheta*cosPhi 
00539       + b*sinTheta*sinPhi;
00540     if(fDir.Mag2()==0) {
00541       cout << "mag0: " << fNormal.X() << "\t" << fNormal.Y() << "\t" << fNormal.Z() << endl;
00542       cout << "mag0: " << a.x() << "\t" << a.y() << "\t" << a.z() << endl;
00543       cout << "mag0: " << b.x() << "\t" << b.y() << "\t" << b.z() << endl;
00544     }
00545   }
00546 }
00547 
00548 
00549 
00551 Double_t ScintPhoton::DistanceToSurfaceI()
00552 {
00553   // Find the distance from pos to surface I.
00554   // Return kTooLong if no interesection.
00555   if(fDir.Z()<=0) return kTooLong;
00556   double lambda = ( fHalfHeight - fPos.Z() )/fDir.Z();
00557   return lambda;
00558 }
00559 
00561 Double_t ScintPhoton::DistanceToSurfaceII()
00562 {
00563   // Find the distance from pos to surface II.
00564   // Return kTooLong if no interesection.
00565   if(fDir.Y()<=0) return kTooLong;
00566   double lambda = ( fHalfWidth - fPos.Y() )/fDir.Y();
00567   return lambda;
00568 }
00569 
00571 Double_t ScintPhoton::DistanceToSurfaceIII()
00572 {
00573   // Find the distance from pos to surface III.
00574   // Return kTooLong if no interesection.
00575   if(fDir.Z()>=0) return kTooLong;
00576   double lambda = ( -fHalfHeight - fPos.Z() )/fDir.Z();
00577   return lambda;
00578 }
00579 
00580 
00582 Double_t ScintPhoton::DistanceToSurfaceIV()
00583 {
00584   // Find the distance from pos to surface IV.
00585   // Return kTooLong if no interesection.
00586   if(fDir.Y()>=0) return kTooLong;
00587   double lambda = ( -fHalfWidth - fPos.Y() )/fDir.Y();
00588   return lambda;
00589 }
00590 
00592 
00593 Double_t ScintPhoton::DistanceToSurfaceV()
00594 {
00595   // Find the distance from pos to surface V.
00596   // Return kTooLong if no interesection.
00597   if(fDir.X() <= 0.) return kTooLong;
00598   double lambda = ( fHalfLength - fPos.X() )/fDir.X();
00599   return lambda;
00600 }
00601 
00603 Double_t ScintPhoton::DistanceToSurfaceVI()
00604 {
00605   // Find the distance from fPos to surface VI.
00606   // Return kTooLong if no interesection.
00607   if(fDir.X() >= 0.) return kTooLong;
00608   double lambda = ( -fHalfLength - fPos.X() )/fDir.X();
00609   return lambda;
00610 }
00611 
00612 
00614 Double_t ScintPhoton::DistanceToFibre()
00615 {
00616   // Find if the photon will intersect with the fibre,
00617   // and if so, where. Return kTooLong if it doesn't intersect.
00618 
00619   // the fibre position is (y=0, z=fHalfHeight-fsFibreRadius)
00620   double dy = fPos.Y();
00621   double dz = fPos.Z() - (fHalfHeight-fsFibreRadius);
00622 
00623   // Solve for : | (y,z) + lambda (vy,vz) - (0,h-r) |= r
00624   // where h is the height, and r is the radius.
00625   
00626   double v2  = (fDir.Y()*fDir.Y() + fDir.Z()*fDir.Z());
00627   if(v2==0) return kTooLong; // Going exactly in x-direction.
00628 
00629   double vdotdx = (fDir.Y() * dy) + (fDir.Z() * dz);
00630   double insqrt =  (vdotdx*vdotdx) - 
00631     (v2)*((dy*dy) + (dz*dz) - (fsFibreRadius*fsFibreRadius));
00632 
00633   // The track does not intersect the fibre ever.
00634   if(insqrt<0) return kTooLong;
00635 
00636   // the first solution is in the forward direction: take it.
00637   double soln1 = (-vdotdx - TMath::Sqrt(insqrt))/v2;             
00638   if(soln1>=0) return soln1;
00639   
00640   // only the first solution can be valid; the second solution
00641   // must apply only if we're already in the fibre.
00642 
00643   return kTooLong;
00644 }
00645 
00646 

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