src/BDSRK4Stepper.cc

00001 #include "BDSRK4Stepper.hh"
00002 #include "G4ThreeVector.hh"
00003 
00005 //
00006 // Constructor sets the number of variables (default = 6)
00007 
00008 extern G4double BDSLocalRadiusOfCurvature;
00009 
00010 BDSRK4Stepper::BDSRK4Stepper(G4EquationOfMotion* EqRhs, G4int nvar) :
00011   G4MagIntegratorStepper(EqRhs,nvar)
00012 {
00013   itsEqRhs = EqRhs;
00014   
00015   unsigned int noVariables= std::max(nvar,8); // For Time .. 7+1
00016  
00017   dydxm = new G4double[noVariables];
00018   dydxt = new G4double[noVariables]; 
00019   yt    = new G4double[noVariables]; 
00020 
00021   yTemp = new G4double[noVariables];
00022   yIn = new G4double[noVariables];
00023 }
00024 
00026 //
00027 // Destructor
00028 
00029 BDSRK4Stepper::~BDSRK4Stepper()
00030 {
00031   delete[] dydxm;
00032   delete[] dydxt;
00033   delete[] yt;
00034 
00035   delete[] yTemp;
00036   delete[] yIn;
00037 }
00038 
00040 //
00041 // Given values for the variables y[0,..,n-1] and their derivatives
00042 // dydx[0,...,n-1] known at x, use the classical 4th Runge-Kutta
00043 // method to advance the solution over an interval h and return the
00044 // incremented variables as yout[0,...,n-1], which not be a distinct
00045 // array from y. The user supplies the routine RightHandSide(x,y,dydx),
00046 // which returns derivatives dydx at x. The source is routine rk4 from
00047 // NRC p. 712-713 .
00048 
00049 void
00050 BDSRK4Stepper::AdvanceHelix( const G4double  yIn[],
00051                              const G4double dydx[],
00052                              const  G4double  h,
00053                              G4double  yOut[])
00054 {
00055 
00056 #ifdef DEBUG
00057   G4cout<<"stepping by "<<h<<G4endl;
00058 #endif
00059 
00060   const G4int nvar = this->GetNumberOfVariables();   //  fNumberOfVariables(); 
00061 
00062 #ifdef DEBUG
00063   G4cout<<"nvar="<<nvar<<G4endl;
00064 #endif
00065 
00066   G4int i;
00067   G4double  hh = h*0.5 , h6 = h/6.0  ;
00068 
00069   // Initialise time to t0, needed when it is not updated by the integration.
00070   //        [ Note: Only for time dependent fields (usually electric) 
00071   //                  is it neccessary to integrate the time.] 
00072   yt[7]   = yIn[7]; 
00073   yOut[7] = yIn[7];
00074 
00075   // Have to calculate total Energy assuming Mass = zero
00076   // because have no way to see particle type here (and hence no mass info)
00077   const G4double *pIn = yIn+3;
00078   G4double itsMomentum = sqrt(pIn[0]*pIn[0]+pIn[1]*pIn[1]+pIn[2]*pIn[2]);
00079   
00080   G4double BField[6];
00081   G4double Pos[4];
00082   Pos[0] = yIn[0];
00083   Pos[1] = yIn[1];
00084   Pos[2] = yIn[2];
00085   Pos[3] = 0.;
00086   itsEqRhs->GetFieldObj()->GetFieldValue(Pos,BField);
00087 
00088   G4ThreeVector BVec = G4ThreeVector(BField[0],
00089                                      BField[1],
00090                                      BField[2]);
00091   G4ThreeVector pVec = G4ThreeVector(pIn[0],
00092                                      pIn[1],
00093                                      pIn[2]);
00094 
00095   G4double Bmag = (BVec.cross(pVec.unit())).mag();
00096   
00097   BDSLocalRadiusOfCurvature = (itsMomentum/GeV) / (0.299792458*Bmag/tesla)*m;
00098 
00099 #ifdef DEBUG 
00100   G4cout<<" Pos = ("<<Pos[0]/mm<<" "<<Pos[1]/mm<<" " <<Pos[2]/mm<<") mm"<<G4endl;
00101   G4cout<<" Mtm = ("<<pIn[0]/GeV<<" "<<pIn[1]/GeV<<" " <<pIn[2]/GeV<<") GeV"<<G4endl;
00102   G4cout<<" BField = ("<<BField[0]/tesla<<" "<<BField[1]/tesla<<" "<<BField[2]/tesla<<") T"<<G4endl;
00103   G4cout<<" Local curvature radius = "<<BDSLocalRadiusOfCurvature/m<<" m"<<G4endl;
00104 #endif
00105 
00106 
00107   //
00108   // Now do the stepping
00109   //
00110 #ifdef DEBUG 
00111   G4cout<<"===>RK Steps 1-2,  before, dydx : ";
00112   for(i=0;i<nvar;i++) { 
00113     G4cout<<dydx[i]<<" ";
00114   }  
00115   G4cout<<G4endl;
00116 
00117   G4cout<<"yIn: ";
00118   for(i=0;i<nvar;i++) { 
00119     G4cout<<yIn[i]<<" ";
00120   }  
00121   G4cout<<G4endl;
00122 #endif
00123 
00124   for(i=0;i<nvar;i++)
00125     {
00126     yt[i] = yIn[i] + hh*dydx[i] ;             // 1st Step K1=h*dydx
00127   }
00128   RightHandSide(yt,dydxt) ;                   // 2nd Step K2=h*dydxt
00129 
00130 #ifdef DEBUG 
00131   G4cout<<"after, dydx: ";
00132   for(i=0;i<nvar;i++) { 
00133     G4cout<<dydxt[i]<<" ";
00134   }  
00135   G4cout<<G4endl;
00136   
00137   G4cout<<"after, yt: ";
00138   for(i=0;i<nvar;i++) { 
00139     G4cout<<yt[i]<<" ";
00140   }  
00141   G4cout<<G4endl;
00142 #endif
00143 
00144 #ifdef DEBUG 
00145   G4cout<<"===>RK Steps 3-4"<<G4endl;
00146 #endif
00147 
00148   for(i=0;i<nvar;i++)
00149   { 
00150     yt[i] = yIn[i] + hh*dydxt[i] ;
00151   }
00152   RightHandSide(yt,dydxm) ;                   // 3rd Step K3=h*dydxm
00153 
00154   for(i=0;i<nvar;i++)
00155   {
00156     yt[i]   = yIn[i] + h*dydxm[i] ;
00157     dydxm[i] += dydxt[i] ;                    // now dydxm=(K2+K3)/h
00158   }
00159   RightHandSide(yt,dydxt) ;                   // 4th Step K4=h*dydxt
00160  
00161   for(i=0;i<nvar;i++)    // Final RK4 output
00162   {
00163     yOut[i] = yIn[i]+h6*(dydx[i]+dydxt[i]+2.0*dydxm[i]); //+K1/6+K4/6+(K2+K3)/3
00164   }
00165   // NormaliseTangentVector( yOut );
00166 
00167  //  G4cout<<"out : ";
00168 
00169 //   for(i=0;i<nvar;i++) { 
00170 //      G4cout<<yOut[i]<<" ";
00171 //   }  
00172 
00173 //   G4cout<<G4endl;
00174 
00175 
00176 //  itsDist = 0;
00177   
00178   return;
00179 
00180 }  // end of DumbStepper ....................................................
00181 
00182 
00183 void BDSRK4Stepper::Stepper( const G4double yInput[],
00184                              const G4double dydx[],
00185                              const G4double hstep,
00186                              G4double yOut[],
00187                              G4double yErr[]      )
00188 {  
00189   const G4int nvar = 6 ;
00190   G4int i;
00191   const G4double *pIn = yInput+3;
00192   G4ThreeVector v0= G4ThreeVector( pIn[0], pIn[1], pIn[2]);  
00193   //G4double InitMag=v0.mag();
00194   
00195   //  Saving yInput because yInput and yOut can reference the same array
00196   
00197   for(i=0;i<nvar;i++) yIn[i]=yInput[i];
00198   
00199 
00200   // G4cout<<"Input: ";
00201   
00202 //   for(i=0;i<nvar;i++) { 
00203 //     G4cout<<yIn[i]<<" ";
00204 //   }  
00205 //   G4cout<<G4endl;
00206 
00207 //   G4cout<<"dydx: ";
00208   
00209 //   for(i=0;i<nvar;i++) { 
00210 //     G4cout<<dydx[i]<<" ";
00211 //   }  
00212 //   G4cout<<G4endl;
00213   
00214 
00215   G4double h = hstep; 
00216   //if(h>itsVolLength) h = itsVolLength;
00217   // Do two half steps
00218   
00219   AdvanceHelix(yIn,   dydx,  h, yOut);
00220  
00221   //G4cout<<"Full step: ";
00222   
00223 //   for(i=0;i<nvar;i++) { 
00224 //     G4cout<<yOut[i]<<" ";
00225 //   }  
00226 //   G4cout<<G4endl;
00227   
00228 
00229   //G4cout<<"Err: ";
00230 
00231   for(i=0;i<nvar;i++) { 
00232     yErr[i] = h*h*h*(yOut[i] - yIn[i]) ;
00233     //G4cout<<yErr[i]<<" ";
00234   }
00235   
00236   //G4cout<<G4endl;
00237 
00238 }
00239 
00240 G4double BDSRK4Stepper::DistChord()   const 
00241 {
00242   //  return itsDist;
00243   return 0.0;
00244 }

Generated on 27 Aug 2013 for BDSIM by  doxygen 1.4.7