00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "G4MagHelicalStepper.hh"
00032 #include "G4PhysicalConstants.hh"
00033 #include "G4SystemOfUnits.hh"
00034 #include "G4LineSection.hh"
00035 #include "G4Mag_EqRhs.hh"
00036
00037
00038
00039
00040
00041
00042
00043
00044 const G4double G4MagHelicalStepper::fUnitConstant = 0.299792458*(GeV/(tesla*m));
00045
00046
00047 G4MagHelicalStepper::G4MagHelicalStepper(G4Mag_EqRhs *EqRhs)
00048 : G4MagIntegratorStepper(EqRhs, 6),
00049
00050 fPtrMagEqOfMot(EqRhs), fAngCurve(0.), frCurve(0.), frHelix(0.)
00051 {
00052 }
00053
00054 G4MagHelicalStepper::~G4MagHelicalStepper()
00055 {
00056 }
00057
00058 void
00059 G4MagHelicalStepper::AdvanceHelix( const G4double yIn[],
00060 G4ThreeVector Bfld,
00061 G4double h,
00062 G4double yHelix[],
00063 G4double yHelix2[] )
00064 {
00065
00066
00067
00068
00069
00070
00071 const G4double approc_limit = 0.005;
00072 G4ThreeVector Bnorm, B_x_P, vperp, vpar;
00073
00074 G4double B_d_P;
00075 G4double B_v_P;
00076 G4double Theta;
00077 G4double R_1;
00078 G4double R_Helix;
00079 G4double CosT2, SinT2, CosT, SinT;
00080 G4ThreeVector positionMove, endTangent;
00081
00082 G4double Bmag = Bfld.mag();
00083 const G4double *pIn = yIn+3;
00084 G4ThreeVector initVelocity= G4ThreeVector( pIn[0], pIn[1], pIn[2]);
00085 G4double velocityVal = initVelocity.mag();
00086 G4ThreeVector initTangent = (1.0/velocityVal) * initVelocity;
00087
00088 R_1=GetInverseCurve(velocityVal,Bmag);
00089
00090
00091
00092
00093 if( (std::fabs(R_1) < 1e-10)||(Bmag<1e-12) )
00094 {
00095 LinearStep( yIn, h, yHelix );
00096
00097
00098
00099 SetAngCurve(1.);
00100 SetCurve(h);
00101 SetRadHelix(0.);
00102 }
00103 else
00104 {
00105 Bnorm = (1.0/Bmag)*Bfld;
00106
00107
00108
00109 B_x_P = Bnorm.cross(initTangent);
00110
00111
00112
00113 B_d_P = Bnorm.dot(initTangent);
00114
00115 vpar = B_d_P * Bnorm;
00116 vperp= initTangent - vpar;
00117
00118 B_v_P = std::sqrt( 1 - B_d_P * B_d_P);
00119
00120
00121
00122 Theta = R_1 * h;
00123
00124
00125
00126 if( std::fabs(Theta) > approc_limit )
00127 {
00128 SinT = std::sin(Theta);
00129 CosT = std::cos(Theta);
00130 }
00131 else
00132 {
00133 G4double Theta2 = Theta*Theta;
00134 G4double Theta3 = Theta2 * Theta;
00135 G4double Theta4 = Theta2 * Theta2;
00136 SinT = Theta - 1.0/6.0 * Theta3;
00137 CosT = 1 - 0.5 * Theta2 + 1.0/24.0 * Theta4;
00138 }
00139
00140
00141
00142 G4double R = 1.0 / R_1;
00143
00144 positionMove = R * ( SinT * vperp + (1-CosT) * B_x_P) + h * vpar;
00145 endTangent = CosT * vperp + SinT * B_x_P + vpar;
00146
00147
00148
00149 yHelix[0] = yIn[0] + positionMove.x();
00150 yHelix[1] = yIn[1] + positionMove.y();
00151 yHelix[2] = yIn[2] + positionMove.z();
00152 yHelix[3] = velocityVal * endTangent.x();
00153 yHelix[4] = velocityVal * endTangent.y();
00154 yHelix[5] = velocityVal * endTangent.z();
00155
00156
00157
00158 if(yHelix2)
00159 {
00160 SinT2 = 2.0 * SinT * CosT;
00161 CosT2 = 1.0 - 2.0 * SinT * SinT;
00162 endTangent = (CosT2 * vperp + SinT2 * B_x_P + vpar);
00163 positionMove = R * ( SinT2 * vperp + (1-CosT2) * B_x_P) + h*2 * vpar;
00164
00165 yHelix2[0] = yIn[0] + positionMove.x();
00166 yHelix2[1] = yIn[1] + positionMove.y();
00167 yHelix2[2] = yIn[2] + positionMove.z();
00168 yHelix2[3] = velocityVal * endTangent.x();
00169 yHelix2[4] = velocityVal * endTangent.y();
00170 yHelix2[5] = velocityVal * endTangent.z();
00171 }
00172
00173
00174
00175 G4double ptan=velocityVal*B_v_P;
00176
00177 G4double particleCharge = fPtrMagEqOfMot->FCof() / (eplus*c_light);
00178 R_Helix =std::abs( ptan/(fUnitConstant * particleCharge*Bmag));
00179
00180 SetAngCurve(std::abs(Theta));
00181 SetCurve(std::abs(R));
00182 SetRadHelix(R_Helix);
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191 void
00192 G4MagHelicalStepper::Stepper( const G4double yInput[],
00193 const G4double*,
00194 G4double hstep,
00195 G4double yOut[],
00196 G4double yErr[] )
00197 {
00198 const G4int nvar = 6;
00199
00200 G4int i;
00201
00202
00203
00204
00205 G4double yTemp[7], yIn[7] ;
00206 G4ThreeVector Bfld_initial, Bfld_midpoint;
00207
00208
00209
00210 for(i=0;i<nvar;i++) { yIn[i]=yInput[i]; }
00211
00212 G4double h = hstep * 0.5;
00213
00214 MagFieldEvaluate(yIn, Bfld_initial) ;
00215
00216
00217
00218 DumbStepper(yIn, Bfld_initial, h, yTemp);
00219 MagFieldEvaluate(yTemp, Bfld_midpoint) ;
00220 DumbStepper(yTemp, Bfld_midpoint, h, yOut);
00221
00222
00223
00224 h = hstep ;
00225 DumbStepper(yIn, Bfld_initial, h, yTemp);
00226
00227
00228
00229 for(i=0;i<nvar;i++)
00230 {
00231 yErr[i] = yOut[i] - yTemp[i] ;
00232 }
00233
00234 return;
00235 }
00236
00237 G4double
00238 G4MagHelicalStepper::DistChord() const
00239 {
00240
00241
00242
00243 G4double Ang=GetAngCurve();
00244 if(Ang<=pi)
00245 {
00246 return GetRadHelix()*(1-std::cos(0.5*Ang));
00247 }
00248 else
00249 {
00250 if(Ang<twopi)
00251 {
00252 return GetRadHelix()*(1+std::cos(0.5*(twopi-Ang)));
00253 }
00254 else
00255 {
00256 return 2*GetRadHelix();
00257 }
00258 }
00259 }