LCOV - code coverage report
Current view: top level - TEvtGen/EvtGen/EvtGenModels - EvtVub.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 178 0.0 %
Date: 2016-06-14 17:26:59 Functions: 0 9 0.0 %

          Line data    Source code
       1             : //--------------------------------------------------------------------------
       2             : //
       3             : // Environment:
       4             : //      This software is part of the EvtGen package developed jointly
       5             : //      for the BaBar and CLEO collaborations.  If you use all or part
       6             : //      of it, please give an appropriate acknowledgement.
       7             : //
       8             : // Copyright Information:
       9             : //      Copyright (C) 1998      Caltech, UCSB
      10             : //
      11             : // Module: EvtVub.cc
      12             : //
      13             : // Description: Routine to decay a particle according th phase space 
      14             : //
      15             : // Modification history:
      16             : //
      17             : //    Sven Menke       January 17, 2001       Module created
      18             : //
      19             : //------------------------------------------------------------------------
      20             : //
      21             : #include "EvtGenBase/EvtPatches.hh"
      22             : #include <stdlib.h>
      23             : #include "EvtGenBase/EvtParticle.hh"
      24             : #include "EvtGenBase/EvtGenKine.hh"
      25             : #include "EvtGenBase/EvtPDL.hh"
      26             : #include "EvtGenBase/EvtReport.hh"
      27             : #include "EvtGenModels/EvtVub.hh"
      28             : #include <string>
      29             : #include "EvtGenBase/EvtVector4R.hh"
      30             : #include "EvtGenModels/EvtPFermi.hh"
      31             : #include "EvtGenModels/EvtVubdGamma.hh"
      32             : #include "EvtGenBase/EvtRandom.hh"
      33             : using std::endl;
      34             : 
      35           0 : EvtVub::~EvtVub() {
      36           0 :   if (_dGamma) delete _dGamma;
      37           0 :   if (_masses) delete [] _masses;
      38           0 :   if (_weights) delete [] _weights;
      39           0 : }
      40             : 
      41             : std::string EvtVub::getName(){
      42             : 
      43           0 :   return "VUB";     
      44             : 
      45             : }
      46             : 
      47             : EvtDecayBase* EvtVub::clone(){
      48             : 
      49           0 :   return new EvtVub;
      50             : 
      51           0 : }
      52             : 
      53             : 
      54             : void EvtVub::init(){
      55             : 
      56             :   // check that there are at least 6 arguments
      57             : 
      58           0 :   if (getNArg()<6) {
      59             : 
      60           0 :     report(Severity::Error,"EvtGen") << "EvtVub generator expected "
      61           0 :                            << " at least 6 arguments (mb,a,alpha_s,Nbins,m1,w1,...) but found: "
      62           0 :                            <<getNArg()<<endl;
      63           0 :     report(Severity::Error,"EvtGen") << "Will terminate execution!"<<endl;
      64           0 :     ::abort();
      65             : 
      66             :   }
      67             :   
      68           0 :   _mb           = getArg(0);
      69           0 :   _a            = getArg(1);
      70           0 :   _alphas       = getArg(2);
      71           0 :   _nbins        = abs((int)getArg(3));
      72           0 :   _storeQplus   = (getArg(3)<0?1:0);
      73           0 :   _masses       = new double[_nbins];
      74           0 :   _weights      = new double[_nbins];
      75             :  
      76           0 :   if (getNArg()-4 != 2*_nbins) {
      77           0 :     report(Severity::Error,"EvtGen") << "EvtVub generator expected " 
      78           0 :                            << _nbins << " masses and weights but found: "
      79           0 :                            <<(getNArg()-4)/2 <<endl;
      80           0 :     report(Severity::Error,"EvtGen") << "Will terminate execution!"<<endl;
      81           0 :     ::abort();
      82             :   }
      83             :   int i,j = 4;
      84             :   double maxw = 0.;
      85           0 :   for (i=0;i<_nbins;i++) {
      86           0 :     _masses[i] = getArg(j++);
      87           0 :     if (i>0 && _masses[i] <= _masses[i-1]) {
      88           0 :       report(Severity::Error,"EvtGen") << "EvtVub generator expected " 
      89           0 :                              << " mass bins in ascending order!"
      90           0 :                              << "Will terminate execution!"<<endl;
      91           0 :       ::abort();
      92             :     }
      93           0 :     _weights[i] = getArg(j++);
      94           0 :     if (_weights[i] < 0) {
      95           0 :       report(Severity::Error,"EvtGen") << "EvtVub generator expected " 
      96           0 :                              << " weights >= 0, but found: " 
      97           0 :                              <<_weights[i] <<endl;
      98           0 :       report(Severity::Error,"EvtGen") << "Will terminate execution!"<<endl;
      99           0 :       ::abort();
     100             :     }
     101           0 :     if ( _weights[i] > maxw ) maxw = _weights[i];
     102             :   }
     103           0 :   if (maxw == 0) {
     104           0 :     report(Severity::Error,"EvtGen") << "EvtVub generator expected at least one " 
     105           0 :                            << " weight > 0, but found none! " 
     106           0 :                            << "Will terminate execution!"<<endl;
     107           0 :     ::abort();
     108             :   }
     109           0 :   for (i=0;i<_nbins;i++) _weights[i]/=maxw;
     110             : 
     111             :   // the maximum dGamma*p2 value depends on alpha_s only:
     112             : 
     113             :   const double dGMax0 = 3.;
     114           0 :   _dGMax = 0.21344+8.905*_alphas;
     115           0 :   if ( _dGMax < dGMax0 ) _dGMax = dGMax0;
     116             : 
     117             :   // for the Fermi Motion we need a B-Meson mass - but it's not critical
     118             :   // to get an exact value; in order to stay in the phase space for
     119             :   // B+- and B0 use the smaller mass
     120             : 
     121           0 :   EvtId BP=EvtPDL::getId("B+");
     122           0 :   EvtId B0=EvtPDL::getId("B0");
     123             :   
     124           0 :   double mB0 = EvtPDL::getMaxMass(B0);
     125           0 :   double mBP = EvtPDL::getMaxMass(BP);
     126             : 
     127           0 :   double mB = (mB0<mBP?mB0:mBP);
     128             :   
     129           0 :   const double xlow = -_mb;
     130           0 :   const double xhigh = mB-_mb;
     131             :   const int aSize = 10000;
     132             : 
     133           0 :   EvtPFermi pFermi(_a,mB,_mb);
     134             :   // pf is the cumulative distribution
     135             :   // normalized to 1.
     136           0 :   _pf.resize(aSize);
     137           0 :   for(i=0;i<aSize;i++){
     138           0 :     double kplus = xlow + (double)(i+0.5)/((double)aSize)*(xhigh-xlow);
     139           0 :     if ( i== 0 )
     140           0 :       _pf[i] = pFermi.getFPFermi(kplus);
     141             :     else
     142           0 :       _pf[i] = _pf[i-1] + pFermi.getFPFermi(kplus);
     143           0 :   }
     144           0 :   for (size_t index=0; index<_pf.size(); index++) {
     145           0 :     _pf[index]/=_pf[_pf.size()-1];
     146             :   }
     147             : 
     148             :   //  static EvtHepRandomEngine myEngine;
     149             : 
     150             :   //  _pFermi = new RandGeneral(myEngine,pf,aSize,0);
     151           0 :   _dGamma = new EvtVubdGamma(_alphas);
     152             :   
     153             :   // check that there are 3 daughters
     154           0 :   checkNDaug(3);
     155           0 : }
     156             : 
     157             : void EvtVub::initProbMax(){
     158             : 
     159           0 :   noProbMax();
     160             : 
     161           0 : }
     162             : 
     163             : void EvtVub::decay( EvtParticle *p ){
     164             : 
     165             :   int j;
     166             :   // B+ -> u-bar specflav l+ nu
     167             :   
     168             :   EvtParticle *xuhad, *lepton, *neutrino;
     169           0 :   EvtVector4R p4;
     170             :   // R. Faccini 21/02/03
     171             :   // move the reweighting up , before also shooting the fermi distribution
     172           0 :   double x,z,p2;
     173             :   double sh=0.0;
     174             :   double mB,ml,xlow,xhigh,qplus;
     175             :   double El=0.0;
     176             :   double Eh=0.0;
     177             :   double kplus;
     178             :   const double lp2epsilon=-10;
     179             :   bool rew(true);
     180           0 :   while(rew){
     181             :     
     182           0 :     p->initializePhaseSpace(getNDaug(),getDaugs());
     183             :     
     184           0 :     xuhad=p->getDaug(0);
     185           0 :     lepton=p->getDaug(1);
     186           0 :     neutrino=p->getDaug(2);
     187             :     
     188           0 :     mB = p->mass();
     189           0 :     ml = lepton->mass();
     190             :     
     191           0 :     xlow = -_mb;
     192           0 :     xhigh = mB-_mb;    
     193             :     
     194             :     
     195             :     // Fermi motion does not need to be computed inside the
     196             :     // tryit loop as m_b in Gamma0 does not need to be replaced by (m_b+kplus).
     197             :     // The difference however should be of the Order (lambda/m_b)^2 which is
     198             :     // beyond the considered orders in the paper anyway ...
     199             :     
     200             :     // for alpha_S = 0 and a mass cut on X_u not all values of kplus are 
     201             :     // possible. The maximum value is mB/2-_mb + sqrt(mB^2/4-_masses[0]^2)
     202           0 :     kplus = 2*xhigh;
     203             :     
     204           0 :     while( kplus >= xhigh || kplus <= xlow 
     205           0 :            || (_alphas == 0 && kplus >= mB/2-_mb 
     206           0 :                + sqrt(mB*mB/4-_masses[0]*_masses[0]))) {
     207           0 :       kplus = findPFermi(); //_pFermi->shoot();
     208           0 :       kplus = xlow + kplus*(xhigh-xlow);
     209             :     }
     210           0 :     qplus = mB-_mb-kplus;
     211           0 :     if( (mB-qplus)/2.<=ml)continue;
     212             :    
     213             :     int tryit = 1;
     214           0 :     while (tryit) {
     215             :       
     216           0 :       x = EvtRandom::Flat();
     217           0 :       z = EvtRandom::Flat(0,2);
     218           0 :       p2=EvtRandom::Flat();
     219           0 :       p2 = pow(10.0,lp2epsilon*p2);
     220             :       
     221           0 :       El = x*(mB-qplus)/2;
     222           0 :       if ( El > ml && El < mB/2) {
     223             :         
     224           0 :         Eh = z*(mB-qplus)/2+qplus;
     225           0 :         if ( Eh > 0 && Eh < mB ) {
     226             :           
     227           0 :           sh = p2*pow(mB-qplus,2)+2*qplus*(Eh-qplus)+qplus*qplus;
     228           0 :           if ( sh > _masses[0]*_masses[0]
     229           0 :                && mB*mB + sh - 2*mB*Eh > ml*ml) {
     230             :             
     231           0 :             double xran = EvtRandom::Flat();
     232             :             
     233           0 :             double y = _dGamma->getdGdxdzdp(x,z,p2)/_dGMax*p2;
     234             :             
     235           0 :             if ( y > 1 ) report(Severity::Warning,"EvtGen")<<"EvtVub decay probability > 1 found: " << y << endl;
     236           0 :             if ( y >= xran ) tryit = 0;
     237           0 :           }
     238             :         }
     239             :       }
     240             :     }
     241             :     // reweight the Mx distribution
     242           0 :     if(_nbins>0){
     243           0 :       double xran1 = EvtRandom::Flat();
     244           0 :       double m = sqrt(sh);j=0;
     245           0 :       while ( j < _nbins && m > _masses[j] ) j++; 
     246           0 :       double w = _weights[j-1]; 
     247           0 :       if ( w >= xran1 ) rew = false;
     248           0 :     } else {
     249             :       rew = false;
     250             :     }
     251             :     
     252             :   }
     253             : 
     254             :   // o.k. we have the three kineamtic variables 
     255             :   // now calculate a flat cos Theta_H [-1,1] distribution of the 
     256             :   // hadron flight direction w.r.t the B flight direction 
     257             :   // because the B is a scalar and should decay isotropic.
     258             :   // Then chose a flat Phi_H [0,2Pi] w.r.t the B flight direction 
     259             :   // and and a flat Phi_L [0,2Pi] in the W restframe w.r.t the 
     260             :   // W flight direction.
     261             : 
     262           0 :   double ctH = EvtRandom::Flat(-1,1);
     263           0 :   double phH = EvtRandom::Flat(0,2*EvtConst::pi);
     264           0 :   double phL = EvtRandom::Flat(0,2*EvtConst::pi);
     265             : 
     266             :   // now compute the four vectors in the B Meson restframe
     267             :     
     268             :   double ptmp,sttmp;
     269             :   // calculate the hadron 4 vector in the B Meson restframe
     270             : 
     271           0 :   sttmp = sqrt(1-ctH*ctH);
     272           0 :   ptmp = sqrt(Eh*Eh-sh);
     273           0 :   double pHB[4] = {Eh,ptmp*sttmp*cos(phH),ptmp*sttmp*sin(phH),ptmp*ctH};
     274           0 :   p4.set(pHB[0],pHB[1],pHB[2],pHB[3]);
     275           0 :   xuhad->init( getDaug(0), p4);
     276             : 
     277           0 :   if (_storeQplus ) {
     278             :     // cludge to store the hidden parameter q+ with the decay; 
     279             :     // the lifetime of the Xu is abused for this purpose.
     280             :     // tau = 1 ps corresponds to ctau = 0.3 mm -> in order to
     281             :     // stay well below BaBars sensitivity we take q+/(10000 GeV) which 
     282             :     // goes up to 0.0005 in the most extreme cases as ctau in mm.
     283             :     // To extract q+ back from the StdHepTrk its necessary to get
     284             :     // delta_ctau = Xu->anyDaughter->getVertexTime()-Xu->getVertexTime()
     285             :     // where these pseudo calls refere to the StdHep time stored at
     286             :     // the production vertex in the lab for each particle. The boost 
     287             :     // has to be reversed and the result is:
     288             :     //
     289             :     // q+ = delta_ctau * 10000 GeV/mm * Mass_Xu/Energy_Xu     
     290             :     //
     291           0 :     xuhad->setLifetime(qplus/10000.);
     292           0 :   }
     293             : 
     294             :   // calculate the W 4 vector in the B Meson restrframe
     295             : 
     296             :   double apWB = ptmp;
     297           0 :   double pWB[4] = {mB-Eh,-pHB[1],-pHB[2],-pHB[3]};
     298             : 
     299             :   // first go in the W restframe and calculate the lepton and
     300             :   // the neutrino in the W frame
     301             : 
     302           0 :   double mW2   = mB*mB + sh - 2*mB*Eh;
     303           0 :   double beta  = ptmp/pWB[0];
     304           0 :   double gamma = pWB[0]/sqrt(mW2);
     305             : 
     306           0 :   double pLW[4];
     307             :     
     308           0 :   ptmp = (mW2-ml*ml)/2/sqrt(mW2);
     309           0 :   pLW[0] = sqrt(ml*ml + ptmp*ptmp);
     310             : 
     311           0 :   double ctL = (El - gamma*pLW[0])/beta/gamma/ptmp;
     312           0 :   if ( ctL < -1 ) ctL = -1;
     313           0 :   if ( ctL >  1 ) ctL =  1;
     314           0 :   sttmp = sqrt(1-ctL*ctL);
     315             : 
     316             :   // eX' = eZ x eW
     317           0 :   double xW[3] = {-pWB[2],pWB[1],0};
     318             :   // eZ' = eW
     319           0 :   double zW[3] = {pWB[1]/apWB,pWB[2]/apWB,pWB[3]/apWB};
     320             :   
     321           0 :   double lx = sqrt(xW[0]*xW[0]+xW[1]*xW[1]);
     322           0 :   for (j=0;j<2;j++) 
     323           0 :     xW[j] /= lx;
     324             : 
     325             :   // eY' = eZ' x eX'
     326           0 :   double yW[3] = {-pWB[1]*pWB[3],-pWB[2]*pWB[3],pWB[1]*pWB[1]+pWB[2]*pWB[2]};
     327           0 :   double ly = sqrt(yW[0]*yW[0]+yW[1]*yW[1]+yW[2]*yW[2]);
     328           0 :   for (j=0;j<3;j++) 
     329           0 :     yW[j] /= ly;
     330             : 
     331             :   // p_lep = |p_lep| * (  sin(Theta) * cos(Phi) * eX'
     332             :   //                    + sin(Theta) * sin(Phi) * eY'
     333             :   //                    + cos(Theta) *            eZ')
     334           0 :   for (j=0;j<3;j++)
     335           0 :     pLW[j+1] = sttmp*cos(phL)*ptmp*xW[j] 
     336           0 :       +        sttmp*sin(phL)*ptmp*yW[j]
     337           0 :       +          ctL         *ptmp*zW[j];
     338             : 
     339             :   double apLW = ptmp;
     340             :     
     341             :   // boost them back in the B Meson restframe  
     342           0 :   double appLB = beta*gamma*pLW[0] + gamma*ctL*apLW;
     343             :  
     344           0 :   ptmp = sqrt(El*El-ml*ml);
     345           0 :   double ctLL = appLB/ptmp;
     346             : 
     347           0 :   if ( ctLL >  1 ) ctLL =  1;
     348           0 :   if ( ctLL < -1 ) ctLL = -1;
     349             :     
     350           0 :   double pLB[4] = {El,0,0,0};
     351           0 :   double pNB[4] = {pWB[0]-El,0,0,0};
     352             : 
     353           0 :   for (j=1;j<4;j++) {
     354           0 :     pLB[j] = pLW[j] + (ctLL*ptmp - ctL*apLW)/apWB*pWB[j];
     355           0 :     pNB[j] = pWB[j] - pLB[j];
     356             :   }
     357             : 
     358           0 :   p4.set(pLB[0],pLB[1],pLB[2],pLB[3]);
     359           0 :   lepton->init( getDaug(1), p4);
     360             : 
     361           0 :   p4.set(pNB[0],pNB[1],pNB[2],pNB[3]);
     362           0 :   neutrino->init( getDaug(2), p4);
     363             : 
     364             :   return ;
     365           0 : }
     366             : 
     367             : 
     368             : double EvtVub::findPFermi() {
     369             : 
     370           0 :   double ranNum=EvtRandom::Flat();
     371           0 :   double oOverBins= 1.0/(float(_pf.size()));
     372             :   int nBinsBelow = 0;     // largest k such that I[k] is known to be <= rand
     373           0 :   int nBinsAbove = _pf.size();  // largest k such that I[k] is known to be >  rand
     374             :   int middle;
     375             :   
     376           0 :   while (nBinsAbove > nBinsBelow+1) {
     377           0 :     middle = (nBinsAbove + nBinsBelow+1)>>1;
     378           0 :     if (ranNum >= _pf[middle]) {
     379             :       nBinsBelow = middle;
     380           0 :     } else {
     381             :       nBinsAbove = middle;
     382             :     }
     383             :   } 
     384             : 
     385           0 :   double bSize = _pf[nBinsAbove] - _pf[nBinsBelow];
     386             :   // binMeasure is always aProbFunc[nBinsBelow], 
     387             :   
     388           0 :   if ( bSize == 0 ) { 
     389             :     // rand lies right in a bin of measure 0.  Simply return the center
     390             :     // of the range of that bin.  (Any value between k/N and (k+1)/N is 
     391             :     // equally good, in this rare case.)
     392           0 :     return (nBinsBelow + .5) * oOverBins;
     393             :   }
     394             :   
     395           0 :   double bFract = (ranNum - _pf[nBinsBelow]) / bSize;
     396             :   
     397           0 :   return (nBinsBelow + bFract) * oOverBins;
     398             : 
     399           0 : } 

Generated by: LCOV version 1.11