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

Generated on 27 Aug 2013 for BDSIM by  doxygen 1.4.7