Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

brems.cxx

Go to the documentation of this file.
00001 // -*- C++ -*-  $Id: brems.cxx,v 1.1 2000/09/01 20:20:18 burnett Exp $
00002 //
00003 // This file is part of Gismo 2
00004 //
00005 // created: 1-Dec-1991 T. Burnett
00006 
00007 // Contents -------------------------------------------------------------
00008 //
00009 //   void EGS::brems(PEGSData&)
00010 //
00011 // End ------------------------------------------------------------------
00012 
00013 #include "EGS.h"
00014 #include "PEGSData.h"
00015 #include "Random.h"
00016 
00017 inline int  ilog2(float x)
00018 {
00019   return (int)(1.44269*log(x));  //  "1.44269=1/LN(2)"
00020 }
00021 
00022 static float ai2ln2=0.7213475; //1./(2.*alog(2.))
00023 
00024 #define MAXPWR2I 50
00025 float pwr2i[MAXPWR2I]={0};
00026 
00027 // used below in calculation of brem angle
00028 static double set_brem_rejection_function(double input, double RJARG1, 
00029                                           double RJARG2, double RJARG3, double ZTARG, double ESEDEI);
00030 
00031 
00032 void EGS::brems(const PEGSData & mat)
00033 {
00034    if (pwr2i[0]==0){float p=2.; for(int i=0;i<MAXPWR2I;i++)pwr2i[i]=(p/=2.);}
00035 
00036    float eie = this->e;  // incoming electron/positron energy
00037    //******************************************************************
00038    //   for electron energy greater than 5.0 mev, the bethe-heitler
00039    //   cross section is employed.
00040    //******************************************************************
00041 
00042    //   decide which distribution to use (b-h coulomb corrected is
00043    //   used from 50 to 20000 mev, b-h is used 1.5 to 50 mev)
00044 
00045    int lvx=1, lvl0=3, lvl;
00046    if (eie < 50.0){lvx=0;lvl0=0;}
00047 
00048    //   the method of butcher and messel for sampling a class of
00049    //   factorizable frequency distributions is used.
00050    //   our 'br' variable is the same as their 'epsilon' variable.
00051    //   see butcher and messel,nucl.phys.,vol.20,pp23,24.
00052    //   compute number of subdistributions needed to produce photons
00053    //   of minimum discrete transport enrgy ap, in case the (1-br)/br
00054    //   part of the distribution is used.
00055 
00056    float abrems=float(ilog2( eie/mat.ap));
00057 
00058    //   ilog2(x) is that integer function of x such that . . .
00059    //   2**(ilog2(x)-1) .le. x .lt. 2**(ilog2(x))
00060 
00061    float esg, ese, br;
00062 
00063    for(;;)
00064    {
00065        //various rejections can cause resample
00066        //   decide whether to sample from the (1-br)/br or the 2*br part
00067        //   of the distribution.
00068 
00069        float rnno06 = Random::flat();
00070        if (0.5 < ((abrems*mat.alphi(lvx)+0.5)*rnno06))
00071        {
00072            //   use the (1-br)/br part.  which subdistribution?
00073            float rnno07 = Random::flat();
00074            int idistr =(int)(abrems*rnno07);
00075 
00076            //   this chooses idistr at random from the set
00077            //   (0,1,2, . . . , nbrems - 1 )
00078            float p= pwr2i[idistr];
00079            //   select screening rejection function
00080            //   lvl=0    uncoulomb corrected     a(delta)
00081            //   lvl=1    uncoulomb corrected     b(delta)
00082            //   lvl=2    uncoulomb corrected     c(delta)
00083            //   lvl=3      coulomb corrected     a(delta)
00084            //   lvl=4      coulomb corrected     b(delta)
00085            //   lvl=5      coulomb corrected     c(delta)
00086            lvl=lvl0;
00087 
00088            //   use a(delta), either born or coulomb corrected, depending on
00089            //   whether lvl has been previously set to 0 or 3.
00090            //   all subdistributions are sampled by first sampling from
00091            //            (1./log(2.))*(1.-br)/br     if 0.5 .le. br .le. 1.
00092            //            1./log(2.)                  if   br.lt. 0.5
00093            //   and then taking br = br*p
00094            //   ai2ln2 is actually 1./(2.*log(2.)), which is the probability
00095            //   that br is less than 0.5 in the elementary distribution above.
00096            float rnno08 = Random::flat();
00097 
00098            if (rnno08>=ai2ln2)
00099            {
00100                for(;;)
00101                {  float rnno09 = Random::flat(), //if rejected for subdistribution
00102                         rnno10 = Random::flat(),
00103                         rnno11 = Random::flat(),
00104                         h=std::max(rnno10,rnno11);
00105                   br=1.0-0.5*h;
00106 
00107                   if ( rnno09 <= 0.5/br) break;   //rejection condition
00108                }
00109 
00110            }   //end br.ge.0.5 part
00111            else
00112            {
00113                //sample br.lt.0.5 part
00114                float rnno12 = Random::flat();
00115                br=rnno12*0.5;
00116            } //end of br.lt.0.5 part
00117 
00118            //   product energy fraction chosen
00119            br=br*p;
00120        } //end (1-br)/br part
00121        else
00122        {
00123           //use the 2*br part
00124            float rnno13 = Random::flat();
00125            float rnno14 = Random::flat();
00126            br=std::max(rnno13,rnno14);
00127            lvl=lvl0+1; //use b(delta) for screening function
00128        } //end of 2*br part of distribution
00129 
00130        //   energy of new photon
00131 
00132        esg=eie*br; //energy of secondary gamma
00133 
00134        //   ap=0.256 mev  ---  rm=0.511 mev
00135        //   ap is selected in the routine pegs.
00136        //   minimum hardness requirement, corresponding to lower bound
00137        //   choice for total cross section integral
00138 
00139        if (esg < mat.ap )continue;
00140 
00141        ese=(double)eie-(double)esg; //precise energy of secondary 'electron'
00142 
00143        //   the electron must have a minimum energy equal to 0.511 mev
00144 
00145        if (ese < rm ) continue;
00146 
00147        //   delta=136.0*exp(zg)*rm*ee/(e*(1.0-ee))
00148        //        =delcm*ee/(e*(1.0-ee))=delcm*del
00149        //   where e=electron incident energy(MeV), and ee=(photon energy)/e
00150        //   zg is defined in the program shinp, and is a weighted average
00151        //   of log(z**(-1./3.))  over the various types of atoms in the
00152        //   molecule (Butcher and Messel, op.cit., p.17-19,22-24).
00153 
00154        float del = br/ese;
00155 
00156        float rejf = mat.screening(del, lvx, lvl);
00157        if (rejf == 0) continue;
00158 
00159        float rnscrn = Random::flat(); //random number for screening rejection
00160        if (rnscrn <= rejf) break;
00161     }  //loop until value accepted
00162 
00163     this->e = ese;    // change electron or positron energy, not angle
00164 
00165     //now, get photon's direction 
00166 
00167     double theta;
00168     
00169     //set IBRDST to 0 for EGS4 default rm/eie;
00170     //set IBRDST to 1 for Koch & Motz angle distribution
00171     //Adapted from Alex F. Bielajew's paper
00172     //"Improved bremsstrahlung photon angular sampleing
00173     //in the EGS4 code system"  Nov, 14, 1989
00174     
00175     int IBRDST = 1; //should change to #ifdef KOCHnMOTZ 
00176     if (IBRDST == 0){
00177         theta = rm / eie;
00178     }
00179     if (IBRDST == 1){
00180         double rm2,test,HPI,ZTARG,TTEIE,TTESE,ESEDEI,Y2MAX;
00181         double RJARG1,RJARG2,RJARG3,REJMIN,REJMID,REJMAX,REJTOP;
00182         double Y2TST,REJTST,RTEST;
00183                 
00184         rm2 = 0.51100340; //ELECTRON REST MASS MEV/CC
00185         HPI = 3.141593;
00186         ZTARG = (double) mat.hzbrang(); //((1/111)*zeff**(1/3))**2
00187         TTEIE = (double) eie / rm2; //incoming e- energy in rest mass units
00188         TTESE = (double) ese / rm2; //outgoing e- energy in rest mass units
00189         ESEDEI = TTESE/TTEIE;
00190         Y2MAX = pow((HPI*TTEIE),2);
00191         RJARG1 = (1.0+pow(ESEDEI,2));
00192         RJARG2 = 3.0 * RJARG1 - 2.0*ESEDEI;
00193         RJARG3 = pow(((1.0-ESEDEI)/(2.0*TTEIE*ESEDEI)),2);
00194         REJMIN = set_brem_rejection_function(0.0E0,RJARG1,RJARG2,RJARG3,ZTARG,ESEDEI);
00195         REJMID = set_brem_rejection_function(1.0E0,RJARG1,RJARG2,RJARG3,ZTARG,ESEDEI);
00196         REJMAX = set_brem_rejection_function(Y2MAX,RJARG1,RJARG2,RJARG3,ZTARG,ESEDEI);
00197         test = REJMIN;
00198         if (test <= REJMID) test = REJMID;
00199         if (test <= REJMAX) test = REJMAX;
00200         REJTOP = test;
00201         do {
00202             Y2TST = (double) Random::flat();
00203             Y2TST = Y2TST/(1.0-Y2TST+1.0/Y2MAX);
00204             REJTST = set_brem_rejection_function(Y2TST,RJARG1,RJARG2,RJARG3,ZTARG,ESEDEI);
00205             RTEST = (double) Random::flat();
00206         } while(RTEST > (REJTST/REJTOP));
00207         if (Y2TST < 0){ //error protection
00208             Y2TST = 0;
00209         }
00210         
00211         theta = sqrt(Y2TST)/TTEIE;
00212         //      if (theta > 3.1415926) theta = 3.141592; //to be safe
00213         //      if (theta < 0) theta = 0; //to be safe
00214     }
00215     
00216     EGS *photon = new EGS(this);  // create the photon
00217     photon->iq = 0;
00218     photon->e = esg;
00219     photon->rotate( cos(theta), Random::flat(2.*M_PI) );
00220 
00221 } // end of PDT::brems
00222 
00223 static double set_brem_rejection_function(double input, double RJARG1, 
00224                                           double RJARG2, double RJARG3, double ZTARG, double ESEDEI)
00225 { //harrison
00226     double Y2TST1, result;
00227     Y2TST1 = pow((1.0 + input),2);
00228     result = (4.0 + log(RJARG3+ZTARG/Y2TST1))*(4.0*ESEDEI*input/Y2TST1-RJARG1)+RJARG2;
00229     return result;
00230 }
00231 

Generated at Mon Nov 26 18:18:31 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000