/home/bes3soft/bes3soft/Boss/7.0.2/dist/7.0.2/Generator/BesEvtGen/BesEvtGen-00-03-58/src/EvtGen/EvtGenModels/EvtVubHybrid.cc

Go to the documentation of this file.
00001 //---------------------------------------------------------------------------
00002 //
00003 // Environment:
00004 //      This software is part of the EvtGen package developed jointly
00005 //      for the BaBar and CLEO collaborations.  If you use all or part
00006 //      of it, please give an appropriate acknowledgement.
00007 //
00008 // Copyright Information:
00009 //      Copyright (C) 1998      Caltech, UCSB
00010 //
00011 // Module: EvtVubHybrid.cc
00012 //
00013 // Description: Routine to decay a particle according to phase space. 
00014 //
00015 // Modification history:
00016 //
00017 //   Jochen Dingfelder February 1, 2005  Created Module as update of the
00018 //                                       original module EvtVub by Sven Menke 
00019 //---------------------------------------------------------------------------
00020 //
00021 #include "EvtGenBase/EvtPatches.hh"
00022 #include <stdlib.h>
00023 #include "EvtGenBase/EvtParticle.hh"
00024 #include "EvtGenBase/EvtGenKine.hh"
00025 #include "EvtGenBase/EvtPDL.hh"
00026 #include "EvtGenBase/EvtReport.hh"
00027 #include "EvtGenModels/EvtVubHybrid.hh"
00028 #include "EvtGenBase/EvtVector4R.hh"
00029 #include "EvtGenModels/EvtPFermi.hh"
00030 #include "EvtGenModels/EvtVubdGamma.hh"
00031 #include "CLHEP/Random/RandGeneral.h"
00032 #include "EvtGenBase/EvtRandom.hh"
00033 
00034 #include <string>
00035 #include <iostream>
00036 #include <fstream>
00037 
00038 typedef double HepDouble;
00039 //#include "CLHEP/config/CLHEP.h" //maqm add
00040 //#include "CLHEP/config/TemplateFunctions.h" //maqm add
00041         
00042 
00043 using std::ifstream;
00044 using std::cout;
00045 using std::endl;
00046 
00047 
00048 // _noHybrid will be set TRUE if the DECAY.DEC file has no binning or weights
00049 // _storeQplus should alwasy be TRUE: writes out Fermi motion parameter
00050 
00051 EvtVubHybrid::EvtVubHybrid() 
00052   : _noHybrid(false), _storeQplus(true),
00053     _mb(4.62), _a(2.27), _alphas(0.22), _dGMax(3.),
00054     _nbins_mX(0), _nbins_q2(0), _nbins_El(0), _nbins(0),
00055     _masscut(0.28), _bins_mX(0), _bins_q2(0), _bins_El(0),
00056     _weights(0), _dGamma(0)
00057 {}
00058 
00059 EvtVubHybrid::~EvtVubHybrid() {
00060   delete _dGamma;
00061   delete [] _bins_mX;
00062   delete [] _bins_q2;
00063   delete [] _bins_El;
00064   delete [] _weights;
00065 
00066 }
00067 
00068 void EvtVubHybrid::getName(std::string& model_name){
00069 
00070   model_name="VUBHYBRID";     
00071 
00072 }
00073 
00074 EvtDecayBase* EvtVubHybrid::clone(){
00075 
00076   return new EvtVubHybrid;
00077 
00078 }
00079 
00080 void EvtVubHybrid::init(){
00081 
00082   // check that there are at least 3 arguments
00083   if (getNArg() < EvtVubHybrid::nParameters) {
00084     report(ERROR,"EvtVubHybrid") << "EvtVub generator expected "
00085                                  << "at least " << EvtVubHybrid::nParameters
00086                                  << " arguments but found: " << getNArg()
00087                                  << "\nWill terminate execution!"<<endl;
00088     ::abort(); 
00089   } else if (getNArg() == EvtVubHybrid::nParameters) {
00090     report(WARNING,"EvtVubHybrid") << "EvtVub: generate B -> Xu l nu events " 
00091                                    << "without using the hybrid reweighting." 
00092                                    << endl;
00093     _noHybrid = true;
00094   } else if (getNArg() < EvtVubHybrid::nParameters+EvtVubHybrid::nVariables) {
00095      report(ERROR,"EvtVubHybrid") << "EvtVub could not read number of bins for "
00096                                   << "all variables used in the reweighting\n"
00097                                   << "Will terminate execution!" << endl;
00098      ::abort();    
00099   }
00100 
00101   // check that there are 3 daughters
00102   checkNDaug(3);
00103 
00104   // read minimum required parameters from decay.dec
00105   _mb     = getArg(0);
00106   _a      = getArg(1);
00107   _alphas = getArg(2);
00108 
00109   // the maximum dGamma*p2 value depends on alpha_s only:
00110   const double dGMax0 = 3.;
00111   _dGMax = 0.21344+8.905*_alphas;
00112   if ( _dGMax < dGMax0 ) _dGMax = dGMax0;
00113 
00114   // for the Fermi Motion we need a B-Meson mass - but it's not critical
00115   // to get an exact value; in order to stay in the phase space for
00116   // B+- and B0 use the smaller mass
00117   
00118   static double mB0 = EvtPDL::getMaxMass(EvtPDL::getId("B0"));
00119   static double mBP = EvtPDL::getMaxMass(EvtPDL::getId("B+"));
00120   static double mB = (mB0<mBP?mB0:mBP);
00121   
00122   const double xlow = -_mb;
00123   const double xhigh = mB-_mb;
00124   const int aSize = 10000;
00125 
00126   EvtPFermi pFermi(_a,mB,_mb);
00127   // pf is the cumulative distribution normalized to 1.
00128   _pf.resize(aSize);
00129   for(int i=0;i<aSize;i++){
00130     double kplus = xlow + (double)(i+0.5)/((double)aSize)*(xhigh-xlow);
00131     if ( i== 0 )
00132       _pf[i] = pFermi.getFPFermi(kplus);
00133     else
00134       _pf[i] = _pf[i-1] + pFermi.getFPFermi(kplus);
00135   }
00136   for (int i=0; i<_pf.size(); i++) _pf[i]/=_pf[_pf.size()-1];
00137 
00138   _dGamma = new EvtVubdGamma(_alphas);
00139   
00140   if (_noHybrid) return;        // Without hybrid weighting, nothing else to do
00141 
00142   _nbins_mX = abs((int)getArg(3));
00143   _nbins_q2 = abs((int)getArg(4));
00144   _nbins_El = abs((int)getArg(5));
00145 
00146   int nextArg = EvtVubHybrid::nParameters + EvtVubHybrid::nVariables;
00147 
00148   _nbins = _nbins_mX*_nbins_q2*_nbins_El;       // Binning of weight table
00149 
00150   int expectArgs = nextArg + _nbins_mX +_nbins_q2 + _nbins_El + _nbins;
00151 
00152   if (getNArg() < expectArgs) {
00153     report(ERROR,"EvtVubHybrid")
00154       << " finds " << getNArg() << " arguments, expected " << expectArgs
00155       << ".  Something is wrong with the tables of weights or thresholds."
00156       << "\nWill terminate execution!" << endl;
00157     ::abort();        
00158   }
00159 
00160   // read bin boundaries from decay.dec
00161   int i;
00162 
00163   _bins_mX  = new double[_nbins_mX];
00164   for (i = 0; i < _nbins_mX; i++,nextArg++) {
00165     _bins_mX[i] = getArg(nextArg);
00166   }
00167   _masscut = _bins_mX[0];
00168 
00169   _bins_q2  = new double[_nbins_q2];
00170   for (i = 0; i < _nbins_q2; i++,nextArg++) {
00171     _bins_q2[i] = getArg(nextArg);    
00172   }
00173 
00174   _bins_El  = new double[_nbins_El];
00175   for (i = 0; i < _nbins_El; i++,nextArg++) {
00176     _bins_El[i] = getArg(nextArg);    
00177   }
00178     
00179   // read in weights (and rescale to range 0..1)
00180   readWeights(nextArg); 
00181 }
00182 
00183 void EvtVubHybrid::initProbMax(){
00184   noProbMax();
00185 }
00186 
00187 void EvtVubHybrid::decay( EvtParticle *p ){
00188 
00189   int j;
00190   // B+ -> u-bar specflav l+ nu
00191   
00192   EvtParticle *xuhad, *lepton, *neutrino;
00193   EvtVector4R p4;
00194   // R. Faccini 21/02/03
00195   // move the reweighting up , before also shooting the fermi distribution
00196   double x,z,p2;
00197   double sh=0.0;
00198   double mB,ml,xlow,xhigh,qplus;
00199   double El=0.0;
00200   double Eh=0.0;
00201   double kplus;
00202   double q2, mX;
00203 
00204   const double lp2epsilon=-10;
00205   bool rew(true);
00206   while(rew){
00207     
00208     p->initializePhaseSpace(getNDaug(),getDaugs());
00209     
00210     xuhad=p->getDaug(0);
00211     lepton=p->getDaug(1);
00212     neutrino=p->getDaug(2);
00213     
00214     mB = p->mass();
00215     ml = lepton->mass();
00216     
00217     xlow = -_mb;
00218     xhigh = mB-_mb;    
00219     
00220     // Fermi motion does not need to be computed inside the
00221     // tryit loop as m_b in Gamma0 does not need to be replaced by (m_b+kplus).
00222     // The difference however should be of the Order (lambda/m_b)^2 which is
00223     // beyond the considered orders in the paper anyway ...
00224     
00225     // for alpha_S = 0 and a mass cut on X_u not all values of kplus are 
00226     // possible. The maximum value is mB/2-_mb + sqrt(mB^2/4-_masscut^2)
00227     kplus = 2*xhigh;
00228     
00229     while( kplus >= xhigh || kplus <= xlow 
00230            || (_alphas == 0 && kplus >= mB/2-_mb 
00231                + sqrt(mB*mB/4-_masscut*_masscut))) {
00232       kplus = findPFermi(); //_pFermi->shoot();
00233       kplus = xlow + kplus*(xhigh-xlow);
00234     }
00235     qplus = mB-_mb-kplus;
00236     if( (mB-qplus)/2.<=ml) continue;
00237    
00238     int tryit = 1;
00239     while (tryit) {
00240       
00241       x = EvtRandom::Flat();
00242       z = EvtRandom::Flat(0,2);
00243       p2=EvtRandom::Flat();
00244       p2 = pow(10,lp2epsilon*p2);
00245       
00246       El = x*(mB-qplus)/2;
00247       if ( El > ml && El < mB/2) {
00248         
00249         Eh = z*(mB-qplus)/2+qplus;
00250         if ( Eh > 0 && Eh < mB ) {
00251           
00252           sh = p2*pow(mB-qplus,2)+2*qplus*(Eh-qplus)+qplus*qplus;
00253           if ( sh > _masscut*_masscut
00254                && mB*mB + sh - 2*mB*Eh > ml*ml) {
00255             
00256             double xran = EvtRandom::Flat();
00257             
00258             double y = _dGamma->getdGdxdzdp(x,z,p2)/_dGMax*p2;
00259             
00260             if ( y > 1 ) report(WARNING,"EvtVubHybrid")
00261               <<"EvtVubHybrid decay probability > 1 found: " << y << endl;
00262             if ( y >= xran ) tryit = 0;
00263           }
00264         }
00265       }
00266     }
00267 
00268     // compute all kinematic variables needed for reweighting (J. Dingfelder)
00269     mX = sqrt(sh);
00270     q2 = mB*mB + sh - 2*mB*Eh;
00271 
00272     // Reweighting in bins of mX, q2, El (J. Dingfelder)
00273     if (_nbins>0) {
00274       double xran1 = EvtRandom::Flat();
00275       double w = 1.0;
00276       if (!_noHybrid) w = getWeight(mX, q2, El); 
00277       if ( w >= xran1 ) rew = false;
00278     } 
00279     else {
00280       rew = false;
00281     }
00282   }
00283 
00284   // o.k. we have the three kineamtic variables 
00285   // now calculate a flat cos Theta_H [-1,1] distribution of the 
00286   // hadron flight direction w.r.t the B flight direction 
00287   // because the B is a scalar and should decay isotropic.
00288   // Then chose a flat Phi_H [0,2Pi] w.r.t the B flight direction 
00289   // and and a flat Phi_L [0,2Pi] in the W restframe w.r.t the 
00290   // W flight direction.
00291 
00292   double ctH = EvtRandom::Flat(-1,1);
00293   double phH = EvtRandom::Flat(0,2*M_PI);
00294   double phL = EvtRandom::Flat(0,2*M_PI);
00295 
00296   // now compute the four vectors in the B Meson restframe
00297     
00298   double ptmp,sttmp;
00299   // calculate the hadron 4 vector in the B Meson restframe
00300 
00301   sttmp = sqrt(1-ctH*ctH);
00302   ptmp = sqrt(Eh*Eh-sh);
00303   double pHB[4] = {Eh,ptmp*sttmp*cos(phH),ptmp*sttmp*sin(phH),ptmp*ctH};
00304   p4.set(pHB[0],pHB[1],pHB[2],pHB[3]);
00305   xuhad->init( getDaug(0), p4);
00306 
00307   if (_storeQplus ) {
00308     // cludge to store the hidden parameter q+ with the decay; 
00309     // the lifetime of the Xu is abused for this purpose.
00310     // tau = 1 ps corresponds to ctau = 0.3 mm -> in order to
00311     // stay well below BaBars sensitivity we take q+/(10000 GeV) which 
00312     // goes up to 0.0005 in the most extreme cases as ctau in mm.
00313     // To extract q+ back from the StdHepTrk its necessary to get
00314     // delta_ctau = Xu->anyDaughter->getVertexTime()-Xu->getVertexTime()
00315     // where these pseudo calls refere to the StdHep time stored at
00316     // the production vertex in the lab for each particle. The boost 
00317     // has to be reversed and the result is:
00318     //
00319     // q+ = delta_ctau * 10000 GeV/mm * Mass_Xu/Energy_Xu     
00320     //
00321     xuhad->setLifetime(qplus/10000.);
00322   }
00323 
00324   // calculate the W 4 vector in the B Meson restrframe
00325 
00326   double apWB = ptmp;
00327   double pWB[4] = {mB-Eh,-pHB[1],-pHB[2],-pHB[3]};
00328 
00329   // first go in the W restframe and calculate the lepton and
00330   // the neutrino in the W frame
00331 
00332   double mW2   = mB*mB + sh - 2*mB*Eh;
00333   double beta  = ptmp/pWB[0];
00334   double gamma = pWB[0]/sqrt(mW2);
00335 
00336   double pLW[4];
00337     
00338   ptmp = (mW2-ml*ml)/2/sqrt(mW2);
00339   pLW[0] = sqrt(ml*ml + ptmp*ptmp);
00340 
00341   double ctL = (El - gamma*pLW[0])/beta/gamma/ptmp;
00342   if ( ctL < -1 ) ctL = -1;
00343   if ( ctL >  1 ) ctL =  1;
00344   sttmp = sqrt(1-ctL*ctL);
00345 
00346   // eX' = eZ x eW
00347   double xW[3] = {-pWB[2],pWB[1],0};
00348   // eZ' = eW
00349   double zW[3] = {pWB[1]/apWB,pWB[2]/apWB,pWB[3]/apWB};
00350   
00351   double lx = sqrt(xW[0]*xW[0]+xW[1]*xW[1]);
00352   for (j=0;j<2;j++) 
00353     xW[j] /= lx;
00354 
00355   // eY' = eZ' x eX'
00356   double yW[3] = {-pWB[1]*pWB[3],-pWB[2]*pWB[3],pWB[1]*pWB[1]+pWB[2]*pWB[2]};
00357   double ly = sqrt(yW[0]*yW[0]+yW[1]*yW[1]+yW[2]*yW[2]);
00358   for (j=0;j<3;j++) 
00359     yW[j] /= ly;
00360 
00361   // p_lep = |p_lep| * (  sin(Theta) * cos(Phi) * eX'
00362   //                    + sin(Theta) * sin(Phi) * eY'
00363   //                    + cos(Theta) *            eZ')
00364   for (j=0;j<3;j++)
00365     pLW[j+1] = sttmp*cos(phL)*ptmp*xW[j] 
00366       +        sttmp*sin(phL)*ptmp*yW[j]
00367       +          ctL         *ptmp*zW[j];
00368 
00369   double apLW = ptmp;
00370   // calculate the neutrino 4 vector in the W restframe
00371   //double pNW[4] = {sqrt(mW2)-pLW[0],-pLW[1],-pLW[2],-pLW[3]};
00372     
00373   // boost them back in the B Meson restframe
00374   
00375   double appLB = beta*gamma*pLW[0] + gamma*ctL*apLW;
00376  
00377   ptmp = sqrt(El*El-ml*ml);
00378   double ctLL = appLB/ptmp;
00379 
00380   if ( ctLL >  1 ) ctLL =  1;
00381   if ( ctLL < -1 ) ctLL = -1;
00382     
00383   double pLB[4] = {El,0,0,0};
00384   double pNB[4] = {pWB[0]-El,0,0,0};
00385 
00386   for (j=1;j<4;j++) {
00387     pLB[j] = pLW[j] + (ctLL*ptmp - ctL*apLW)/apWB*pWB[j];
00388     pNB[j] = pWB[j] - pLB[j];
00389   }
00390 
00391   p4.set(pLB[0],pLB[1],pLB[2],pLB[3]);
00392   lepton->init( getDaug(1), p4);
00393 
00394   p4.set(pNB[0],pNB[1],pNB[2],pNB[3]);
00395   neutrino->init( getDaug(2), p4);
00396 
00397   return ;
00398 }
00399 
00400 
00401 double EvtVubHybrid::findPFermi() {
00402 
00403   double ranNum=EvtRandom::Flat();
00404   double oOverBins= 1.0/(float(_pf.size()));
00405   int nBinsBelow = 0;     // largest k such that I[k] is known to be <= rand
00406   int nBinsAbove = _pf.size();  // largest k such that I[k] is known to be >  rand
00407   int middle;
00408   
00409   while (nBinsAbove > nBinsBelow+1) {
00410     middle = (nBinsAbove + nBinsBelow+1)>>1;
00411     if (ranNum >= _pf[middle]) {
00412       nBinsBelow = middle;
00413     } else {
00414       nBinsAbove = middle;
00415     }
00416   } 
00417 
00418   double bSize = _pf[nBinsAbove] - _pf[nBinsBelow];
00419   // binMeasure is always aProbFunc[nBinsBelow], 
00420   
00421   if ( bSize == 0 ) { 
00422     // rand lies right in a bin of measure 0.  Simply return the center
00423     // of the range of that bin.  (Any value between k/N and (k+1)/N is 
00424     // equally good, in this rare case.)
00425     return (nBinsBelow + .5) * oOverBins;
00426   }
00427   
00428   HepDouble bFract = (ranNum - _pf[nBinsBelow]) / bSize;
00429   
00430   return (nBinsBelow + bFract) * oOverBins;
00431 
00432 } 
00433 
00434 
00435 double EvtVubHybrid::getWeight(double mX, double q2, double El) {
00436 
00437   int ibin_mX = -1;
00438   int ibin_q2 = -1;
00439   int ibin_El = -1;
00440 
00441   for (int i = 0; i < _nbins_mX; i++) {
00442     if (mX >= _bins_mX[i]) ibin_mX = i;
00443   }
00444   for (int i = 0; i < _nbins_q2; i++) {
00445     if (q2 >= _bins_q2[i]) ibin_q2 = i;
00446   }
00447   for (int i = 0; i < _nbins_El; i++) {
00448     if (El >= _bins_El[i]) ibin_El = i;
00449   }
00450   int ibin = ibin_mX + ibin_q2*_nbins_mX + ibin_El*_nbins_mX*_nbins_q2;
00451 
00452   if ( (ibin_mX < 0) || (ibin_q2 < 0) || (ibin_El < 0) ) {
00453     report(ERROR,"EvtVubHybrid") << "Cannot determine hybrid weight "
00454                                  << "for this event " 
00455                                  << "-> assign weight = 0" << endl;
00456     return 0.0;
00457   }
00458 
00459   return _weights[ibin];
00460 }
00461 
00462 
00463 void EvtVubHybrid::readWeights(int startArg) {
00464   _weights  = new double[_nbins];
00465 
00466   double maxw = 0.0;
00467   for (int i = 0; i < _nbins; i++, startArg++) {
00468     _weights[i] = getArg(startArg);
00469     if (_weights[i] > maxw) maxw = _weights[i];
00470   }
00471 
00472   if (maxw == 0) {
00473     report(ERROR,"EvtVubHybrid") << "EvtVub generator expected at least one " 
00474                                  << " weight > 0, but found none! " 
00475                                  << "Will terminate execution!"<<endl;
00476     ::abort();
00477   }
00478 
00479   // rescale weights (to be in range 0..1)
00480   for (int i = 0; i < _nbins; i++) {
00481     _weights[i] /= maxw;
00482   }
00483 }

Generated on Tue Nov 29 23:12:23 2016 for BOSS_7.0.2 by  doxygen 1.4.7