/scratch0/jsnuveri/BDSIM/BDSIMgit/bdsim/src/BDSSynchrotronRadiation.cc

00001 /* BDSIM code.    Version 1.0
00002    Author: Grahame A. Blair, Royal Holloway, Univ. of London.
00003    Last modified 24.7.2002
00004    Copyright (c) 2002 by G.A.Blair.  ALL RIGHTS RESERVED. 
00005 */ 
00006 //      ------------ BDSSynchrotronRadiation physics process --------
00007 //                     by Grahame Blair, 18 October 2001
00008 
00009 /* Modifications to BDSSynchrotronRadiation physics process
00010    Author of Mods: John Carter, Royal Holloway, Univ. of London
00011    Date: 16.11.2004
00012    Description: Modified to improve efficiency of process. It is now possible 
00013    to use BDSInput.cards to create a given number of photons 
00014    each time (rather than one) using SYNCH_PHOTON_MULTIPLICITY
00015    
00016    Also modified to break up the meanfree path length into a given
00017    number of smaller lengths. Use the following BDSInput.card
00018                 flag, SYNCH_MEANFREE_FACTOR
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     // initialization
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   //Allow reweight of the synchrotron photons
00052   aParticleChange.SetSecondaryWeightByProcess(true);
00053 
00054   G4double eEnergy=trackData.GetTotalEnergy();
00055   
00056   //G4double R=BDSLocalRadiusOfCurvature;
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           // If the field manager has no field, there is no field !
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           //Loop over multiplicity
00128           for (int i=0; i<BDSGlobalConstants::Instance()->GetSynchPhotonMultiplicity(); i++){
00129 #ifdef BDSDEBUG 
00130             G4cout  << "BDSSynchrotronRadiation::PostStepDoIt\nSynchPhotonMultiplicity" << G4endl;
00131 #endif
00132             //if(fabs(R)==0)
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                 //BDSBeamline::const_iterator iBeam;
00160                 //G4double zpos=trackData.GetPosition().z();
00161                 
00162                 //   for(iBeam=BDSBeamline::Instance()->begin();
00163                 //        iBeam!=BDSBeamline::Instance()->end() && zpos>=(*iBeam)->GetZUpper(); 
00164                 //        iBeam++){}
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                     // Update the incident particle 
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           //Find out the weight of the gammas
00199           G4double gammaWeight = aParticleChange.GetParentWeight()/BDSGlobalConstants::Instance()->GetSynchPhotonMultiplicity();
00200           //Set the weights of the gammas
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 // routines from H. Burkhardt (Lep Note 632)
00214 G4double BDSSynchrotronRadiation::SynGenC(G4double xmin)
00215 // C++ version
00216 // synchrotron radiation photon spectrum generator
00217 // returns photon energy in units of the critical energy
00218 // xmin is the lower limit for the photon energy to be generated
00219 //          see H.Burkhardt, LEP Note 632
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      // initialize constants used in the approximate expressions
00228      // for SYNRAD   (integral over the modified Bessel function K5/3)
00229     a1=SynRadC(1.e-38)/pow(1.e-38,-2./3.); // = 2**2/3 GAMMA(2/3)
00230     a2=SynRadC(xlow)/exp(-xlow);
00231     c1=pow(xmin,1./3.);
00232      // calculate the integrals of the approximate expressions
00233     if(xmin<1.) // low and high approx needed
00234     { G4double sum1ap=3.*a1*(1.-pow(xmin,1./3.)); //     integral xmin --> 1
00235       G4double sum2ap=a2*exp(-1.);                    //     integral 1 --> infin
00236       ratio=sum1ap/(sum1ap+sum2ap);
00237     }
00238     else // only high approx needed
00239     {  ratio=0.;     //     generate only high energies using approx. 2
00240        a2=SynRadC(xlow)/exp(-xlow);
00241     }
00242   }
00243   // Init done, now generate
00244   G4double appr,exact,result;
00245   do
00246   { if(G4UniformRand()<ratio)           // use low energy approximation
00247      { result=c1+(1.-c1)*G4UniformRand();
00248        result*=result*result;  // take to 3rd power;
00249        exact=SynRadC(result);
00250        appr=a1*pow(result,-2./3.);
00251      }
00252      else                      // use high energy approximation
00253      { result=xlow-log(G4UniformRand());
00254        exact=SynRadC(result);
00255        appr=a2*exp(-result);
00256      }
00257   }
00258   while(exact<appr*G4UniformRand());    // reject in proportion of approx
00259   return result;               // result now exact spectrum with unity weight
00260 }
00261 
00262 G4double BDSSynchrotronRadiation::SynRadC(G4double x)
00263 /*   x :    energy normalized to the critical energy
00264      returns function value SynRadC   photon spectrum dn/dx
00265      (integral of modified 1/3 order Bessel function)
00266      principal: Chebyshev series see H.H.Umstaetter CERN/PS/SM/81-13 10-3-1981
00267      see also my LEP Note 632 of 12/1990
00268      converted to C++, H.Burkhardt 21-4-1996    */
00269 { G4double synrad=0.;
00270   if((x>0.) & (x<800.)) // otherwise result synrad remains 0
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 // 6 < x < 174
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        //       G4double const pihalf=pi/2.;
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 /*PreviousStepSize*/,
00362                                          G4ForceCondition* ForceCondition)
00363 {  
00364   *ForceCondition = NotForced ;
00365 
00366   //   static G4FieldManager* lastFieldManager;
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   G4double SynchOnZPos = (7.184+4.0) * CLHEP::m;
00376   if(track.GetPosition().z() + BDSGlobalConstants::Instance()->GetWorldSizeZ() < SynchOnZPos)
00377     return DBL_MAX;
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           // transform to the local coordinate frame
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           // reset mean free path counter
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 

Generated on 28 Jun 2015 for BDSIM by  doxygen 1.4.7