FastJet 3.0beta1
|
00001 //STARTHEADER 00002 // $Id: GhostedAreaSpec.cc 2294 2011-06-28 10:23:31Z salam $ 00003 // 00004 // Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam 00005 // 00006 //---------------------------------------------------------------------- 00007 // This file is part of FastJet. 00008 // 00009 // FastJet is free software; you can redistribute it and/or modify 00010 // it under the terms of the GNU General Public License as published by 00011 // the Free Software Foundation; either version 2 of the License, or 00012 // (at your option) any later version. 00013 // 00014 // The algorithms that underlie FastJet have required considerable 00015 // development and are described in hep-ph/0512210. If you use 00016 // FastJet as part of work towards a scientific publication, please 00017 // include a citation to the FastJet paper. 00018 // 00019 // FastJet is distributed in the hope that it will be useful, 00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 // GNU General Public License for more details. 00023 // 00024 // You should have received a copy of the GNU General Public License 00025 // along with FastJet; if not, write to the Free Software 00026 // Foundation, Inc.: 00027 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00028 //---------------------------------------------------------------------- 00029 //ENDHEADER 00030 00031 #include "fastjet/GhostedAreaSpec.hh" 00032 #include "fastjet/Error.hh" 00033 #include<iostream> 00034 #include<sstream> 00035 00036 using namespace std; 00037 00038 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh 00039 00040 BasicRandom<double> GhostedAreaSpec::_random_generator; 00041 00042 /// explicit constructor 00043 GhostedAreaSpec::GhostedAreaSpec( 00044 const Selector & selector, 00045 int repeat , 00046 double ghost_area , 00047 double grid_scatter , 00048 double kt_scatter , 00049 double mean_ghost_kt 00050 ): 00051 _repeat(repeat), 00052 _ghost_area(ghost_area), 00053 _grid_scatter(grid_scatter), 00054 _kt_scatter(kt_scatter), 00055 _mean_ghost_kt(mean_ghost_kt), 00056 _fj2_placement(false), 00057 _selector(selector), 00058 _actual_ghost_area(-1.0) 00059 { 00060 // check the selector has the properties needed -- an area and 00061 // applicability jet-by-jet (the latter follows automatically from 00062 // the former?) 00063 if (!_selector.has_finite_area()) throw Error("To construct a GhostedAreaSpec with a Selector, the selector must have a finite area"); 00064 if (!_selector.applies_jet_by_jet()) throw Error("To construct a GhostedAreaSpec with a Selector, the selector must apply jet-by-jet"); 00065 // get the internal rapidity extent from the selector 00066 double ghost_maxrap, ghost_minrap; 00067 _selector.get_rapidity_extent(ghost_minrap, ghost_maxrap); 00068 _ghost_maxrap = 0.5*(ghost_maxrap - ghost_minrap); 00069 _ghost_rap_offset = 0.5*(ghost_maxrap + ghost_minrap); 00070 00071 _initialize(); 00072 00073 } 00074 //====================================================================== 00075 /// sets the detailed parameters for the ghosts (which may not be quite 00076 /// the same as those requested -- this is in order for things to fit 00077 /// in nicely into 2pi etc... 00078 void GhostedAreaSpec::_initialize() { 00079 // add on area-measuring dummy particles 00080 _drap = sqrt(_ghost_area); 00081 _dphi = _drap; 00082 if (_fj2_placement) { 00083 _nphi = int(ceil(twopi/_dphi)); _dphi = twopi/_nphi; 00084 _nrap = int(ceil(_ghost_maxrap/_drap)); _drap = _ghost_maxrap / _nrap; 00085 _actual_ghost_area = _dphi * _drap; 00086 _n_ghosts = (2*_nrap+1)*_nphi; 00087 } else { 00088 // for FJ3, update the ghost placement as follows 00089 // - use nearest int rather than ceiling in determining number of 00090 // phi and rapidity locations, because this is more stable when 00091 // the user is trying to get an exact number based on the area 00092 // - rather than placing ghosts up to maximum rapidity 00093 _nphi = int(twopi/_dphi + 0.5); _dphi = twopi/_nphi; 00094 _nrap = int(_ghost_maxrap/_drap + 0.5); _drap = _ghost_maxrap / _nrap; 00095 _actual_ghost_area = _dphi * _drap; 00096 _n_ghosts = (2*_nrap)*_nphi; 00097 } 00098 // checkpoint the status of the random number generator. 00099 checkpoint_random(); 00100 //_random_generator.info(cerr); 00101 } 00102 00103 //---------------------------------------------------------------------- 00104 /// adds the ghost 4-momenta to the vector of PseudoJet's 00105 void GhostedAreaSpec::add_ghosts(vector<PseudoJet> & event) const { 00106 00107 double rap_offset; 00108 int nrap_upper; 00109 if (_fj2_placement) { 00110 rap_offset = 0.0; 00111 nrap_upper = _nrap; 00112 } else { 00113 rap_offset = 0.5; 00114 nrap_upper = _nrap-1; 00115 } 00116 00117 // add momenta for ghosts 00118 for (int irap = -_nrap; irap <= nrap_upper; irap++) { 00119 for (int iphi = 0; iphi < _nphi; iphi++) { 00120 00121 // include random offsets for all quantities 00122 //---------------------------------------------- 00123 // NB: in FJ2 we'd exchanged the px and py components relative to a 00124 // standard definition of phi; to preserve the same areas as fj2 00125 // we now generate a "phi_fj2", and then convert to a standard phi 00126 double phi_fj2 = (iphi+0.5) * _dphi + _dphi*(_our_rand()-0.5)*_grid_scatter; 00127 double phi; 00128 if (_fj2_placement) phi = 0.5*pi - phi_fj2; 00129 else phi = phi_fj2; 00130 double rap = (irap+rap_offset) * _drap + _drap*(_our_rand()-0.5)*_grid_scatter 00131 + _ghost_rap_offset ; 00132 double kt = _mean_ghost_kt*(1+(_our_rand()-0.5)*_kt_scatter); 00133 00134 double exprap = exp(+rap); 00135 double pminus = kt/exprap; 00136 double pplus = kt*exprap; 00137 double px = kt*cos(phi); 00138 double py = kt*sin(phi); 00139 PseudoJet mom(px,py,0.5*(pplus-pminus),0.5*(pplus+pminus)); 00140 // this call fills in the PseudoJet's cached rap,phi information, 00141 // based on pre-existing knowledge. Watch out: if you get the hint 00142 // wrong nobody will tell you, but you will certainly mess up 00143 // your results. 00144 mom.set_cached_rap_phi(rap,phi); 00145 00146 // if we have an active selector and the particle does not pass the 00147 // selection condition, move on to the next momentum 00148 if (_selector.worker().get() && !_selector.pass(mom)) continue; 00149 event.push_back(mom); 00150 } 00151 } 00152 } 00153 00154 string GhostedAreaSpec::description() const { 00155 00156 ostringstream ostr; 00157 ostr << "ghosts of area " << actual_ghost_area() 00158 << " (had requested " << ghost_area() << ")"; 00159 if (_selector.worker().get()) 00160 ostr << ", placed according to selector (" << _selector.description() << ")"; 00161 else 00162 ostr << ", placed up to y = " << ghost_maxrap() ; 00163 ostr << ", scattered wrt to perfect grid by (rel) " << grid_scatter() 00164 << ", mean_ghost_kt = " << mean_ghost_kt() 00165 << ", rel kt_scatter = " << kt_scatter() 00166 << ", n repetitions of ghost distributions = " << repeat(); 00167 return ostr.str(); 00168 } 00169 00170 FASTJET_END_NAMESPACE 00171