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),
00012
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
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
00054
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
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
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
00117 BDSLocalRadiusOfCurvature=R;
00118
00119
00120 itsDist= h2/(8*R);
00121
00122
00123 if(fabs(zp)>0.9)
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
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
00170 G4double dR2=dx*dx+dy*dy;
00171 G4double dz=sqrt(h2*(1.-h2/(12*R*R))-dR2);
00172
00173
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
00188 {
00189 #ifdef BDSDEBUG
00190 G4cout << "local helical steps" << G4endl;
00191 #endif
00192
00193 G4double quadX= - kappa*x0*zp;
00194 G4double quadY= kappa*y0*zp;
00195 G4double quadZ= kappa*(x0*xp - y0*yp);
00196
00197
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
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
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
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
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)
00312 {
00313 for(i=0;i<nvar;i++) yErr[i]=0;
00314 AdvanceHelix(yInput,(G4ThreeVector)0,hstep,yOut);
00315 }
00316 else
00317 {
00318 G4double yTemp[7], yIn[7];
00319
00320
00321
00322 for(i=0;i<nvar;i++) yIn[i]=yInput[i];
00323
00324
00325 G4double h = hstep * 0.5;
00326 AdvanceHelix(yIn, (G4ThreeVector)0, h, yTemp);
00327 AdvanceHelix(yTemp, (G4ThreeVector)0, h, yOut);
00328
00329
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
00336
00337
00338
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
00348
00349 }
00350
00351 BDSQuadStepper::~BDSQuadStepper()
00352 {
00353 delete QuadNavigator;
00354 }
00355