00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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),
00026
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
00069
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
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
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
00132 BDSLocalRadiusOfCurvature=R;
00133
00134
00135 itsDist= h2/(8*R);
00136
00137
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
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
00182 G4double dR2=dx*dx+dy*dy;
00183 G4double dz=sqrt(h2*(1.-h2/(12*R*R))-dR2);
00184
00185
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
00200 {
00201
00202 G4double quadX= - kappa*x0*zp;
00203 G4double quadY= kappa*y0*zp;
00204 G4double quadZ= kappa*(x0*xp - y0*yp);
00205
00206
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
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
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
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
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)
00323 {
00324 for(i=0;i<nvar;i++) yErr[i]=0;
00325 AdvanceHelix(yInput,(G4ThreeVector)0,hstep,yOut);
00326 }
00327 else
00328 {
00329 G4double yTemp[7], yIn[7];
00330
00331
00332
00333 for(i=0;i<nvar;i++) yIn[i]=yInput[i];
00334
00335
00336 G4double h = hstep * 0.5;
00337 AdvanceHelix(yIn, (G4ThreeVector)0, h, yTemp);
00338 AdvanceHelix(yTemp, (G4ThreeVector)0, h, yOut);
00339
00340
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
00352
00353 }
00354
00355 BDSQuadStepper::~BDSQuadStepper()
00356 {
00357 delete QuadNavigator;
00358 }
00359