/home/cern/BDSIM_new/src/BDSSolenoidStepper.cc

00001 //  
00002 //   BDSIM, (C) 2001-2007
00003 //   
00004 //   version 0.4
00005 //  
00006 //
00007 //
00008 //   Stepper for Solenoid magnetic field
00009 //
00010 //
00011 //   History
00012 //
00013 //     21 Oct 2007 by Marchiori,  v.0.4
00014 //
00015 //
00016 
00017 #include "BDSGlobalConstants.hh" 
00018 #include "BDSSolenoidStepper.hh"
00019 #include "G4ThreeVector.hh"
00020 #include "G4TransportationManager.hh"
00021 
00022 using std::max;
00023 extern G4double BDSLocalRadiusOfCurvature;
00024 extern G4int event_number;
00025 
00026 const int DEBUG = 0;
00027 
00028 BDSSolenoidStepper::BDSSolenoidStepper(G4Mag_EqRhs *EqRhs)
00029   : G4MagIntegratorStepper(EqRhs,6)  // integrate over 6 variables only !!
00030                                      // position & velocity
00031 {
00032   fPtrMagEqOfMot = EqRhs;
00033 }
00034 
00035 void BDSSolenoidStepper::AdvanceHelix( const G4double  yIn[],
00036                                        G4ThreeVector Bfld,
00037                                        G4double  h,
00038                                        G4double  yOut[])
00039 {
00040   //
00041   // Compute charge of particle (FCof = particleCharge*eplus*c_light)
00042   //
00043   G4double charge = (fPtrMagEqOfMot->FCof())/c_light;
00044 
00045   
00046   //
00047   // Get B field
00048   //
00049   G4double Bz;
00050   if(BDSGlobals->GetSynchRescale())
00051     {
00052       G4double B[3];
00053       fPtrMagEqOfMot->GetFieldValue(yIn, B);
00054       Bz = B[2];
00055     }
00056   else
00057     Bz = itsBField;
00058 
00059 
00060   if (DEBUG) G4cout << "BDSSolenoidStepper: step= " << h/m << " m" << G4endl;
00061   if (DEBUG) G4cout << "BDSSolenoidStepper: initial point in global coordinates:" << G4endl
00062                     << " x= " << yIn[0]/m << "m" << G4endl
00063                     << " y= " << yIn[1]/m << "m" << G4endl
00064                     << " z= " << yIn[2]/m << "m" << G4endl
00065                     << " px= " << yIn[3]/GeV << "GeV/c" << G4endl
00066                     << " py= " << yIn[4]/GeV << "GeV/c" << G4endl
00067                     << " pz= " << yIn[5]/GeV << "GeV/c" << G4endl
00068                     << " q= " << charge/eplus << "e" << G4endl
00069                     << " B= " << Bz/tesla << "T" << G4endl
00070                     << G4endl; 
00071 
00072 
00073   //
00074   // compute initial R, P, R' in global coordinates
00075   //
00076   const G4double *pIn = yIn+3;
00077   G4ThreeVector GlobalR = G4ThreeVector( yIn[0], yIn[1], yIn[2]);  
00078   G4ThreeVector GlobalP = G4ThreeVector( pIn[0], pIn[1], pIn[2]);  
00079   G4ThreeVector GlobalRp = GlobalP.unit();
00080   G4double InitPMag = GlobalP.mag();
00081 
00082 
00083   //
00084   // transform global to local coordinates
00085   //
00086   G4Navigator* HelixNavigator=
00087     G4TransportationManager::GetTransportationManager()->
00088     GetNavigatorForTracking();
00089   
00090   G4AffineTransform GlobalAffine = HelixNavigator->GetGlobalToLocalTransform();
00091   G4ThreeVector LocalR = GlobalAffine.TransformPoint(GlobalR); 
00092   G4ThreeVector LocalRp = GlobalAffine.TransformAxis(GlobalRp);
00093 
00094   if (DEBUG) G4cout << "BDSSolenoidStepper: initial point in local coordinates:" << G4endl
00095                     << " x= " << LocalR[0]/m << "m" << G4endl
00096                     << " y= " << LocalR[1]/m << "m" << G4endl
00097                     << " z= " << LocalR[2]/m << "m" << G4endl
00098                     << " x'= " << LocalRp[0] << G4endl
00099                     << " y'= " << LocalRp[1] << G4endl
00100                     << " z'= " << LocalRp[2] << G4endl
00101                     << G4endl; 
00102 
00103 
00104   //
00105   // compute radius of helix
00106   //
00107   G4double R;
00108   if (Bz!=0)
00109     R = -(InitPMag*LocalRp.perp()/GeV)/(0.299792458 * Bz/tesla) * m;
00110   else
00111     R=DBL_MAX;
00112 
00113   // include the sign of the charge of the particles
00114   // FCof = particleCharge*eplus*c_light
00115   if( charge<0 ) R*=-1.;
00116   else if ( charge==0 ) R=DBL_MAX;
00117 
00118   // Save for Synchrotron Radiation calculations:
00119   BDSLocalRadiusOfCurvature=R;
00120 
00121   // check that the approximations are valid, else do a linear step
00122   G4ThreeVector itsFinalR, itsFinalRp;
00123   if(fabs(R)<DBL_MAX)
00124     {
00125 
00126       //
00127       // compute pitch of helix
00128       //
00129       G4double pitch;
00130       pitch = fabs(2*pi*R*LocalRp[2]/LocalRp.perp());
00131 
00132       //
00133       // compute center of helix
00134       //
00135       G4ThreeVector Bhat(0.,0.,Bz/fabs(Bz));
00136       G4ThreeVector vhat=LocalRp;
00137       G4ThreeVector Rhat=(charge*vhat.cross(Bhat)).unit();
00138       G4ThreeVector center=LocalR+fabs(R)*Rhat; //occhio che anche R ha il segno!
00139       //
00140       // compute step length in z and theta (h is the helix arc length)
00141       //
00142       G4double dz = h / sqrt(1. + pow(2.*pi*R/pitch,2));
00143       G4double dtheta = 2*pi*dz/pitch*R/fabs(R);
00144       
00145       if (DEBUG) G4cout << "Parameters of helix: " << G4endl
00146                         << " R= " << R/m << " m" << G4endl
00147                         << " pitch= " << pitch/m << " m" <<G4endl
00148                         << " center= " << center/m << " m"<<G4endl
00149                         << " step length= " << h/m << " m"<<G4endl
00150                         << " step dz= " << dz/m << " m"<<G4endl
00151                         << " step dtheta= " << dtheta/radian << " rad"<<G4endl;
00152 
00153 
00154       //
00155       // advance the orbit (in local coordinates)
00156       // h is the helix length
00157       //
00158       G4ThreeVector itsInitialR = LocalR;
00159       G4ThreeVector itsInitialRp = LocalRp;
00160       
00161       //G4double CosT = cos(dtheta);
00162       //G4double SinT = sin(dtheta);  
00163       //G4RotationMatrix r;
00164       //r.rotateZ(dtheta);
00165       
00166       itsFinalRp = itsInitialRp.rotateZ(dtheta);
00167       itsFinalR = 
00168         center + (itsInitialR-center).rotateZ(dtheta) + G4ThreeVector(0,0,dz);
00169 
00170 
00171       //
00172       // compute max distance between chord from yIn to yOut and helix
00173       //
00174       G4double Ang = fabs(dtheta);
00175       if(Ang<=pi){
00176         itsDist = fabs(R)*(1 - cos(0.5*Ang));
00177       } else
00178         if(Ang<twopi){
00179           itsDist = fabs(R)*(1 + cos(pi-0.5*Ang));
00180         } else
00181           itsDist = 2*fabs(R);
00182     }      
00183   else
00184     {
00185       itsFinalR = LocalR + h * LocalRp;
00186       itsFinalRp = LocalRp;
00187       itsDist=0.;
00188     }
00189   
00190   if (DEBUG) G4cout << "BDSSolenoidStepper: final point in local coordinates:" << G4endl
00191                     << " x= " << itsFinalR[0]/m << "m" << G4endl
00192                     << " y= " << itsFinalR[1]/m << "m" << G4endl
00193                     << " z= " << itsFinalR[2]/m << "m" << G4endl
00194                     << " x'= " << itsFinalRp[0] << G4endl
00195                     << " y'= " << itsFinalRp[1] << G4endl
00196                     << " z'= " << itsFinalRp[2] << G4endl
00197                     << G4endl; 
00198 
00199 
00200   //
00201   // transform local to global coordinates
00202   //
00203   G4AffineTransform LocalAffine = HelixNavigator->GetLocalToGlobalTransform();
00204   GlobalR = LocalAffine.TransformPoint(itsFinalR); 
00205   GlobalRp = LocalAffine.TransformAxis(itsFinalRp);
00206   GlobalP = InitPMag*GlobalRp;
00207 
00208   yOut[0] = GlobalR.x(); 
00209   yOut[1] = GlobalR.y(); 
00210   yOut[2] = GlobalR.z(); 
00211   
00212   yOut[3] = GlobalP.x();
00213   yOut[4] = GlobalP.y();
00214   yOut[5] = GlobalP.z();
00215 
00216   if (DEBUG) G4cout << "BDSSolenoidStepper: final point in global coordinates:" << G4endl
00217                     << " x= " << yOut[0]/m << "m" << G4endl
00218                     << " y= " << yOut[1]/m << "m" << G4endl
00219                     << " z= " << yOut[2]/m << "m" << G4endl
00220                     << " px= " << yOut[3]/GeV << "GeV/c" << G4endl
00221                     << " py= " << yOut[4]/GeV << "GeV/c" << G4endl
00222                     << " pz= " << yOut[5]/GeV << "GeV/c" << G4endl
00223                     << G4endl; 
00224 }    
00225 
00226 
00227 void BDSSolenoidStepper::Stepper( const G4double yInput[],
00228                                   const G4double dydx[],
00229                                   const G4double hstep,
00230                                   G4double yOut[],
00231                                   G4double yErr[]      )
00232 {  
00233   const G4int nvar = 6 ;
00234 
00235   for(G4int i=0;i<nvar;i++) yErr[i]=0;
00236   AdvanceHelix(yInput,0,hstep,yOut);
00237   return ;
00238 }
00239 
00240 G4double BDSSolenoidStepper::DistChord()   const 
00241 {
00242 
00243   return itsDist;
00244   // This is a class method that gives distance of Mid 
00245   //  from the Chord between the Initial and Final points.
00246 }
00247 
00248 BDSSolenoidStepper::~BDSSolenoidStepper()
00249 {}

Generated on Wed Mar 5 17:25:23 2008 for BDSIM by  doxygen 1.5.3