src/BDSQuadStepper.cc

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

Generated on 27 Aug 2013 for BDSIM by  doxygen 1.4.7