00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "BDSGlobalConstants.hh"
00022 #include "BDSSynchrotronRadiation.hh"
00023 #include "BDSBeamline.hh"
00024 #include "G4AffineTransform.hh"
00025 #include "G4Field.hh"
00026 #include "G4FieldManager.hh"
00027 #include "G4Gamma.hh"
00028 #include "G4ios.hh"
00029 #include "G4PropagatorInField.hh"
00030 #include "G4TransportationManager.hh"
00031 #include "Randomize.hh"
00032 #include "CLHEP/Units/PhysicalConstants.h"
00033
00034 BDSSynchrotronRadiation::BDSSynchrotronRadiation(const G4String& processName)
00035 : G4VDiscreteProcess(processName)
00036
00037 {
00038 nExpConst=5*CLHEP::fine_structure_const/(2*sqrt(3.0))/CLHEP::electron_mass_c2;
00039 CritEngFac=3./2.*CLHEP::hbarc/pow(CLHEP::electron_mass_c2,3);
00040 MeanFreePathCounter = 0;
00041 }
00042
00043 G4VParticleChange*
00044 BDSSynchrotronRadiation::PostStepDoIt(const G4Track& trackData,
00045 const G4Step& stepData)
00046 {
00047 #ifdef BDSDEBUG
00048 G4cout << "BDSSynchrotronRadiation::PostStepDoIt" << G4endl;
00049 #endif
00050 aParticleChange.Initialize(trackData);
00051
00052 aParticleChange.SetSecondaryWeightByProcess(true);
00053
00054 G4double eEnergy=trackData.GetTotalEnergy();
00055
00056
00057
00058 G4double NewKinEnergy = trackData.GetKineticEnergy();
00059
00060 G4double GamEnergy=0;
00061
00062 MeanFreePathCounter++;
00063
00064 const G4DynamicParticle* aDynamicParticle=trackData.GetDynamicParticle();
00065
00066 G4double gamma = aDynamicParticle->GetTotalEnergy()/
00067 (aDynamicParticle->GetMass() );
00068
00069 if(gamma <= 1.0e3 )
00070 {
00071 #ifdef BDSDEBUG
00072 G4cout << "BDSSynchrotronRadiation::PostStepDoItG\nGamma<1000" << G4endl;
00073 #endif
00074 return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
00075 }
00076 G4double particleCharge = aDynamicParticle->GetCharge();
00077
00078 G4ThreeVector FieldValue;
00079 const G4Field* pField = 0 ;
00080
00081 G4FieldManager* fieldMgr=0;
00082 G4bool fieldExertsForce = false;
00083
00084 G4TransportationManager* transportMgr =
00085 G4TransportationManager::GetTransportationManager();
00086
00087 G4PropagatorInField* fFieldPropagator = transportMgr->GetPropagatorInField();
00088 if( (particleCharge != 0.0) )
00089 {
00090 #ifdef BDSDEBUG
00091 G4cout << "BDSSynchrotronRadiation::PostStepDoIt\nParticle charge != 0.0" << G4endl;
00092 #endif
00093 fieldMgr = fFieldPropagator->FindAndSetFieldManager( trackData.GetVolume() );
00094 if ( fieldMgr != 0 )
00095 {
00096
00097
00098 fieldExertsForce = ( fieldMgr->GetDetectorField() != 0 );
00099 }
00100 }
00101 if ( fieldExertsForce )
00102 {
00103 #ifdef BDSDEBUG
00104 G4cout << "BDSSynchrotronRadiation::PostStepDoIt\n fieldExertsForce==true" << G4endl;
00105 #endif
00106 pField = fieldMgr->GetDetectorField() ;
00107 G4ThreeVector globPosition = trackData.GetPosition() ;
00108 G4double globPosVec[3], FieldValueVec[3] ;
00109 globPosVec[0] = globPosition.x() ;
00110 globPosVec[1] = globPosition.y() ;
00111 globPosVec[2] = globPosition.z() ;
00112
00113 pField->GetFieldValue( globPosVec, FieldValueVec ) ;
00114 FieldValue = G4ThreeVector( FieldValueVec[0],
00115 FieldValueVec[1],
00116 FieldValueVec[2] );
00117
00118 G4ThreeVector unitMomentum = aDynamicParticle->GetMomentumDirection();
00119 G4ThreeVector unitMcrossB = FieldValue.cross(unitMomentum);
00120 G4double perpB = unitMcrossB.mag() ;
00121 std::vector<G4DynamicParticle*> listOfSecondaries;
00122 if(perpB > 0.0)
00123 {
00124 #ifdef BDSDEBUG
00125 G4cout << "BDSSynchrotronRadiation::PostStepDoIt\nperpB>0.0" << G4endl;
00126 #endif
00127
00128 for (int i=0; i<BDSGlobalConstants::Instance()->GetSynchPhotonMultiplicity(); i++){
00129 #ifdef BDSDEBUG
00130 G4cout << "BDSSynchrotronRadiation::PostStepDoIt\nSynchPhotonMultiplicity" << G4endl;
00131 #endif
00132
00133 G4double R=(aDynamicParticle->GetTotalMomentum()/CLHEP::GeV)/
00134 (0.299792458*particleCharge*perpB);
00135 GamEnergy=SynGenC(BDSGlobalConstants::Instance()->GetSynchLowX())*
00136 CritEngFac*pow(eEnergy,3)/fabs(R);
00137
00138 if(GamEnergy>0 && GamEnergy < NewKinEnergy)
00139 {
00140 #ifdef BDSDEBUG
00141 G4cout << "BDSSynchrotronRadiation::PostStepDoIt\nGamEnergy in range" << G4endl;
00142 #endif
00143 if((BDSGlobalConstants::Instance()->GetSynchTrackPhotons())&&
00144 (GamEnergy>BDSGlobalConstants::Instance()->GetSynchLowGamE()) )
00145 {
00146 #ifdef BDSDEBUG
00147 G4cout << "BDSSynchrotronRadiation::PostStepDoIt\nTrackPhotons" << G4endl;
00148 #endif
00149 G4DynamicParticle* aGamma=
00150 new G4DynamicParticle (G4Gamma::Gamma(),
00151 trackData.GetMomentumDirection(),
00152 GamEnergy);
00153 listOfSecondaries.push_back(aGamma);
00154 #ifdef BDSDEBUG
00155 printf("Creating synchRad photon of energy %f\n",GamEnergy);
00156 #endif
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166 if(i==0 && MeanFreePathCounter==1) NewKinEnergy -= GamEnergy;
00167
00168 if (NewKinEnergy > 0.)
00169 {
00170 #ifdef BDSDEBUG
00171 G4cout << "BDSSynchrotronRadiation::PostStepDoIt\nNewKinEnergy>0.0" << G4endl;
00172 #endif
00173
00174 aParticleChange.ProposeEnergy(NewKinEnergy);
00175 }
00176 else
00177 {
00178 aParticleChange.ProposeEnergy( 0. );
00179 aParticleChange.ProposeLocalEnergyDeposit (0.);
00180 G4double charge= trackData.GetDynamicParticle()->GetCharge();
00181 if (charge<0.) aParticleChange.ProposeTrackStatus(fStopAndKill);
00182 else aParticleChange.ProposeTrackStatus(fStopButAlive);
00183 }
00184 }
00185 }
00186 aParticleChange.SetNumberOfSecondaries(listOfSecondaries.size());
00187
00188 for(unsigned int n=0;n<listOfSecondaries.size();n++){
00189 #ifdef BDSDEBUG
00190 G4cout << "BDSSynchrotronRadiation::PostStepDoIt\nAdding secondaries" << G4endl;
00191 #endif
00192
00193 aParticleChange.AddSecondary(listOfSecondaries[n]);
00194 #ifdef BDSDEBUG
00195 G4cout << "Adding secondary particle...\n";
00196 #endif
00197 }
00198
00199 G4double gammaWeight = aParticleChange.GetParentWeight()/BDSGlobalConstants::Instance()->GetSynchPhotonMultiplicity();
00200
00201 for(unsigned int n=0;n<listOfSecondaries.size();n++){
00202 aParticleChange.GetSecondary(n)->SetWeight(gammaWeight);
00203 }
00204 }
00205 }
00206 return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
00207 }
00208
00209 BDSSynchrotronRadiation::~BDSSynchrotronRadiation(){
00210 }
00211
00212
00213
00214 G4double BDSSynchrotronRadiation::SynGenC(G4double xmin)
00215
00216
00217
00218
00219
00220 { static bool DoInit=true;
00221 static G4double a1,a2,c1,xlow,ratio,LastXmin=-1.;
00222
00223 if((DoInit) | (xmin!=LastXmin))
00224 { DoInit=false;
00225 LastXmin=xmin;
00226 if(xmin>1.) xlow=xmin; else xlow=1.;
00227
00228
00229 a1=SynRadC(1.e-38)/pow(1.e-38,-2./3.);
00230 a2=SynRadC(xlow)/exp(-xlow);
00231 c1=pow(xmin,1./3.);
00232
00233 if(xmin<1.)
00234 { G4double sum1ap=3.*a1*(1.-pow(xmin,1./3.));
00235 G4double sum2ap=a2*exp(-1.);
00236 ratio=sum1ap/(sum1ap+sum2ap);
00237 }
00238 else
00239 { ratio=0.;
00240 a2=SynRadC(xlow)/exp(-xlow);
00241 }
00242 }
00243
00244 G4double appr,exact,result;
00245 do
00246 { if(G4UniformRand()<ratio)
00247 { result=c1+(1.-c1)*G4UniformRand();
00248 result*=result*result;
00249 exact=SynRadC(result);
00250 appr=a1*pow(result,-2./3.);
00251 }
00252 else
00253 { result=xlow-log(G4UniformRand());
00254 exact=SynRadC(result);
00255 appr=a2*exp(-result);
00256 }
00257 }
00258 while(exact<appr*G4UniformRand());
00259 return result;
00260 }
00261
00262 G4double BDSSynchrotronRadiation::SynRadC(G4double x)
00263
00264
00265
00266
00267
00268
00269 { G4double synrad=0.;
00270 if((x>0.) & (x<800.))
00271 { if(x<6.)
00272 { G4double a,b,z;
00273 z=x*x/16.-2.;
00274 b= .00000000000000000012;
00275 a=z*b + .00000000000000000460;
00276 b=z*a-b+ .00000000000000031738;
00277 a=z*b-a+ .00000000000002004426;
00278 b=z*a-b+ .00000000000111455474;
00279 a=z*b-a+ .00000000005407460944;
00280 b=z*a-b+ .00000000226722011790;
00281 a=z*b-a+ .00000008125130371644;
00282 b=z*a-b+ .00000245751373955212;
00283 a=z*b-a+ .00006181256113829740;
00284 b=z*a-b+ .00127066381953661690;
00285 a=z*b-a+ .02091216799114667278;
00286 b=z*a-b+ .26880346058164526514;
00287 a=z*b-a+ 2.61902183794862213818;
00288 b=z*a-b+ 18.65250896865416256398;
00289 a=z*b-a+ 92.95232665922707542088;
00290 b=z*a-b+ 308.15919413131586030542;
00291 a=z*b-a+ 644.86979658236221700714;
00292 G4double p;
00293 p=.5*z*a-b+ 414.56543648832546975110;
00294 a= .00000000000000000004;
00295 b=z*a+ .00000000000000000289;
00296 a=z*b-a+ .00000000000000019786;
00297 b=z*a-b+ .00000000000001196168;
00298 a=z*b-a+ .00000000000063427729;
00299 b=z*a-b+ .00000000002923635681;
00300 a=z*b-a+ .00000000115951672806;
00301 b=z*a-b+ .00000003910314748244;
00302 a=z*b-a+ .00000110599584794379;
00303 b=z*a-b+ .00002581451439721298;
00304 a=z*b-a+ .00048768692916240683;
00305 b=z*a-b+ .00728456195503504923;
00306 a=z*b-a+ .08357935463720537773;
00307 b=z*a-b+ .71031361199218887514;
00308 a=z*b-a+ 4.26780261265492264837;
00309 b=z*a-b+ 17.05540785795221885751;
00310 a=z*b-a+ 41.83903486779678800040;
00311 G4double q;
00312 q=.5*z*a-b+28.41787374362784178164;
00313 G4double y;
00314 G4double const twothird=2./3.;
00315 y=pow(x,twothird);
00316 synrad=(p/y-q*y-1.)*1.81379936423421784215530788143;
00317 }
00318 else
00319 { G4double a,b,z;
00320 z=20./x-2.;
00321 a= .00000000000000000001;
00322 b=z*a -.00000000000000000002;
00323 a=z*b-a+.00000000000000000006;
00324 b=z*a-b-.00000000000000000020;
00325 a=z*b-a+.00000000000000000066;
00326 b=z*a-b-.00000000000000000216;
00327 a=z*b-a+.00000000000000000721;
00328 b=z*a-b-.00000000000000002443;
00329 a=z*b-a+.00000000000000008441;
00330 b=z*a-b-.00000000000000029752;
00331 a=z*b-a+.00000000000000107116;
00332 b=z*a-b-.00000000000000394564;
00333 a=z*b-a+.00000000000001489474;
00334 b=z*a-b-.00000000000005773537;
00335 a=z*b-a+.00000000000023030657;
00336 b=z*a-b-.00000000000094784973;
00337 a=z*b-a+.00000000000403683207;
00338 b=z*a-b-.00000000001785432348;
00339 a=z*b-a+.00000000008235329314;
00340 b=z*a-b-.00000000039817923621;
00341 a=z*b-a+.00000000203088939238;
00342 b=z*a-b-.00000001101482369622;
00343 a=z*b-a+.00000006418902302372;
00344 b=z*a-b-.00000040756144386809;
00345 a=z*b-a+.00000287536465397527;
00346 b=z*a-b-.00002321251614543524;
00347 a=z*b-a+.00022505317277986004;
00348 b=z*a-b-.00287636803664026799;
00349 a=z*b-a+.06239591359332750793;
00350 G4double p;
00351 p=.5*z*a-b +1.06552390798340693166;
00352
00353 synrad=p*sqrt(CLHEP::halfpi/x)/exp(x);
00354 }
00355 }
00356 return synrad;
00357 }
00358
00359 G4double
00360 BDSSynchrotronRadiation::GetMeanFreePath(const G4Track& track,
00361 G4double ,
00362 G4ForceCondition* ForceCondition)
00363 {
00364 *ForceCondition = NotForced ;
00365
00366
00367
00368 G4double MeanFreePath;
00369 G4FieldManager* TheFieldManager=
00370 track.GetVolume()->GetLogicalVolume()->GetFieldManager();
00371
00372 if(track.GetTotalEnergy()<BDSGlobalConstants::Instance()->GetThresholdCutCharged())
00373 return DBL_MAX;
00374
00375
00376
00377
00378
00379 if(TheFieldManager)
00380 {
00381 const G4Field* pField = TheFieldManager->GetDetectorField() ;
00382 G4ThreeVector globPosition = track.GetPosition() ;
00383 G4double globPosVec[3], FieldValueVec[3]={0.} ;
00384 globPosVec[0] = globPosition.x() ;
00385 globPosVec[1] = globPosition.y() ;
00386 globPosVec[2] = globPosition.z() ;
00387
00388 if(pField)
00389 pField->GetFieldValue( globPosVec, FieldValueVec ) ;
00390
00391 G4double Blocal= FieldValueVec[1];
00392 if ( FieldValueVec[0]!=0.)
00393 Blocal=sqrt(Blocal*Blocal+FieldValueVec[0]*FieldValueVec[0]);
00394
00395
00396
00397 if(track.GetMaterial()==BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetVacuumMaterial())
00398 && Blocal !=0 )
00399 {
00400 G4ThreeVector InitMag=track.GetMomentum();
00401
00402
00403
00404 G4AffineTransform tf(track.GetTouchable()->GetHistory()->GetTopTransform().Inverse());
00405 const G4RotationMatrix Rot=tf.NetRotation();
00406 const G4ThreeVector Trans=-tf.NetTranslation();
00407 InitMag=Rot*InitMag;
00408
00409
00410 G4double Rlocal=(InitMag.z()/CLHEP::GeV)/(0.299792458 * Blocal/CLHEP::tesla) *CLHEP::m;
00411
00412 MeanFreePath=
00413 fabs(Rlocal)/(track.GetTotalEnergy()*nExpConst);
00414
00415 MeanFreePath /= BDSGlobalConstants::Instance()->GetSynchMeanFreeFactor();
00416
00417
00418 if(MeanFreePathCounter>=BDSGlobalConstants::Instance()->GetSynchMeanFreeFactor())
00419 MeanFreePathCounter=0;
00420
00421 #ifdef BDSDEBUG
00422 G4cout<<"*****************SR*************************"<<G4endl;
00423 G4cout<<"Track momentum: "<<InitMag<<G4endl;
00424 G4cout<<"Blocal="<<Blocal/CLHEP::tesla<<" Rlocal="<<Rlocal/CLHEP::m<<G4endl;
00425 G4cout<<track.GetVolume()->GetName()<<" mfp="<<MeanFreePath/CLHEP::m<<G4endl;
00426 G4cout<<"********************************************"<<G4endl;
00427 #endif
00428
00429 return MeanFreePath;
00430 }
00431 else
00432 return DBL_MAX;
00433 }
00434 else
00435 return DBL_MAX;
00436
00437 }
00438
00439