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

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