/scratch0/jsnuveri/BDSIM/BDSIMgit/bdsim/src/BDSQuadStepper.cc

00001 #include "BDSQuadStepper.hh"
00002 #include "G4ThreeVector.hh"
00003 #include "G4TransportationManager.hh"
00004 #include "G4Navigator.hh"
00005 #include "G4AffineTransform.hh"
00006 
00007 using std::max;
00008 extern G4double BDSLocalRadiusOfCurvature;
00009 
00010 BDSQuadStepper::BDSQuadStepper(G4Mag_EqRhs *EqRhs)
00011   : G4MagIntegratorStepper(EqRhs,6),  // integrate over 6 variables only !!
00012                                       // position & velocity
00013     itsBGrad(0.0),itsDist(0.0)
00014 {
00015   fPtrMagEqOfMot = EqRhs;
00016   QuadNavigator=new G4Navigator();
00017 }
00018 
00019 
00020 void BDSQuadStepper::AdvanceHelix( const G4double  yIn[],
00021                                    G4ThreeVector,
00022                                    G4double  h,
00023                                    G4double  yQuad[])
00024 {
00025   const G4double *pIn = yIn+3;
00026   G4ThreeVector GlobalR = G4ThreeVector( yIn[0], yIn[1], yIn[2]);
00027   G4ThreeVector GlobalP = G4ThreeVector( pIn[0], pIn[1], pIn[2]);
00028   G4ThreeVector InitMomDir = GlobalP.unit();
00029   G4double InitPMag = GlobalP.mag();
00030   // quad strength k
00031   G4double kappa = - fPtrMagEqOfMot->FCof()*itsBGrad/InitPMag;
00032 
00033 #ifdef BDSDEBUG
00034   G4double charge = (fPtrMagEqOfMot->FCof())/CLHEP::c_light;
00035   G4cout << "BDSQuadStepper: step = " << h/CLHEP::m << " m" << G4endl
00036          << " x  = " << yIn[0]/CLHEP::m     << " m"     << G4endl
00037          << " y  = " << yIn[1]/CLHEP::m     << " m"     << G4endl
00038          << " z  = " << yIn[2]/CLHEP::m     << " m"     << G4endl
00039          << " px = " << yIn[3]/CLHEP::GeV   << " GeV/c" << G4endl
00040          << " py = " << yIn[4]/CLHEP::GeV   << " GeV/c" << G4endl
00041          << " pz = " << yIn[5]/CLHEP::GeV   << " GeV/c" << G4endl
00042          << " q  = " << charge/CLHEP::eplus << " e"     << G4endl
00043          << " dBy/dx = " << itsBGrad/(CLHEP::tesla/CLHEP::m) << " T/m" << G4endl
00044          << " k = " << kappa/(1./CLHEP::m2) << " m^-2" << G4endl
00045          << G4endl; 
00046 #endif
00047 
00048   G4double h2=h*h;
00049 
00050   QuadNavigator->SetWorldVolume(G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume()); 
00051   QuadNavigator->LocateGlobalPointAndSetup(GlobalR);
00052 
00053   // relevant momentum scale is p_z, not P_tot:
00054   // check that the approximations are valid, else do a linear step:
00055   if(fabs(kappa)<1.e-12)
00056     {
00057       G4ThreeVector positionMove = h * InitMomDir;
00058 
00059       yQuad[0] = yIn[0] + positionMove.x(); 
00060       yQuad[1] = yIn[1] + positionMove.y(); 
00061       yQuad[2] = yIn[2] + positionMove.z(); 
00062                                 
00063       yQuad[3] = GlobalP.x();
00064       yQuad[4] = GlobalP.y();
00065       yQuad[5] = GlobalP.z();
00066 
00067       itsDist=0;
00068       return;
00069     }
00070     
00071   h2=h*h;
00072 
00073   G4AffineTransform GlobalAffine=QuadNavigator->
00074     GetGlobalToLocalTransform();
00075 
00076   G4ThreeVector LocalR=GlobalAffine.TransformPoint(GlobalR); 
00077   G4ThreeVector LocalRp=GlobalAffine.TransformAxis(InitMomDir);
00078 
00079 #ifdef BDSDEBUG
00080   G4cout << "BDSQuadStepper: initial point in local coordinates:" << G4endl
00081          << " x= " << LocalR[0]/CLHEP::m << "m" << G4endl
00082          << " y= " << LocalR[1]/CLHEP::m << "m" << G4endl
00083          << " z= " << LocalR[2]/CLHEP::m << "m" << G4endl
00084          << " x'= " << LocalRp[0] << G4endl
00085          << " y'= " << LocalRp[1] << G4endl
00086          << " z'= " << LocalRp[2] << G4endl
00087          << G4endl; 
00088 #endif
00089 
00090   G4double x0,xp,y0,yp,z0,zp;
00091   G4double x1,x1p,y1,y1p,z1,z1p;
00092   x0=LocalR.x();
00093   y0=LocalR.y();
00094   z0=LocalR.z();
00095   xp=LocalRp.x();
00096   yp=LocalRp.y();
00097   zp=LocalRp.z();
00098 
00099   // local r'' (for curvature)
00100   G4ThreeVector LocalRpp;
00101   LocalRpp.setX(-zp*x0);
00102   LocalRpp.setY( zp*y0);
00103   LocalRpp.setZ( x0*xp - y0*yp);
00104 
00105   LocalRpp*=kappa;
00106 
00107   // determine effective curvature 
00108   G4double R_1 = LocalRpp.mag();
00109 #ifdef BDSDEBUG 
00110   G4cout << " curvature= " << R_1*CLHEP::m << "m^-1" << G4endl;
00111 #endif
00112   if(R_1>0.)
00113     {
00114       G4double R=1./R_1;
00115 
00116       // Save for Synchrotron Radiation calculations:
00117       BDSLocalRadiusOfCurvature=R;
00118 
00119       // chord distance (simple quadratic approx)
00120       itsDist= h2/(8*R);
00121 
00122       // check for paraxial approximation:
00123       if(fabs(zp)>0.9)//&&(fabs(kappa)<1.e-6))
00124         {
00125 #ifdef BDSDEBUG
00126           G4cout << "paraxial approximation being used" << G4endl;
00127 #endif
00128           G4double rootK=sqrt(fabs(kappa*zp));
00129           G4double rootKh=rootK*h*zp;
00130           G4double X11,X12,X21,X22;
00131           G4double Y11,Y12,Y21,Y22;
00132 
00133           if (kappa>0)
00134             {
00135               X11= cos(rootKh);
00136               X12= sin(rootKh)/rootK;
00137               X21=-fabs(kappa)*X12;
00138               X22= X11;
00139                   
00140               Y11= cosh(rootKh);
00141               Y12= sinh(rootKh)/rootK;
00142               Y21= fabs(kappa)*Y12;
00143               Y22= Y11;
00144             }
00145           else //if (kappa<0)
00146             {
00147               X11= cosh(rootKh);
00148               X12= sinh(rootKh)/rootK;
00149               X21= fabs(kappa)*X12;
00150               X22= X11;
00151                   
00152               Y11= cos(rootKh);
00153               Y12= sin(rootKh)/rootK;
00154               Y21= -fabs(kappa)*Y12;
00155               Y22= Y11;
00156             }
00157 
00158           x1 = X11*x0 + X12*xp;    
00159           x1p= X21*x0 + X22*xp;
00160               
00161           y1 = Y11*y0 + Y12*yp;    
00162           y1p= Y21*y0 + Y22*yp;
00163               
00164           z1p=sqrt(1 - x1p*x1p -y1p*y1p);
00165 
00166           G4double dx=x1-x0;
00167           G4double dy=y1-y0;
00168 
00169           // Linear chord length
00170           G4double dR2=dx*dx+dy*dy;
00171           G4double dz=sqrt(h2*(1.-h2/(12*R*R))-dR2);
00172               
00173           // check for precision problems
00174           G4double ScaleFac=(dx*dx+dy*dy+dz*dz)/h2;
00175           if(ScaleFac>1.0000001)
00176             {
00177               ScaleFac=sqrt(ScaleFac);
00178               dx/=ScaleFac;
00179               dy/=ScaleFac;
00180               dz/=ScaleFac;
00181               x1=x0+dx;
00182               y1=y0+dy;
00183             }
00184           z1=z0+dz;
00185         }
00186       else
00187         // perform local helical steps (paraxial approx not safe)
00188         {
00189 #ifdef BDSDEBUG
00190           G4cout << "local helical steps" << G4endl;
00191 #endif
00192           // simple quadratic approx:         
00193           G4double quadX= - kappa*x0*zp;
00194           G4double quadY=   kappa*y0*zp;
00195           G4double quadZ=   kappa*(x0*xp - y0*yp);
00196               
00197           // determine maximum curvature:
00198           G4double maxCurv=max(fabs(quadX),fabs(quadY));
00199           maxCurv=max(maxCurv,fabs(quadZ));
00200               
00201           x1 = x0 + h*xp + quadX*h2/2;
00202           y1 = y0 + h*yp + quadY*h2/2; 
00203           z1 = z0 + h*zp + quadZ*h2/2;
00204               
00205           x1p = xp + quadX*h;
00206           y1p = yp + quadY*h;
00207           z1p = zp + quadZ*h;
00208               
00209           // estimate parameters at end of step:
00210           G4double quadX_end= - kappa*x1*z1p;
00211           G4double quadY_end=   kappa*y1*z1p;
00212           G4double quadZ_end=   kappa*(x1*x1p - y1*y1p);
00213               
00214           // determine maximum curvature:
00215           maxCurv=max(maxCurv,fabs(quadX_end));
00216           maxCurv=max(maxCurv,fabs(quadY_end));
00217           maxCurv=max(maxCurv,fabs(quadZ_end));
00218 
00219           itsDist=maxCurv*h2/4.;
00220               
00221           // use the average:
00222           G4double quadX_av=(quadX+quadX_end)/2;
00223           G4double quadY_av=(quadY+quadY_end)/2;
00224           G4double quadZ_av=(quadZ+quadZ_end)/2;
00225               
00226           G4double x_prime_av=(xp + x1p)/2;
00227           G4double y_prime_av=(yp + y1p)/2;
00228           G4double z_prime_av=(zp + z1p)/2;
00229               
00230           x1 = x0 + h*x_prime_av + quadX_av * h2/2;
00231           y1 = y0 + h*y_prime_av + quadY_av * h2/2; 
00232           z1 = z0 + h*z_prime_av + quadZ_av * h2/2;
00233               
00234           x1p = xp + quadX_av*h;
00235           y1p = yp + quadY_av*h;
00236           z1p = zp + quadZ_av*h;
00237               
00238           G4double dx = (x1-x0);
00239           G4double dy = (y1-y0);
00240           G4double dz = (z1-z0);
00241           G4double chord2 = dx*dx + dy*dy + dz*dz;
00242           if(chord2>h2)
00243             {
00244               G4double hnew=h*sqrt(h2/chord2);
00245               x1=x0 + hnew*x_prime_av + quadX_av * hnew*hnew/2;
00246               y1=y0 + hnew*y_prime_av + quadY_av * hnew*hnew/2; 
00247               z1=z0 + hnew*z_prime_av + quadZ_av * hnew*hnew/2;
00248 
00249               x1p=xp + quadX_av*hnew;
00250               y1p=yp + quadY_av*hnew;
00251               z1p=zp + quadZ_av*hnew;
00252             }
00253         }
00254 
00255       LocalR.setX(x1);
00256       LocalR.setY(y1);
00257       LocalR.setZ(z1);
00258           
00259       LocalRp.setX(x1p);
00260       LocalRp.setY(y1p);
00261       LocalRp.setZ(z1p);
00262 
00263     }
00264   else //if curvature = 0 ...
00265     {
00266       LocalR += h*LocalRp;
00267       itsDist=0.;
00268     }
00269 
00270 #ifdef BDSDEBUG 
00271   G4cout << "BDSQuadStepper: final point in local coordinates:" << G4endl
00272          << " x= " << LocalR[0]/CLHEP::m << "m" << G4endl
00273          << " y= " << LocalR[1]/CLHEP::m << "m" << G4endl
00274          << " z= " << LocalR[2]/CLHEP::m << "m" << G4endl
00275          << " x'= " << LocalRp[0] << G4endl
00276          << " y'= " << LocalRp[1] << G4endl
00277          << " z'= " << LocalRp[2] << G4endl
00278          << G4endl; 
00279 #endif
00280 
00281   G4AffineTransform LocalAffine=QuadNavigator-> 
00282     GetLocalToGlobalTransform();
00283 
00284   GlobalR = LocalAffine.TransformPoint(LocalR); 
00285   GlobalP = InitPMag*LocalAffine.TransformAxis(LocalRp);
00286 
00287   yQuad[0] = GlobalR.x(); 
00288   yQuad[1] = GlobalR.y(); 
00289   yQuad[2] = GlobalR.z(); 
00290 
00291   yQuad[3] = GlobalP.x();
00292   yQuad[4] = GlobalP.y();
00293   yQuad[5] = GlobalP.z();
00294 }    
00295 
00296 
00297 void BDSQuadStepper::Stepper( const G4double yInput[],
00298                               const G4double[],
00299                               const G4double hstep,
00300                               G4double yOut[],
00301                               G4double yErr[]      )
00302 {  
00303   const G4int nvar = 6 ;
00304   G4int i;
00305 
00306   const G4double *pIn = yInput+3;
00307   G4ThreeVector GlobalP = G4ThreeVector( pIn[0], pIn[1], pIn[2]);
00308   G4double InitPMag = GlobalP.mag();
00309   G4double kappa= - fPtrMagEqOfMot->FCof()*itsBGrad/InitPMag;
00310   
00311   if(fabs(kappa)<1.e-6) //kappa is small - no error needed for paraxial treatment
00312     {
00313       for(i=0;i<nvar;i++) yErr[i]=0;
00314       AdvanceHelix(yInput,(G4ThreeVector)0,hstep,yOut);
00315     }
00316   else   //need to compute errors for helical steps
00317     {
00318       G4double yTemp[7], yIn[7];
00319       
00320       //  Saving yInput because yInput and yOut can be aliases for same array
00321       
00322       for(i=0;i<nvar;i++) yIn[i]=yInput[i];
00323       
00324       // Do two half steps
00325       G4double h = hstep * 0.5; 
00326       AdvanceHelix(yIn,   (G4ThreeVector)0, h, yTemp);
00327       AdvanceHelix(yTemp, (G4ThreeVector)0, h, yOut); 
00328       
00329       // Do a full Step
00330       h = hstep ;
00331       AdvanceHelix(yIn, (G4ThreeVector)0, h, yTemp); 
00332       
00333       for(i=0;i<nvar;i++) {
00334         yErr[i] = yOut[i] - yTemp[i] ;
00335         // if error small, set error to 0
00336         // this is done to prevent Geant4 going to smaller and smaller steps
00337         // ideally use some of the global constants instead of hardcoding here
00338         // could look at step size as well instead.
00339         if (std::abs(yErr[i]) < 1e-7) yErr[i] = 0;
00340       }
00341     }
00342 }
00343 
00344 G4double BDSQuadStepper::DistChord()   const 
00345 {
00346   return itsDist;
00347   // This is a class method that gives distance of Mid 
00348   // from the Chord between the Initial and Final points.
00349 }
00350 
00351 BDSQuadStepper::~BDSQuadStepper()
00352 {
00353   delete QuadNavigator;
00354 }
00355 

Generated on 28 Jun 2015 for BDSIM by  doxygen 1.4.7