00001 #include "BDSSolenoidStepper.hh"
00002 #include "BDSDebug.hh"
00003
00004 #include "G4ThreeVector.hh"
00005 #include "G4TransportationManager.hh"
00006 #include "G4Navigator.hh"
00007 #include "G4AffineTransform.hh"
00008 #include "G4ClassicalRK4.hh"
00009
00010 extern G4double BDSLocalRadiusOfCurvature;
00011
00012 BDSSolenoidStepper::BDSSolenoidStepper(G4Mag_EqRhs *EqRhs)
00013 : G4MagIntegratorStepper(EqRhs,6),
00014
00015 itsBField(0.0), itsDist(0.0), nvar(6)
00016 {
00017 fPtrMagEqOfMot = EqRhs;
00018 SolenoidNavigator = new G4Navigator();
00019 backupStepper = new G4ClassicalRK4(EqRhs,6);
00020 }
00021
00022 void BDSSolenoidStepper::AdvanceHelix( const G4double yIn[],
00023 const G4double dydx[],
00024 G4ThreeVector,
00025 G4double h,
00026 G4double yOut[],
00027 G4double yErr[])
00028 {
00029 const G4double *pIn = yIn+3;
00030 G4ThreeVector GlobalR = G4ThreeVector( yIn[0], yIn[1], yIn[2]);
00031 G4ThreeVector GlobalP = G4ThreeVector( pIn[0], pIn[1], pIn[2]);
00032 G4ThreeVector InitMomDir = GlobalP.unit();
00033 G4double InitPMag = GlobalP.mag();
00034 G4double kappa = - 0.5*fPtrMagEqOfMot->FCof()*itsBField/InitPMag;
00035 G4double h2 = h*h;
00036
00037 #ifdef BDSDEBUG
00038 G4double charge = (fPtrMagEqOfMot->FCof())/CLHEP::c_light;
00039 G4cout << "BDSSolenoidStepper: step = " << h/CLHEP::m << " m" << G4endl
00040 << " x = " << yIn[0]/CLHEP::m << " m" << G4endl
00041 << " y = " << yIn[1]/CLHEP::m << " m" << G4endl
00042 << " z = " << yIn[2]/CLHEP::m << " m" << G4endl
00043 << " px = " << yIn[3]/CLHEP::GeV << " GeV/c" << G4endl
00044 << " py = " << yIn[4]/CLHEP::GeV << " GeV/c" << G4endl
00045 << " pz = " << yIn[5]/CLHEP::GeV << " GeV/c" << G4endl
00046 << " q = " << charge/CLHEP::eplus << "e" << G4endl
00047 << " Bz = " << itsBField/(CLHEP::tesla/CLHEP::m) << " T" << G4endl
00048 << " k = " << kappa/(1./CLHEP::m2) << " m^-2" << G4endl
00049 << G4endl;
00050 #endif
00051
00052
00053 SolenoidNavigator->SetWorldVolume(G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume());
00054 SolenoidNavigator->LocateGlobalPointAndSetup(GlobalR);
00055
00056
00057 G4AffineTransform GlobalAffine = SolenoidNavigator->
00058 GetGlobalToLocalTransform();
00059
00060 G4ThreeVector LocalR = GlobalAffine.TransformPoint(GlobalR);
00061 G4ThreeVector LocalRp = GlobalAffine.TransformAxis(InitMomDir);
00062
00063 G4double x1,xp1,y1,yp1,z1,zp1;
00064
00065 if (fabs(kappa)<1e-12)
00066 {
00067
00068 G4ThreeVector positionMove = h * InitMomDir;
00069
00070 yOut[0] = yIn[0] + positionMove.x();
00071 yOut[1] = yIn[1] + positionMove.y();
00072 yOut[2] = yIn[2] + positionMove.z();
00073
00074 yOut[3] = GlobalP.x();
00075 yOut[4] = GlobalP.y();
00076 yOut[5] = GlobalP.z();
00077
00078 yErr[0] = 0;
00079 yErr[1] = 0;
00080 yErr[2] = 0;
00081 yErr[3] = 0;
00082 yErr[4] = 0;
00083 yErr[5] = 0;
00084
00085 itsDist=0;
00086 return;
00087 }
00088
00089
00090 G4double x0 = LocalR.x();
00091 G4double y0 = LocalR.y();
00092 G4double z0 = LocalR.z();
00093 G4double xp0 = LocalRp.x();
00094 G4double yp0 = LocalRp.y();
00095 G4double zp0 = LocalRp.z();
00096
00097
00098 G4ThreeVector LocalRpp;
00099 LocalRpp.setX(-zp0*x0);
00100 LocalRpp.setY( zp0*y0);
00101 LocalRpp.setZ( x0*xp0 - y0*yp0);
00102 LocalRpp *= kappa;
00103
00104
00105 G4double R_1 = LocalRpp.mag();
00106 #ifdef BDSDEBUG
00107 G4cout << " curvature= " << R_1*CLHEP::m << "m^-1" << G4endl;
00108 #endif
00109
00110 if (R_1<1e-15)
00111 {
00112
00113 G4ThreeVector positionMove = h * InitMomDir;
00114
00115 yOut[0] = yIn[0] + positionMove.x();
00116 yOut[1] = yIn[1] + positionMove.y();
00117 yOut[2] = yIn[2] + positionMove.z();
00118
00119 yOut[3] = GlobalP.x();
00120 yOut[4] = GlobalP.y();
00121 yOut[5] = GlobalP.z();
00122
00123 yErr[0] = 0;
00124 yErr[1] = 0;
00125 yErr[2] = 0;
00126 yErr[3] = 0;
00127 yErr[4] = 0;
00128 yErr[5] = 0;
00129
00130 itsDist=0;
00131 return;
00132 }
00133
00134 #ifdef BDSDEBUG
00135 G4cout << __METHOD_NAME__ << " using thick lens matrix " << G4endl;
00136 #endif
00137
00138
00139 G4double R=1./R_1;
00140 BDSLocalRadiusOfCurvature=R;
00141
00142
00143 itsDist= h2/(8*R);
00144
00145
00146 if(fabs(zp0)>0.9)
00147 {
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 G4double w = kappa;
00159
00160 G4ThreeVector positionMove = h * InitMomDir;
00161 G4double dz = positionMove.z();
00162 G4double wL = kappa*dz;
00163 G4double cosOL = cos(wL);
00164 G4double cosSqOL = cosOL*cosOL;
00165 G4double sinOL = sin(wL);
00166 G4double sin2OL = sin(2.0*wL);
00167 G4double sinSqOL = sinOL*sinOL;
00168
00169
00170 x1 = x0*cosSqOL + (0.5*xp0/w)*sin2OL + (0.5*y0)*sin2OL + (yp0/w)*sinSqOL;
00171 xp1 = (0.5*x0*w)*sin2OL + xp0*cosSqOL - (w*y0)*sinSqOL + (0.5*yp0)*sin2OL;
00172 y1 = (-0.5*x0)*sin2OL - (xp0/w)*sinSqOL + y0*cosSqOL + (0.5*yp0/w)*sin2OL;
00173 yp1 = x0*w*sinSqOL - (0.5*xp0)*sin2OL - (0.5*w*y0)*sin2OL + yp0*cosSqOL;
00174
00175
00176 zp1 = sqrt(1 - xp1*xp1 -yp1*yp1);
00177
00178
00179 G4double dx = x1-x0;
00180 G4double dy = y1-y0;
00181
00182
00183 G4double ScaleFac = (dx*dx+dy*dy+dz*dz)/h2;
00184 #ifdef BDSDEBUG
00185 G4cout << "Ratio of calculated to proposed step length: " << ScaleFac << G4endl;
00186 #endif
00187 if(ScaleFac>1.0000001)
00188 {
00189 #ifdef BDSDEBUG
00190 G4cout << __METHOD_NAME__ << " normalising to conserve step length" << G4endl;
00191 #endif
00192 ScaleFac = sqrt(ScaleFac);
00193 dx /= ScaleFac;
00194 dy /= ScaleFac;
00195 dz /= ScaleFac;
00196 x1 = x0+dx;
00197 y1 = y0+dy;
00198 }
00199 z1 = z0+dz;
00200
00201
00202 LocalR.setX(x1);
00203 LocalR.setY(y1);
00204 LocalR.setZ(z1);
00205 LocalRp.setX(xp1);
00206 LocalRp.setY(yp1);
00207 LocalRp.setZ(zp1);
00208
00209 #ifdef BDSDEBUG
00210 G4cout << "BDSSolenoidStepper: final point in local coordinates:" << G4endl
00211 << " x = " << LocalR[0]/CLHEP::m << " m" << G4endl
00212 << " y = " << LocalR[1]/CLHEP::m << " m" << G4endl
00213 << " z = " << LocalR[2]/CLHEP::m << " m" << G4endl
00214 << " x' = " << LocalRp[0] << G4endl
00215 << " y' = " << LocalRp[1] << G4endl
00216 << " z' = " << LocalRp[2] << G4endl
00217 << G4endl;
00218 #endif
00219
00220 G4AffineTransform LocalAffine = SolenoidNavigator->
00221 GetLocalToGlobalTransform();
00222
00223 GlobalR = LocalAffine.TransformPoint(LocalR);
00224 GlobalP = InitPMag*LocalAffine.TransformAxis(LocalRp);
00225
00226 yOut[0] = GlobalR.x();
00227 yOut[1] = GlobalR.y();
00228 yOut[2] = GlobalR.z();
00229
00230 yOut[3] = GlobalP.x();
00231 yOut[4] = GlobalP.y();
00232 yOut[5] = GlobalP.z();
00233
00234 for(G4int i=0;i<nvar;i++) yErr[i]=0;
00235 }
00236 else
00237
00238 {
00239 #ifdef BDSDEBUG
00240 G4cout << __METHOD_NAME__ << " local helical steps - using G4ClassicalRK4" << G4endl;
00241 #endif
00242
00243 backupStepper->Stepper(yIn, dydx, h, yOut, yErr);
00244 }
00245 }
00246
00247
00248 void BDSSolenoidStepper::Stepper( const G4double yInput[],
00249 const G4double dydx[],
00250 const G4double hstep,
00251 G4double yOut[],
00252 G4double yErr[] )
00253 {
00254
00255 AdvanceHelix(yInput,dydx,(G4ThreeVector)0,hstep,yOut,yErr);
00256 }
00257
00258 G4double BDSSolenoidStepper::DistChord() const
00259 {
00260 return itsDist;
00261
00262
00263 }
00264
00265 BDSSolenoidStepper::~BDSSolenoidStepper()
00266 {}