Index: trunk/src/e_starlightStandalone.cpp =================================================================== --- trunk/src/e_starlightStandalone.cpp (revision 10) +++ trunk/src/e_starlightStandalone.cpp (revision 11) @@ -1,179 +1,180 @@ ////////////////////////////////////////////////////////////////////////// // // Copyright 2010 // // This file is part of starlight. // // starlight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // starlight is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with starlight. If not, see <http://www.gnu.org/licenses/>. // /////////////////////////////////////////////////////////////////////////// // // File and Version Information: // $Rev:: 270 $: revision of last commit // $Author:: jnystrand $: author of last commit // $Date:: 2016-07-08 16:31:51 +0100 #$: date of last commit // // Description: // // // /////////////////////////////////////////////////////////////////////////// #include <iostream> +#include <chrono> #include "reportingUtils.h" #include "e_starlight.h" #include "inputParameters.h" #include "eventfilewriter.h" #include "e_starlightStandalone.h" using namespace std; e_starlightStandalone::e_starlightStandalone() : _configFileName ("slight.in"), _starlight (0), _nmbEventsTot (1), _nmbEventsPerFile (_nmbEventsTot) { } e_starlightStandalone::~e_starlightStandalone() { } bool e_starlightStandalone::init() { _inputParameters = new inputParameters(); // read input parameters from config file _inputParameters->configureFromFile(_configFileName); if (!_inputParameters->init()) { printWarn << "problems initializing input parameters. cannot initialize starlight." << endl; return false; } // copy input file to one with baseFileName naming scheme std::string inputCopyName, _baseFileName; _baseFileName = _inputParameters->baseFileName(); if (_baseFileName != "slight") { inputCopyName = _baseFileName +".in"; ofstream inputCopyFile; inputCopyFile.open(inputCopyName.c_str()); std::ifstream infile(_configFileName.c_str()); if ((!infile) || (!infile.good())) { return -1; } int lineSize = 256; char tmp[lineSize]; while (!infile.getline(tmp, lineSize).eof()) { cout << tmp << endl; inputCopyFile << tmp << endl; } inputCopyFile.close(); } // get the number of events // for now we write everything to one file _nmbEventsTot = _inputParameters->nmbEvents(); _nmbEventsPerFile = _nmbEventsTot; // create the starlight object _starlight = new e_starlight(); // give starlight the input parameters _starlight->setInputParameters(_inputParameters); // initialize starlight return _starlight->init(); } bool e_starlightStandalone::run() { if (!_starlight) { printWarn << "null pointer to starlight object. make sure that init() was called. " << "cannot generate events." << endl; return false; } // open output file eventFileWriter fileWriter; fileWriter.writeFullPythiaInfo(_inputParameters->pythiaFullEventRecord()); _baseFileName = _inputParameters->baseFileName(); _eventDataFileName = _baseFileName +".out"; fileWriter.open(_eventDataFileName); // fileWriter.writeInit(*_inputParameters); // printInfo << "generating events:" << endl; unsigned int nmbEvents = 0; std::chrono::steady_clock::time_point begin= std::chrono::steady_clock::now(); while (nmbEvents < _nmbEventsTot) { for (unsigned int iEvent = 0; (iEvent < _nmbEventsPerFile) && (nmbEvents < _nmbEventsTot); ++iEvent, ++nmbEvents) { progressIndicator(iEvent, _nmbEventsTot, true, 4); eXEvent event = _starlight->produceEvent(); // Boost event from back to lab reference frame boostEvent(event); fileWriter.writeEvent(event, iEvent); } } std::chrono::steady_clock::time_point end= std::chrono::steady_clock::now(); float running_total = 1E-3*std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count(); cout<<"Total time "<<running_total<<" s ("<<1E3*running_total/nmbEvents<<" ms/ev)"<<endl; fileWriter.close(); if( _starlight->nmbAttempts() == 0 )return true; double _branchingRatio = _inputParameters->inputBranchingRatio(); printInfo << "number of attempts = " << _starlight->nmbAttempts() << ", " << "number of accepted events = " << _starlight->nmbAccepted() << endl; double selectedCrossSection = ((double)_starlight->nmbAccepted()/_starlight->nmbAttempts())*_branchingRatio*_starlight->getTotalCrossSection(); if (selectedCrossSection > 1.){ cout<< " The cross section of the generated sample is "<<selectedCrossSection<<" barn."<<endl; } else if (1.E3*selectedCrossSection > 1.){ cout<< " The cross section of the generated sample is "<<1.E3*selectedCrossSection<<" mb."<<endl; } else if (1.E6*selectedCrossSection > 1.){ cout<< " The cross section of the generated sample is "<<1.E6*selectedCrossSection<<" microbarn."<<endl; } else if (1.E9*selectedCrossSection > 1.){ cout<< " The cross section of the generated sample is "<<1.E9*selectedCrossSection<<" nanobarn."<<endl; } else if (1.E12*selectedCrossSection > 1.){ cout<< " The cross section of the generated sample is "<<1.E12*selectedCrossSection<<" picobarn."<<endl; } else { cout<< " The cross section of the generated sample is " <<1.E15*selectedCrossSection<<" femtob."<<endl; } return true; } void e_starlightStandalone::boostEvent(eXEvent &event) { // Calculate CMS boost double rap1 = acosh(_inputParameters->beam1LorentzGamma()); double rap2 = -acosh(_inputParameters->beam2LorentzGamma()); double boost = (rap1+rap2)/2.; event.boost(boost, rap2); // Boost back to laboratory reference frame. Electron initially in target frame and V.M. in CMS // Assuming electron is beam1 } Index: trunk/src/e_wideResonanceCrossSection.cpp =================================================================== --- trunk/src/e_wideResonanceCrossSection.cpp (revision 10) +++ trunk/src/e_wideResonanceCrossSection.cpp (revision 11) @@ -1,351 +1,344 @@ /////////////////////////////////////////////////////////////////////////// // // Copyright 2010 // // This file is part of starlight. // // starlight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // starlight is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with starlight. If not, see <http://www.gnu.org/licenses/>. // /////////////////////////////////////////////////////////////////////////// // // File and Version Information: // $Rev:: 264 $: revision of last commit // $Author:: mlomnitz $: author of last commit // $Date:: 2017-03-14 21:05:12 +0100 #$: date of last commit // // Description: // // // /////////////////////////////////////////////////////////////////////////// //#define _makeGammaPQ2_ #include <iostream> #include <fstream> #include <cmath> #include "starlightconstants.h" #include "e_wideResonanceCrossSection.h" using namespace std; using namespace starlightConstants; //______________________________________________________________________________ e_wideResonanceCrossSection::e_wideResonanceCrossSection(const inputParameters& inputParametersInstance, const beamBeamSystem& bbsystem) : photonNucleusCrossSection(inputParametersInstance, bbsystem)//hrm { _wideWmax = _wMax; _wideWmin = _wMin; _targetMaxPhotonEnergy=inputParametersInstance.targetMaxPhotonEnergy(); _targetMinPhotonEnergy=inputParametersInstance.targetMinPhotonEnergy(); _Ep = inputParametersInstance.protonEnergy(); _electronEnergy = inputParametersInstance.electronEnergy(); _target_beamLorentz = inputParametersInstance.beamLorentzGamma(); _VMnumEgamma = inputParametersInstance.nmbEnergyBins(); _useFixedRange = inputParametersInstance.fixedQ2Range(); _gammaMinQ2 = inputParametersInstance.minGammaQ2(); _gammaMaxQ2 = inputParametersInstance.maxGammaQ2(); _targetRadii = inputParametersInstance.targetRadius(); } //______________________________________________________________________________ e_wideResonanceCrossSection::~e_wideResonanceCrossSection() { } //______________________________________________________________________________ void e_wideResonanceCrossSection::crossSectionCalculation(const double bwnormsave) { // This subroutine calculates the cross-section assuming a wide // (Breit-Wigner) resonance. double W,dW, dEgamma, minEgamma; double ega[3] = {0}; double int_r,dR; double int_r2,dR2; - double Eth; int iW,nW,iEgamma,nEgamma,beam; double bwnorm = bwnormsave; //used to transfer the bwnorm from the luminosity tables - - //gamma+nucleon threshold. - Eth=0.5*(((_wideWmin+protonMass)*(_wideWmin+protonMass) - -protonMass*protonMass)/(_Ep+sqrt(_Ep*_Ep-protonMass*protonMass))); - + // For W integration nW = 100; dW = (_wideWmax-_wideWmin)/double(nW); // For Egamma integration nEgamma = 1000; dEgamma = std::log(_targetMaxPhotonEnergy/_targetMinPhotonEnergy)/nEgamma; minEgamma = std::log(_targetMinPhotonEnergy); if (getBNORM() == 0.){ cout<<" Using Breit-Wigner Resonance Profile."<<endl; } else{ cout<<" Using Breit-Wigner plus direct pi+pi- profile."<<endl; } cout<<" Integrating over W from "<<_wideWmin<<" to "<<_wideWmax<<endl; int A_1 = getbbs().beam1().A(); int A_2 = getbbs().beam2().A(); if( A_2 == 0 && A_1 >= 1 ){ // eA, first beam is the nucleus and is in this case the target beam = 1; } else if( A_1 ==0 && A_2 >= 1){ // eA, second beam is the nucleus and is in this case the target beam = 2; } else { beam = 2; } int_r=0.; int_r2 = 0.; // Do this first for the case when the first beam is the photon emitter // The variable beam (=1,2) defines which nucleus is the target // Integration done using Simpson's rule for(iW=0;iW<=nW-1;iW++){ W = _wideWmin + double(iW)*dW + 0.5*dW; int nQ2 = 1000; for(iEgamma = 0 ; iEgamma < nEgamma; ++iEgamma){ // Integral over photon energy // Target frame photon energies ega[0] = exp(minEgamma + iEgamma*dEgamma ); ega[1] = exp(minEgamma + (iEgamma+1)*dEgamma ); ega[2] = 0.5*(ega[0]+ega[1]); // Integral over Q2 double full_int[3] = {0}; // Full e+X --> e+X+V.M. cross section double dndE[3] = {0}; // Full e+X --> e+X+V.M. cross section // for( int iEgaInt = 0 ; iEgaInt < 3; ++iEgaInt){ // Loop over the energies for the three points to integrate over Q2 //These are the physical limits double Q2_min = std::pow(starlightConstants::mel*ega[iEgaInt],2.0)/(_electronEnergy*(_electronEnergy-ega[iEgaInt])); double Q2_max = 4.*_electronEnergy*(_electronEnergy-ega[iEgaInt]); if(_useFixedRange == true){ if( Q2_min < _gammaMinQ2 ) Q2_min = _gammaMinQ2; if( Q2_max > _gammaMaxQ2 ) Q2_max = _gammaMaxQ2; } double lnQ2ratio = std::log(Q2_max/Q2_min)/nQ2; double lnQ2_min = std::log(Q2_min); // - int q2end = -99; for( int iQ2 = 0 ; iQ2 < nQ2; ++iQ2){ // Integral over photon virtuality // double q2_1 = exp( lnQ2_min + iQ2*lnQ2ratio); double q2_2 = exp( lnQ2_min + (iQ2+1)*lnQ2ratio); double q2_12 = (q2_2+q2_1)/2.; // // Integrating cross section full_int[iEgaInt] += (q2_2-q2_1)*( g(ega[iEgaInt],q2_1)*getcsgA(ega[iEgaInt],q2_1,beam) + g(ega[iEgaInt],q2_2)*getcsgA(ega[iEgaInt],q2_2,beam) + 4.*g(ega[iEgaInt],q2_12)*getcsgA(ega[iEgaInt],q2_12,beam) ); // Effective flux dndE[iEgaInt] +=(q2_2-q2_1)*( getcsgA_Q2_dep(q2_1)*photonFlux(ega[iEgaInt],q2_1) +getcsgA_Q2_dep(q2_2)*photonFlux(ega[iEgaInt],q2_2) +4.*getcsgA_Q2_dep(q2_12)*photonFlux(ega[iEgaInt],q2_12) ); } - q2end = -99 ; full_int[iEgaInt] = full_int[iEgaInt]/6.; dndE[iEgaInt] = dndE[iEgaInt]/6.; } // Finishing cross-section integral dR = full_int[0]; dR += full_int[1]; dR += 4.*full_int[2]; dR = dR*(ega[1]-ega[0])/6.; int_r = int_r + dR*breitWigner(W,bwnorm)*dW; // Finishing effective flux integral // Finishing integral over the effective photon flux dR2 = dndE[0]; dR2 += dndE[1]; dR2 += 4.*dndE[2]; dR2 = dR2*(ega[1]-ega[0])/6.; int_r2 = int_r2 + dR2*breitWigner(W,bwnorm)*dW; } } cout<<endl; if(_useFixedRange == true){ cout<<" Using fixed Q2 range "<<_gammaMinQ2 << " < Q2 < "<<_gammaMaxQ2<<endl; } printCrossSection(" Total cross section: ",int_r); //printCrossSection(" gamma+X --> VM+X ", int_r/int_r2); setPhotonNucleusSigma(0.01*int_r); // #ifdef _makeGammaPQ2_ makeGammaPQ2dependence(bwnormsave); #endif } #ifdef _makeGammaPQ2_ //______________________________________________________________________________ void e_wideResonanceCrossSection::makeGammaPQ2dependence( double bwnormsave) { // This subroutine calculates the Q2 dependence of // gamma+X -> VM + X cross section for a narrow resonance int const nQ2bins = 19; double const q2Edge[nQ2bins+1] = { 0.,1.,2.,3., 4.,5., 6.,7.,8.,9.,10., 11.,12.,13.,14.,15., 20.,30.,40.,50.}; double W = 0,dW,dY; double y1,y2,y12,ega1,ega2,ega12; double int_r,dR,dR2; double csgA1, csgA2, csgA12; double Eth; int I,J,NW,NY,beam; double bwnorm = bwnormsave; //used to transfer the bwnorm from the luminosity tables NW = 100; dW = (_wideWmax-_wideWmin)/double(NW); if (getBNORM() == 0.){ cout<<" Using Breit-Wigner Resonance Profile."<<endl; } else{ cout<<" Using Breit-Wigner plus direct pi+pi- profile."<<endl; } cout<<" Integrating over W from "<<_wideWmin<<" to "<<_wideWmax<<endl; //Lomnitz old used for XX Eth=0.5*(((W+protonMass)*(W+protonMass)- protonMass*protonMass)/(_Ep+sqrt(_Ep*_Ep-protonMass*protonMass))); // Adapted for eX //Eth=0.5*(((W+starlightConstants::mel)*(W +starlightConstants::mel)- // starlightConstants::mel*starlightConstants::mel)/(_electronEnergy+sqrt(_electronEnergy*_electronEnergy-starlightConstants::mel*starlightConstants::mel))); printf(" gamma+nucleon threshold: %e GeV \n", Eth); int A_1 = getbbs().beam1().A(); int A_2 = getbbs().beam2().A(); // Do this first for the case when the first beam is the photon emitter // The variable beam (=1,2) defines which nucleus is the target // Target beam ==2 so repidity is negative. Can generalize later /// cout<<" Lomnitz debug :: sigma_gamma_p --> VM_p "<<endl; cout<<" Q2+MV2 \t \t"<<" sigma_gamma_p --> VM_p (nanob)"<<endl; double target_cm = acosh(_target_beamLorentz); // another - sign from subraction in addition rule double exp_target_cm = exp(-target_cm); double int_r2; for( int iQ2 = 0 ; iQ2 < nQ2bins; ++iQ2){ int_r=0.; int_r2=0.; // double q2_cor = getcsgA_Q2_dep( (q2Edge[iQ2+1] + q2Edge[iQ2])/2. ); for(I=0;I<=NW-1;I++){ W = _wideWmin + double(I)*dW + 0.5*dW; for(J=0;J<=(NY-1);J++){ y1 = _wideYmin + double(J)*dY; y2 = _wideYmin + double(J+1)*dY; y12 = 0.5*(y1+y2); double target_ega1, target_ega2, target_ega12; if( A_2 == 0 && A_1 >= 1 ){ // pA, first beam is the nucleus and is in this case the target ega1 = 0.5*W*exp(-y1); ega2 = 0.5*W*exp(-y2); ega12 = 0.5*W*exp(-y12); beam = 1; } else if( A_1 ==0 && A_2 >= 1){ // pA, second beam is the nucleus and is in this case the target ega1 = 0.5*W*exp(y1); ega2 = 0.5*W*exp(y2); ega12 = 0.5*W*exp(y12); // photon energy in Target frame beam = 2; } else { ega1 = 0.5*W*exp(y1); ega2 = 0.5*W*exp(y2); ega12 = 0.5*W*exp(y12); // photon energy in Target frame beam = 2; } // if(ega1 < Eth || ega2 < Eth) continue; if(ega2 > maxPhotonEnergy() || ega1 > maxPhotonEnergy() ) continue; target_ega1 = ega1*exp_target_cm; target_ega12 = ega12*exp_target_cm; target_ega2 = ega2*exp_target_cm; //cout<<"Nortmalizations "<<integrated_x_section(ega1,0,50)<<endl; // csgA1=getcsgA(ega1,W,beam); double full_range_1 = integrated_x_section(target_ega1); // >> Middle Point =====>>> csgA12=getcsgA(ega12,W,beam); double full_range_12 = integrated_x_section(target_ega12); // >> Second Point =====>>> csgA2=getcsgA(ega2,W,beam); double full_range_2 = integrated_x_section(target_ega2); // //>> Sum the contribution for this W,Y. The 2 accounts for the 2 beams dR = q2_cor*csgA1; dR = dR + 4.*q2_cor*csgA12; dR = dR + q2_cor*csgA2; dR = dR*(dY/6.)*breitWigner(W,bwnorm)*dW; // dR2 = full_range_1*csgA1; dR2 = dR2 + 4.*full_range_12*csgA12; dR2 = dR2 + full_range_2*csgA2; dR2 = dR2*(dY/6.)*breitWigner(W,bwnorm)*dW; // int_r = int_r+dR; int_r2 = int_r2 +dR2; } // } if( iQ2 ==0 ) cout<<"Full range "<<int_r2*10000000<<endl; cout<<(q2Edge[iQ2+1]+q2Edge[iQ2])/2.+W*W<<" , "<<10000000.*int_r<<endl; } } #endif void e_wideResonanceCrossSection::printCrossSection(const string name, const double x_section) { if (0.01*x_section > 1.){ cout<< name.c_str() <<0.01*x_section<<" barn."<<endl; } else if (10.*x_section > 1.){ cout<< name.c_str() <<10.*x_section<<" mb."<<endl; } else if (10000.*x_section > 1.){ cout<< name.c_str() <<10000.*x_section<<" microb."<<endl; } else if (10000000.*x_section > 1.){ cout<< name.c_str() <<10000000.*x_section<<" nanob."<<endl; } else if (1.E10*x_section > 1.){ cout<< name.c_str() <<1.E10*x_section<<" picob."<<endl; } else { cout<< name.c_str() <<1.E13*x_section<<" femtob."<<endl; } //cout<<endl; } Index: trunk/src/photonNucleusCrossSection.cpp =================================================================== --- trunk/src/photonNucleusCrossSection.cpp (revision 10) +++ trunk/src/photonNucleusCrossSection.cpp (revision 11) @@ -1,1229 +1,1222 @@ /////////////////////////////////////////////////////////////////////////// // // Copyright 2010 // // This file is part of starlight. // // starlight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // starlight is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with starlight. If not, see <http://www.gnu.org/licenses/>. // /////////////////////////////////////////////////////////////////////////// // // File and Version Information: // $Rev:: 276 $: revision of last commit // $Author:: jnystrand $: author of last commit // $Date:: 2016-09-13 19:54:42 +0100 #$: date of last commit // // Description: // // /////////////////////////////////////////////////////////////////////////// #include <iostream> #include <fstream> #include <cmath> #include "reportingUtils.h" #include "starlightconstants.h" #include "bessel.h" #include "photonNucleusCrossSection.h" using namespace std; using namespace starlightConstants; //______________________________________________________________________________ photonNucleusCrossSection::photonNucleusCrossSection(const inputParameters& inputParametersInstance, const beamBeamSystem& bbsystem) : _nWbins (inputParametersInstance.nmbWBins() ), _nYbins (inputParametersInstance.nmbRapidityBins() ), _wMin (inputParametersInstance.minW() ), _wMax (inputParametersInstance.maxW() ), _yMax (inputParametersInstance.maxRapidity() ), _beamLorentzGamma (inputParametersInstance.beamLorentzGamma() ), _bbs (bbsystem ), _protonEnergy (inputParametersInstance.protonEnergy() ), _electronEnergy (inputParametersInstance.electronEnergy() ), _particleType (inputParametersInstance.prodParticleType() ), _beamBreakupMode (inputParametersInstance.beamBreakupMode() ), _productionMode (inputParametersInstance.productionMode() ), _sigmaNucleus (_bbs.beam2().A() ), _fixedQ2range (inputParametersInstance.fixedQ2Range() ), _minQ2 (inputParametersInstance.minGammaQ2() ), _maxQ2 (inputParametersInstance.maxGammaQ2() ), _maxPhotonEnergy (inputParametersInstance.cmsMaxPhotonEnergy()), _cmsMinPhotonEnergy(inputParametersInstance.cmsMinPhotonEnergy()), _targetRadii (inputParametersInstance.targetRadius() ) { // new options - impulse aproximation (per Joakim) and Quantum Glauber (per SK) SKQG _impulseSelected = inputParametersInstance.impulseVM(); _quantumGlauber = inputParametersInstance.quantumGlauber(); switch(_particleType) { case RHO: - _slopeParameter = 11.0; // [(GeV/c)^{-2}] - _vmPhotonCoupling = 2.02; - _vmQ2Power_c1 = 2.09; - _vmQ2Power_c2 = 0.0073; // [ GeV^{-2}] - _ANORM = -2.75; - _BNORM = 0.0; - _defaultC = 1.0; - _channelMass = starlightConstants::rho0Mass; - _width = starlightConstants::rho0Width; - break; + _slopeParameter = 11.0; // [(GeV/c)^{-2}] + _vmPhotonCoupling = 2.02; + _vmQ2Power_c1 = 2.09; + _vmQ2Power_c2 = 0.0073; // [ GeV^{-2}] + _ANORM = -2.75; + _BNORM = 0.0; + _defaultC = 1.0; + _channelMass = starlightConstants::rho0Mass; + _width = starlightConstants::rho0Width; + break; case RHOZEUS: - _slopeParameter =11.0; - _vmPhotonCoupling=2.02; - _vmQ2Power_c1 = 2.09; - _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] - _ANORM=-2.75; - _BNORM=1.84; - _defaultC=1.0; - _channelMass = starlightConstants::rho0Mass; - _width = starlightConstants::rho0Width; - break; + _slopeParameter =11.0; + _vmPhotonCoupling=2.02; + _vmQ2Power_c1 = 2.09; + _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] + _ANORM=-2.75; + _BNORM=1.84; + _defaultC=1.0; + _channelMass = starlightConstants::rho0Mass; + _width = starlightConstants::rho0Width; + break; case FOURPRONG: - _slopeParameter = 11.0; - _vmPhotonCoupling = 2.02; - _vmQ2Power_c1 = 2.09; - _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] - _ANORM = -2.75; - _BNORM = 0; - _defaultC = 11.0; - _channelMass = starlightConstants::rho0PrimeMass; - _width = starlightConstants::rho0PrimeWidth; - break; + _slopeParameter = 11.0; + _vmPhotonCoupling = 2.02; + _vmQ2Power_c1 = 2.09; + _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] + _ANORM = -2.75; + _BNORM = 0; + _defaultC = 11.0; + _channelMass = starlightConstants::rho0PrimeMass; + _width = starlightConstants::rho0PrimeWidth; + break; case OMEGA: - _slopeParameter=10.0; - _vmPhotonCoupling=23.13; - _vmQ2Power_c1 = 2.09; - _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] - _ANORM=-2.75; - _BNORM=0.0; - _defaultC=1.0; - _channelMass = starlightConstants::OmegaMass; - _width = starlightConstants::OmegaWidth; - break; + _slopeParameter=10.0; + _vmPhotonCoupling=23.13; + _vmQ2Power_c1 = 2.09; + _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] + _ANORM=-2.75; + _BNORM=0.0; + _defaultC=1.0; + _channelMass = starlightConstants::OmegaMass; + _width = starlightConstants::OmegaWidth; + break; case PHI: - _slopeParameter=7.0; - _vmPhotonCoupling=13.71; - _vmQ2Power_c1 = 2.15; - _vmQ2Power_c2 = 0.0074; // [GeV^{-2}] - //_vmQ2Power_c1 = 2.45; - //_vmQ2Power_c2 = 0.0011; // [GeV^{-2}] - _ANORM=-2.75; - _BNORM=0.0; - _defaultC=1.0; - _channelMass = starlightConstants::PhiMass; - _width = starlightConstants::PhiWidth; - break; + _slopeParameter=7.0; + _vmPhotonCoupling=13.71; + _vmQ2Power_c1 = 2.15; + _vmQ2Power_c2 = 0.0074; // [GeV^{-2}] + _ANORM=-2.75; + _BNORM=0.0; + _defaultC=1.0; + _channelMass = starlightConstants::PhiMass; + _width = starlightConstants::PhiWidth; + break; case JPSI: case JPSI_ee: - //_vmQ2Power_c1 = 2.44; - // _vmQ2Power_c2 = 0.0074; // [GeV^{-2}] + _slopeParameter=4.0; + _vmPhotonCoupling=10.45; _vmQ2Power_c1 = 2.45; _vmQ2Power_c2 = 0.00084; // [GeV^{-2}] + _ANORM=-2.75; + _BNORM=0.0; + _defaultC=1.0; + _channelMass = starlightConstants::JpsiMass; + _width = starlightConstants::JpsiWidth; + break; case JPSI_mumu: - _slopeParameter=4.0; - _vmPhotonCoupling=10.45; - // Best so far - //_vmQ2Power_c1 = 2.60; - //_vmQ2Power_c2 = 0.0057; // [GeV^{-2}] - //Clsoe second - //_vmQ2Power_c1 = 2.30; - //_vmQ2Power_c2 = 0.0098; // [GeV^{-2}] - //New winner - _vmQ2Power_c1 = 2.36; - _vmQ2Power_c2 = 0.0029; // [GeV^{-2}] - _ANORM=-2.75; - _BNORM=0.0; - _defaultC=1.0; - _channelMass = starlightConstants::JpsiMass; - _width = starlightConstants::JpsiWidth; - break; + _slopeParameter=4.0; + _vmPhotonCoupling=10.45; + _vmQ2Power_c1 = 2.36; + _vmQ2Power_c2 = 0.0029; // [GeV^{-2}] + _ANORM=-2.75; + _BNORM=0.0; + _defaultC=1.0; + _channelMass = starlightConstants::JpsiMass; + _width = starlightConstants::JpsiWidth; + break; case JPSI2S: case JPSI2S_ee: case JPSI2S_mumu: - _slopeParameter=4.3; - _vmPhotonCoupling=26.39; - _vmQ2Power_c1 = 2.09; - _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] - _ANORM=-2.75; - _BNORM=0.0; - _defaultC=1.0; - _channelMass = starlightConstants::Psi2SMass; - _width = starlightConstants::Psi2SWidth; - break; + _slopeParameter=4.3; + _vmPhotonCoupling=26.39; + _vmQ2Power_c1 = 2.09; + _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] + _ANORM=-2.75; + _BNORM=0.0; + _defaultC=1.0; + _channelMass = starlightConstants::Psi2SMass; + _width = starlightConstants::Psi2SWidth; + break; case UPSILON: case UPSILON_ee: case UPSILON_mumu: - _slopeParameter=4.0; - _vmPhotonCoupling=125.37; - _vmQ2Power_c1 = 2.09; - _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] - _ANORM=-2.75; - _BNORM=0.0; - _defaultC=1.0; - _channelMass = starlightConstants::Upsilon1SMass; - _width = starlightConstants::Upsilon1SWidth; - break; + _slopeParameter=4.0; + _vmPhotonCoupling=125.37; + _vmQ2Power_c1 = 2.09; + _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] + _ANORM=-2.75; + _BNORM=0.0; + _defaultC=1.0; + _channelMass = starlightConstants::Upsilon1SMass; + _width = starlightConstants::Upsilon1SWidth; + break; case UPSILON2S: case UPSILON2S_ee: case UPSILON2S_mumu: - _slopeParameter=4.0; - _vmPhotonCoupling=290.84; - _vmQ2Power_c1 = 2.09; - _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] - _ANORM=-2.75; - _BNORM=0.0; - _defaultC=1.0; - _channelMass = starlightConstants::Upsilon2SMass; - _width = starlightConstants::Upsilon2SWidth; - break; + _slopeParameter=4.0; + _vmPhotonCoupling=290.84; + _vmQ2Power_c1 = 2.09; + _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] + _ANORM=-2.75; + _BNORM=0.0; + _defaultC=1.0; + _channelMass = starlightConstants::Upsilon2SMass; + _width = starlightConstants::Upsilon2SWidth; + break; case UPSILON3S: case UPSILON3S_ee: case UPSILON3S_mumu: - _slopeParameter=4.0; - _vmPhotonCoupling=415.10; - _vmQ2Power_c1 = 2.09; - _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] - _ANORM=-2.75; - _BNORM=0.0; - _defaultC=1.0; - _channelMass = starlightConstants::Upsilon3SMass; - _width = starlightConstants::Upsilon3SWidth; - break; + _slopeParameter=4.0; + _vmPhotonCoupling=415.10; + _vmQ2Power_c1 = 2.09; + _vmQ2Power_c2 = 0.0073; // [GeV^{-2}] + _ANORM=-2.75; + _BNORM=0.0; + _defaultC=1.0; + _channelMass = starlightConstants::Upsilon3SMass; + _width = starlightConstants::Upsilon3SWidth; + break; default: cout <<"No sigma constants parameterized for pid: "<<_particleType <<" GammaAcrosssection"<<endl; } //Changed by Lomnitz for e case. Limit is now E_e - 100m_e //_maxPhotonEnergy = 12. * _beamLorentzGamma * hbarc/(_bbs.beam1().nuclearRadius()+_bbs.beam2().nuclearRadius()); //_maxPhotonEnergy = _electronEnergy - 10.*starlightConstants::mel; /*cout<<" Lomnitz:: max energy in target frame "<< _electronEnergy - 1000.*starlightConstants::mel<<" vs electron energy "<<_electronEnergy<<endl <<" max energy in cms frame "<<_maxPhotonEnergy<<" vs electron energy "<<_beamLorentzGamma*starlightConstants::mel<<endl; cout<<" testing original limit "<< 12. * _beamLorentzGamma * hbarc/(2.*_bbs.beam2().nuclearRadius())<<endl;*/ } //______________________________________________________________________________ photonNucleusCrossSection::~photonNucleusCrossSection() { } //______________________________________________________________________________ void photonNucleusCrossSection::crossSectionCalculation(const double) { cout << "Neither narrow/wide resonance cross-section calculation.--Derived" << endl; } //______________________________________________________________________________ double photonNucleusCrossSection::getcsgA(const double targetEgamma, const double Q2, const int beam) { //This function returns the cross-section for photon-nucleus interaction //producing vectormesons double Av,Wgp,cs,cvma; double t,tmin,tmax; double csgA,ax,bx; int NGAUSS; // double W = _channelMass; //new change, channel mass center used for the t min integration. // DATA FOR GAUSS INTEGRATION double xg[6] = {0, 0.1488743390, 0.4333953941, 0.6794095683, 0.8650633667, 0.9739065285}; double ag[6] = {0, 0.2955242247, 0.2692667193, 0.2190863625, 0.1494513492, 0.0666713443}; NGAUSS = 6; // Note: The photon energy passed to this function is now in the target frame. The rest of the calculations are done in the // CMS frame. The next lines boost the photon into the CM frame. double E_prime = _electronEnergy - targetEgamma; double cos_theta_e = 1. - Q2/(2.*_electronEnergy*E_prime); double theta_e = acos(cos_theta_e); double beam_y = acosh(_beamLorentzGamma); double gamma_pt = E_prime*sin(theta_e); double pz_squared = targetEgamma*targetEgamma - Q2 - gamma_pt*gamma_pt; if( pz_squared < 0 || fabs(cos_theta_e) > 1 || 2.*targetEgamma/(Q2+W*W) < _targetRadii) return 0; double temp_pz = sqrt(pz_squared); // Now boost to CM frame double Egamma = targetEgamma*cosh(beam_y) - temp_pz*sinh(beam_y); if( Egamma < _cmsMinPhotonEnergy || Egamma > _maxPhotonEnergy){ return 0; } //cout<<" ::: Lomnitz test in photonNucleus ::: pz^2 = "<<pz_squared << " CMS Egamma = "<<Egamma<<endl; // Find gamma-proton CM energy in CMS frame in the limit Q2->0 (this is our assumption, the Q2 dependence is in the factor) Wgp = sqrt( 2.*(protonMass*targetEgamma)+protonMass*protonMass); /*Wgp = sqrt(2. * Egamma * (_protonEnergy + sqrt(_protonEnergy * _protonEnergy - protonMass * protonMass)) + protonMass * protonMass);*/ //Used for A-A tmin = (W * W / (4. * Egamma * _beamLorentzGamma)) * (W * W / (4. * Egamma * _beamLorentzGamma)); if ((_bbs.beam1().A() <= 1) && (_bbs.beam2().A() <= 1)){ // proton-proton, no scaling needed csgA = getcsgA_Q2_dep(Q2)*sigmagp(Wgp); } else { // Check if one or both beams are nuclei int A_1 = _bbs.beam1().A(); int A_2 = _bbs.beam2().A(); // coherent AA interactions // Calculate V.M.+proton cross section // cs = sqrt(16. * pi * _vmPhotonCoupling * _slopeParameter * hbarc * hbarc * sigmagp(Wgp) / alpha); cs = getcsgA_Q2_dep(Q2)*sigma_N(Wgp); //Use member function instead // Calculate V.M.+nucleus cross section cvma = sigma_A(cs,beam); // Do impulse approximation here if( _impulseSelected == 1){ if( beam == 1 ){ cvma = A_1*cs; } else if ( beam == 2 ){ cvma = A_2*cs; } } // Calculate Av = dsigma/dt(t=0) Note Units: fm**s/Gev**2 Av = (alpha * cvma * cvma) / (16. * pi * _vmPhotonCoupling * hbarc * hbarc); tmax = tmin + 0.25; ax = 0.5 * (tmax - tmin); bx = 0.5 * (tmax + tmin); csgA = 0.; for (int k = 1; k < NGAUSS; ++k) { t = ax * xg[k] + bx; if( A_1 <= 1 && A_2 != 1){ csgA = csgA + ag[k] * _bbs.beam2().formFactor(t) * _bbs.beam2().formFactor(t); }else if(A_2 <=1 && A_1 != 1){ csgA = csgA + ag[k] * _bbs.beam1().formFactor(t) * _bbs.beam1().formFactor(t); }else{ if( beam==1 ){ csgA = csgA + ag[k] * _bbs.beam1().formFactor(t) * _bbs.beam1().formFactor(t); }else if(beam==2){ csgA = csgA + ag[k] * _bbs.beam2().formFactor(t) * _bbs.beam2().formFactor(t); }else{ cout<<"Something went wrong here, beam= "<<beam<<endl; } } t = ax * (-xg[k]) + bx; if( A_1 <= 1 && A_2 != 1){ csgA = csgA + ag[k] * _bbs.beam2().formFactor(t) * _bbs.beam2().formFactor(t); }else if(A_2 <=1 && A_1 != 1){ csgA = csgA + ag[k] * _bbs.beam1().formFactor(t) * _bbs.beam1().formFactor(t); }else{ if( beam==1 ){ csgA = csgA + ag[k] * _bbs.beam1().formFactor(t) * _bbs.beam1().formFactor(t); }else if(beam==2){ csgA = csgA + ag[k] * _bbs.beam2().formFactor(t) * _bbs.beam2().formFactor(t); }else{ cout<<"Something went wrong here, beam= "<<beam<<endl; } } } csgA = 0.5 * (tmax - tmin) * csgA; csgA = Av * csgA; } return csgA; } //______________________________________________________________________________ double photonNucleusCrossSection::e_getcsgA(const double Egamma, double Q2, const double W, const int beam) { //This function returns the cross-section for photon-nucleus interaction //producing vectormesons for e_starlight. Stuff will be returned in CMS frame, but //photon input is take in target frame double Av,Wgp,cs,cvma; double t,tmin,tmax; double csgA,ax,bx; int NGAUSS; // DATA FOR GAUSS INTEGRATION double xg[6] = {0, 0.1488743390, 0.4333953941, 0.6794095683, 0.8650633667, 0.9739065285}; double ag[6] = {0, 0.2955242247, 0.2692667193, 0.2190863625, 0.1494513492, 0.0666713443}; NGAUSS = 6; // Find gamma-proton CM energy - double proton_pz = sqrt(_protonEnergy * _protonEnergy - protonMass * protonMass); - proton_pz = 0 ; - /* Wgp = sqrt( 2.*(_protonEnergy*Egamma + proton_pz*(Egamma+Q2/(2.*_electronEnergy))) - +protonMass*protonMass - Q2);*/ Wgp = sqrt( 2.*(protonMass*Egamma) +protonMass*protonMass + Q2); //Used for A-A tmin = (W * W / (4. * Egamma * _beamLorentzGamma)) * (W * W / (4. * Egamma * _beamLorentzGamma)); if ((_bbs.beam1().A() <= 1) && (_bbs.beam2().A() <= 1)){ // proton-proton, no scaling needed csgA = sigmagp(Wgp); } else { // coherent AA interactions // Calculate V.M.+proton cross section // cs = sqrt(16. * pi * _vmPhotonCoupling * _slopeParameter * hbarc * hbarc * sigmagp(Wgp) / alpha); cs = sigma_N(Wgp); //Use member function instead // Calculate V.M.+nucleus cross section cvma = sigma_A(cs,beam); // Calculate Av = dsigma/dt(t=0) Note Units: fm**s/Gev**2 Av = (alpha * cvma * cvma) / (16. * pi * _vmPhotonCoupling * hbarc * hbarc); // Check if one or both beams are nuclei int A_1 = _bbs.beam1().A(); int A_2 = _bbs.beam2().A(); tmax = tmin + 0.25; ax = 0.5 * (tmax - tmin); bx = 0.5 * (tmax + tmin); csgA = 0.; for (int k = 1; k < NGAUSS; ++k) { t = ax * xg[k] + bx; if( A_1 <= 1 && A_2 != 1){ csgA = csgA + ag[k] * _bbs.beam2().formFactor(t) * _bbs.beam2().formFactor(t); }else if(A_2 <=1 && A_1 != 1){ csgA = csgA + ag[k] * _bbs.beam1().formFactor(t) * _bbs.beam1().formFactor(t); }else{ if( beam==1 ){ csgA = csgA + ag[k] * _bbs.beam1().formFactor(t) * _bbs.beam1().formFactor(t); }else if(beam==2){ csgA = csgA + ag[k] * _bbs.beam2().formFactor(t) * _bbs.beam2().formFactor(t); }else{ cout<<"Something went wrong here, beam= "<<beam<<endl; } } t = ax * (-xg[k]) + bx; if( A_1 <= 1 && A_2 != 1){ csgA = csgA + ag[k] * _bbs.beam2().formFactor(t) * _bbs.beam2().formFactor(t); }else if(A_2 <=1 && A_1 != 1){ csgA = csgA + ag[k] * _bbs.beam1().formFactor(t) * _bbs.beam1().formFactor(t); }else{ if( beam==1 ){ csgA = csgA + ag[k] * _bbs.beam1().formFactor(t) * _bbs.beam1().formFactor(t); }else if(beam==2){ csgA = csgA + ag[k] * _bbs.beam2().formFactor(t) * _bbs.beam2().formFactor(t); }else{ cout<<"Something went wrong here, beam= "<<beam<<endl; } } } csgA = 0.5 * (tmax - tmin) * csgA; csgA = Av * csgA; } return csgA; } //______________________________________________________________________________ double photonNucleusCrossSection::getcsgA_Q2_dep(const double Q2) { double const mv2 = getChannelMass()*getChannelMass(); double const n = vmQ2Power(Q2); return std::pow(mv2/(mv2+Q2),n); } //______________________________________________________________________________ double photonNucleusCrossSection::photonFlux(const double Egamma, const int beam) { // This routine gives the photon flux as a function of energy Egamma // It works for arbitrary nuclei and gamma; the first time it is // called, it calculates a lookup table which is used on // subsequent calls. // It returns dN_gamma/dE (dimensions 1/E), not dI/dE // energies are in GeV, in the lab frame // rewritten 4/25/2001 by SRK // NOTE: beam (=1,2) defines the photon TARGET double lEgamma,Emin,Emax; static double lnEmax, lnEmin, dlnE; double stepmult,energy,rZ; int nbstep,nrstep,nphistep,nstep; double bmin,bmax,bmult,biter,bold,integratedflux; double fluxelement,deltar,riter; double deltaphi,phiiter,dist; static double dide[401]; double lnElt; double flux_r; double Xvar; int Ilt; double RNuc=0.,RSum=0.; RSum=_bbs.beam1().nuclearRadius()+_bbs.beam2().nuclearRadius(); if( beam == 1){ rZ=double(_bbs.beam2().Z()); RNuc = _bbs.beam1().nuclearRadius(); } else { rZ=double(_bbs.beam1().Z()); RNuc = _bbs.beam2().nuclearRadius(); } static int Icheck = 0; static int Ibeam = 0; //Check first to see if pp if( _bbs.beam1().A()==1 && _bbs.beam2().A()==1 ){ int nbsteps = 400; double bmin = 0.5; double bmax = 5.0 + (5.0*_beamLorentzGamma*hbarc/Egamma); double dlnb = (log(bmax)-log(bmin))/(1.*nbsteps); double local_sum=0.0; // Impact parameter loop for (int i = 0; i<=nbsteps;i++){ double bnn0 = bmin*exp(i*dlnb); double bnn1 = bmin*exp((i+1)*dlnb); double db = bnn1-bnn0; double ppslope = 19.0; double GammaProfile = exp(-bnn0*bnn0/(2.*hbarc*hbarc*ppslope)); double PofB0 = 1. - (1. - GammaProfile)*(1. - GammaProfile); GammaProfile = exp(-bnn1*bnn1/(2.*hbarc*hbarc*ppslope)); double PofB1 = 1. - (1. - GammaProfile)*(1. - GammaProfile); double loc_nofe0 = _bbs.beam1().photonDensity(bnn0,Egamma); double loc_nofe1 = _bbs.beam2().photonDensity(bnn1,Egamma); local_sum += 0.5*loc_nofe0*(1. - PofB0)*2.*starlightConstants::pi*bnn0*db; local_sum += 0.5*loc_nofe1*(1. - PofB1)*2.*starlightConstants::pi*bnn1*db; } // End Impact parameter loop return local_sum; } // first call or new beam? - initialize - calculate photon flux Icheck=Icheck+1; // Do the numerical integration only once for symmetric systems. if( Icheck > 1 && _bbs.beam1().A() == _bbs.beam2().A() && _bbs.beam1().Z() == _bbs.beam2().Z() ) goto L1000f; // For asymmetric systems check if we have another beam if( Icheck > 1 && beam == Ibeam ) goto L1000f; Ibeam = beam; // Nuclear breakup is done by PofB // collect number of integration steps here, in one place nbstep=1200; nrstep=60; nphistep=40; // this last one is the number of energy steps nstep=100; // following previous choices, take Emin=10 keV at LHC, Emin = 1 MeV at RHIC Emin=1.E-5; if (_beamLorentzGamma < 500) Emin=1.E-3; Emax=_maxPhotonEnergy; // Emax=12.*hbarc*_beamLorentzGamma/RSum; // >> lnEmin <-> ln(Egamma) for the 0th bin // >> lnEmax <-> ln(Egamma) for the last bin lnEmin=log(Emin); lnEmax=log(Emax); dlnE=(lnEmax-lnEmin)/nstep; printf("Calculating photon flux from Emin = %e GeV to Emax = %e GeV (CM frame) for source with Z = %3.0f \n", Emin, Emax, rZ); stepmult= exp(log(Emax/Emin)/double(nstep)); energy=Emin; for (int j = 1; j<=nstep;j++){ energy=energy*stepmult; // integrate flux over 2R_A < b < 2R_A+ 6* gamma hbar/energy // use exponential steps bmin=0.8*RSum; //Start slightly below 2*Radius bmax=bmin + 6.*hbarc*_beamLorentzGamma/energy; bmult=exp(log(bmax/bmin)/double(nbstep)); biter=bmin; integratedflux=0.; if( (_bbs.beam1().A() == 1 && _bbs.beam2().A() != 1) || (_bbs.beam2().A() == 1 && _bbs.beam1().A() != 1) ){ // This is pA if( _productionMode == PHOTONPOMERONINCOHERENT ){ // This pA incoherent, proton is the target int nbsteps = 400; double bmin = 0.7*RSum; double bmax = 2.0*RSum + (8.0*_beamLorentzGamma*hbarc/energy); double dlnb = (log(bmax)-log(bmin))/(1.*nbsteps); double local_sum=0.0; // Impact parameter loop for (int i = 0; i<=nbsteps; i++){ double bnn0 = bmin*exp(i*dlnb); double bnn1 = bmin*exp((i+1)*dlnb); double db = bnn1-bnn0; double PofB0 = _bbs.probabilityOfBreakup(bnn0); double PofB1 = _bbs.probabilityOfBreakup(bnn1); double loc_nofe0 = 0.0; double loc_nofe1 = 0.0; if( _bbs.beam1().A() == 1 ){ loc_nofe0 = _bbs.beam2().photonDensity(bnn0,energy); loc_nofe1 = _bbs.beam2().photonDensity(bnn1,energy); } else if( _bbs.beam2().A() == 1 ){ loc_nofe0 = _bbs.beam1().photonDensity(bnn0,energy); loc_nofe1 = _bbs.beam1().photonDensity(bnn1,energy); } // cout<<" i: "<<i<<" bnn0: "<<bnn0<<" PofB0: "<<PofB0<<" loc_nofe0: "<<loc_nofe0<<endl; local_sum += 0.5*loc_nofe0*PofB0*2.*starlightConstants::pi*bnn0*db; local_sum += 0.5*loc_nofe1*PofB1*2.*starlightConstants::pi*bnn1*db; } // End Impact parameter loop integratedflux = local_sum; } else if ( _productionMode == PHOTONPOMERONNARROW || _productionMode == PHOTONPOMERONWIDE ){ // This is pA coherent, nucleus is the target double localbmin = 0.0; if( _bbs.beam1().A() == 1 ){ localbmin = _bbs.beam2().nuclearRadius() + 0.7; } if( _bbs.beam2().A() == 1 ){ localbmin = _bbs.beam1().nuclearRadius() + 0.7; } integratedflux = nepoint(energy,localbmin); } }else{ // This is AA for (int jb = 1; jb<=nbstep;jb++){ bold=biter; biter=biter*bmult; // When we get to b>20R_A change methods - just take the photon flux // at the center of the nucleus. if (biter > (10.*RNuc)){ // if there is no nuclear breakup or only hadronic breakup, which only // occurs at smaller b, we can analytically integrate the flux from b~20R_A // to infinity, following Jackson (2nd edition), Eq. 15.54 Xvar=energy*biter/(hbarc*_beamLorentzGamma); // Here, there is nuclear breakup. So, we can't use the integrated flux // However, we can do a single flux calculation, at the center of the nucleus // Eq. 41 of Vidovic, Greiner and Soff, Phys.Rev.C47,2308(1993), among other places // this is the flux per unit area fluxelement = (rZ*rZ*alpha*energy)* (bessel::dbesk1(Xvar))*(bessel::dbesk1(Xvar))/ ((pi*_beamLorentzGamma*hbarc)* (pi*_beamLorentzGamma*hbarc)); } else { // integrate over nuclear surface. n.b. this assumes total shadowing - // treat photons hitting the nucleus the same no matter where they strike fluxelement=0.; deltar=RNuc/double(nrstep); riter=-deltar/2.; for (int jr =1; jr<=nrstep;jr++){ riter=riter+deltar; // use symmetry; only integrate from 0 to pi (half circle) deltaphi=pi/double(nphistep); phiiter=0.; for( int jphi=1;jphi<= nphistep;jphi++){ phiiter=(double(jphi)-0.5)*deltaphi; // dist is the distance from the center of the emitting nucleus // to the point in question dist=sqrt((biter+riter*cos(phiiter))*(biter+riter* cos(phiiter))+(riter*sin(phiiter))*(riter*sin(phiiter))); Xvar=energy*dist/(hbarc*_beamLorentzGamma); flux_r = (rZ*rZ*alpha*energy)* (bessel::dbesk1(Xvar)*bessel::dbesk1(Xvar))/ ((pi*_beamLorentzGamma*hbarc)* (pi*_beamLorentzGamma*hbarc)); // The surface element is 2.* delta phi* r * delta r // The '2' is because the phi integral only goes from 0 to pi fluxelement=fluxelement+flux_r*2.*deltaphi*riter*deltar; // end phi and r integrations }//for(jphi) }//for(jr) // average fluxelement over the nuclear surface fluxelement=fluxelement/(pi*RNuc*RNuc); }//else // multiply by volume element to get total flux in the volume element fluxelement=fluxelement*2.*pi*biter*(biter-bold); // modulate by the probability of nuclear breakup as f(biter) // cout<<" jb: "<<jb<<" biter: "<<biter<<" fluxelement: "<<fluxelement<<endl; if (_beamBreakupMode > 1){ fluxelement=fluxelement*_bbs.probabilityOfBreakup(biter); } // cout<<" jb: "<<jb<<" biter: "<<biter<<" fluxelement: "<<fluxelement<<endl; integratedflux=integratedflux+fluxelement; } //end loop over impact parameter } //end of else (pp, pA, AA) // In lookup table, store k*dN/dk because it changes less // so the interpolation should be better dide[j]=integratedflux*energy; }//end loop over photon energy // for 2nd and subsequent calls, use lookup table immediately L1000f: lEgamma=log(Egamma); if (lEgamma < (lnEmin+dlnE) || lEgamma > lnEmax){ flux_r=0.0; cout<<" ERROR: Egamma outside defined range. Egamma= "<<Egamma <<" "<<lnEmax<<" "<<(lnEmin+dlnE)<<endl; } else{ // >> Egamma between Ilt and Ilt+1 Ilt = int((lEgamma-lnEmin)/dlnE); // >> ln(Egamma) for first point lnElt = lnEmin + Ilt*dlnE; // >> Interpolate flux_r = dide[Ilt] + ((lEgamma-lnElt)/dlnE)*(dide[Ilt+1]- dide[Ilt]); flux_r = flux_r/Egamma; } return flux_r; } //______________________________________________________________________________ double photonNucleusCrossSection::integrated_Q2_dep(double const Egamma, double const _min, double const _max) { //Integration over full limits gives more accurate result double Q2_min = std::pow(starlightConstants::mel*Egamma,2.0)/(_electronEnergy*(_electronEnergy-Egamma)); double Q2_max = 4.*_electronEnergy*(_electronEnergy-Egamma); //double Q2_max = 2.*Egamma/_targetRadii - _wMax*_wMax; if( _min != 0 || _max !=0){ if( _min > Q2_min ) Q2_min = _min; if( _max < Q2_max ) Q2_max = _max; } // Simpsons rule in using exponential step size and 10000 steps. Tested trapeve rule, linear steps and // nstep = 10,000 100,000 & 10,000,0000 int nstep = 1000; double ln_min = std::log(Q2_min); double ratio = std::log(Q2_max/Q2_min)/nstep; double g_int = 0; double g_int2 = 0 ; double g_int3 = 0; //cout<<"*** Lomnitz **** Energy "<<Egamma<<" limits "<<Q2_min*1E9<<" x 1E-9 - "<<Q2_max<<endl; for ( int ii = 0 ; ii< nstep; ++ii){ double x1 = std::exp(ln_min+(double)ii*ratio); double x3 = std::exp(ln_min+(double)(ii+1)*ratio); double x2 = (x3+x1)/2.; //cout<<"ii : "<<x1<<" "<<x2<<" "<<x3<<endl; g_int += (x3-x1)*( g(Egamma,x3)+g(Egamma,x1) +4.*g(Egamma,x2)); g_int2 += (x3-x1)*( photonFlux(Egamma,x3)+photonFlux(Egamma,x1) +4.*photonFlux(Egamma,x2)); g_int3 += (x3-x1)*( getcsgA_Q2_dep(x3)+getcsgA_Q2_dep(x1) +4.*getcsgA_Q2_dep(x2)); } //return g_int2*g_int3/36.; //return g_int2/6.; return g_int/6.; } //______________________________________________________________________________ double photonNucleusCrossSection::integrated_x_section(double const Egamma, double const _min, double const _max) { //Integration over full limits gives more accurate result double Q2_min = std::pow(starlightConstants::mel*Egamma,2.0)/(_electronEnergy*(_electronEnergy-Egamma)); //double Q2_max = 2.*Egamma/_targetRadii - _wMax*_wMax; double Q2_max = 4.*_electronEnergy*(_electronEnergy-Egamma); // Fixed ranges for plot if( _min != 0 || _max!=0){ if( _min > Q2_min) Q2_min = _min; if( _max < Q2_max) Q2_max = _max; } // Simpsons rule in using exponential step size and 10000 steps. Tested trapeve rule, linear steps and // nstep = 10,000 100,000 & 10,000,0000 int nstep = 1000; double ln_min = std::log(Q2_min); double ratio = std::log(Q2_max/Q2_min)/nstep; double g_int = 0; for ( int ii = 0 ; ii< nstep; ++ii){ double x1 = std::exp(ln_min+(double)ii*ratio); double x3 = std::exp(ln_min+(double)(ii+1)*ratio); double x2 = (x3+x1)/2.; //Tests from HERA https://arxiv.org/pdf/hep-ex/9601009.pdf // g_int += (x3-x1)*( getcsgA_Q2_dep(x3)+getcsgA_Q2_dep(x1) +4.*getcsgA_Q2_dep(x2)); g_int += (x3-x1)*( getcsgA_Q2_dep(x3)+getcsgA_Q2_dep(x1) +4.*getcsgA_Q2_dep(x2)); } //return g_int2*g_int3/36.; return g_int/6.; } //______________________________________________________________________________ pair< double, double >*photonNucleusCrossSection::Q2arraylimits(double const Egamma) { //double Q2max = 2.*Egamma/_targetRadii - _wMax*_wMax; double Q2max = 4.*_electronEnergy*(_electronEnergy-Egamma); double Q2min= std::pow(starlightConstants::mel*Egamma,2.0)/(_electronEnergy*(_electronEnergy-Egamma)); if( _fixedQ2range == true){ if( Q2min < _minQ2 ) Q2min = _minQ2; if( Q2max > _maxQ2 ) Q2max = _maxQ2; //cout<<" Imposed limits "<<Q2min<<" - "<<Q2max<<endl; std::pair<double,double>* to_ret = new std::pair<double, double>(Q2min,Q2max); return to_ret; } int Nstep = 1000; // double ratio = std::log(Q2max/Q2min)/(double)Nstep; double ln_min = std::log(Q2min); // -- - - const double limit = 1E-9; std::vector<double>Q2_array; int iNstep = 0; double g_step = 1.; while( g_step>limit ){ double Q2 = std::exp(ln_min+iNstep*ratio); if(Q2>Q2max) break; g_step = g(Egamma,Q2); Q2_array.push_back(g_step); iNstep++; } if( std::exp(ln_min+iNstep*ratio) < Q2max) Q2max = std::exp(ln_min+iNstep*ratio); //cout<<Q2max<<" "<<g(Egamma,Q2max)*1E9<<endl; std::pair<double, double>* to_ret = new std::pair<double, double>(Q2min,Q2max); return to_ret; } //______________________________________________________________________________ double photonNucleusCrossSection::g(double const Egamma, double const Q2) { //return photonFlux(Egamma,Q2)*getcsgA_Q2_dep(Q2); return photonFlux(Egamma,Q2); //This could be done more elegantly in the future, but this one change should account for everything } //______________________________________________________________________________ double photonNucleusCrossSection::photonFlux(double const Egamma, double const Q2) { //Need to check units later //double const hbar = starlightConstants::hbarc / 2.99*pow(10,14); // 6.582 * pow (10,-16) [eVs] //double omega = Egamma/ hbar; //Do we even need a lookup table for this case? This should return N(E,Q2) from dn = N(E,Q2) dE dQ2 double const ratio = Egamma/_electronEnergy; double const minQ2 = std::pow( starlightConstants::mel*Egamma,2.0) / (_electronEnergy*(_electronEnergy - Egamma)); double to_ret = alpha/(pi) *( 1- ratio + ratio*ratio/2. - (1-ratio)*( fabs(minQ2/Q2)) ); //Comparisons: // double temp = pow(2.*_electronEnergy-Egamma,2.)/(Egamma*Egamma + Q2) + 1. - 4.*starlightConstants::mel*starlightConstants::mel/Q2; //temp = alpha*temp*Egamma/(4.*Q2*pi*_electronEnergy*_electronEnergy); // cout<<" *** Lomnitz *** Testing photon flux approximation for electron energy "<<_electronEnergy<<" gamma "<<Egamma<<" Q2 "<<Q2*1E6<<" 1E-6 "<<endl; //cout<<" Full expression "<<temp*1E6<<" vs. apporioximation "<<to_ret/( Egamma*fabs(Q2) )*1E6<<" --- ratio "<<temp/(to_ret/( Egamma*fabs(Q2) ))<<endl; return to_ret/( Egamma*fabs(Q2) ); //return temp; } //______________________________________________________________________________ double photonNucleusCrossSection::nepoint(const double Egamma, const double bmin) { // Function for the spectrum of virtual photons, // dn/dEgamma, for a point charge q=Ze sweeping // past the origin with velocity gamma // (=1/SQRT(1-(V/c)**2)) integrated over impact // parameter from bmin to infinity // See Jackson eq15.54 Classical Electrodynamics // Declare Local Variables double beta,X,C1,bracket,nepoint_r; beta = sqrt(1.-(1./(_beamLorentzGamma*_beamLorentzGamma))); X = (bmin*Egamma)/(beta*_beamLorentzGamma*hbarc); bracket = -0.5*beta*beta*X*X*(bessel::dbesk1(X)*bessel::dbesk1(X) -bessel::dbesk0(X)*bessel::dbesk0(X)); bracket = bracket+X*bessel::dbesk0(X)*bessel::dbesk1(X); // Note: NO Z*Z!! C1=(2.*alpha)/pi; nepoint_r = C1*(1./beta)*(1./beta)*(1./Egamma)*bracket; return nepoint_r; } //______________________________________________________________________________ double photonNucleusCrossSection::sigmagp(const double Wgp) { // Function for the gamma-proton --> VectorMeson // cross section. Wgp is the gamma-proton CM energy. // Unit for cross section: fm**2 double sigmagp_r=0.; switch(_particleType) { case RHO: case RHOZEUS: case FOURPRONG: sigmagp_r=1.E-4*(5.0*exp(0.22*log(Wgp))+26.0*exp(-1.23*log(Wgp))); break; case OMEGA: sigmagp_r=1.E-4*(0.55*exp(0.22*log(Wgp))+18.0*exp(-1.92*log(Wgp))); break; case PHI: sigmagp_r=1.E-4*0.34*exp(0.22*log(Wgp)); break; case JPSI: case JPSI_ee: case JPSI_mumu: sigmagp_r=(1.0-((_channelMass+protonMass)*(_channelMass+protonMass))/(Wgp*Wgp)); sigmagp_r*=sigmagp_r; sigmagp_r*=1.E-4*0.00406*exp(0.65*log(Wgp)); // sigmagp_r=1.E-4*0.0015*exp(0.80*log(Wgp)); break; case JPSI2S: case JPSI2S_ee: case JPSI2S_mumu: sigmagp_r=(1.0-((_channelMass+protonMass)*(_channelMass+protonMass))/(Wgp*Wgp)); sigmagp_r*=sigmagp_r; sigmagp_r*=1.E-4*0.00406*exp(0.65*log(Wgp)); sigmagp_r*=0.166; // sigmagp_r=0.166*(1.E-4*0.0015*exp(0.80*log(Wgp))); break; case UPSILON: case UPSILON_ee: case UPSILON_mumu: // >> This is W**1.7 dependence from QCD calculations // sigmagp_r=1.E-10*(0.060)*exp(1.70*log(Wgp)); sigmagp_r=(1.0-((_channelMass+protonMass)*(_channelMass+protonMass))/(Wgp*Wgp)); sigmagp_r*=sigmagp_r; sigmagp_r*=1.E-10*6.4*exp(0.74*log(Wgp)); break; case UPSILON2S: case UPSILON2S_ee: case UPSILON2S_mumu: // sigmagp_r=1.E-10*(0.0259)*exp(1.70*log(Wgp)); sigmagp_r=(1.0-((_channelMass+protonMass)*(_channelMass+protonMass))/(Wgp*Wgp)); sigmagp_r*=sigmagp_r; sigmagp_r*=1.E-10*2.9*exp(0.74*log(Wgp)); break; case UPSILON3S: case UPSILON3S_ee: case UPSILON3S_mumu: // sigmagp_r=1.E-10*(0.0181)*exp(1.70*log(Wgp)); sigmagp_r=(1.0-((_channelMass+protonMass)*(_channelMass+protonMass))/(Wgp*Wgp)); sigmagp_r*=sigmagp_r; sigmagp_r*=1.E-10*2.1*exp(0.74*log(Wgp)); break; default: cout<< "!!! ERROR: Unidentified Vector Meson: "<< _particleType <<endl; } return sigmagp_r; } //______________________________________________________________________________ double photonNucleusCrossSection::sigma_A(const double sig_N, const int beam) { // Nuclear Cross Section // sig_N,sigma_A in (fm**2) double sum; double b,bmax,Pint,arg,sigma_A_r; int NGAUSS; double xg[17]= {.0, .0483076656877383162,.144471961582796493, .239287362252137075, .331868602282127650, .421351276130635345, .506899908932229390, .587715757240762329, .663044266930215201, .732182118740289680, .794483795967942407, .849367613732569970, .896321155766052124, .934906075937739689, .964762255587506430, .985611511545268335, .997263861849481564 }; double ag[17]= {.0, .0965400885147278006, .0956387200792748594, .0938443990808045654, .0911738786957638847, .0876520930044038111, .0833119242269467552, .0781938957870703065, .0723457941088485062, .0658222227763618468, .0586840934785355471, .0509980592623761762, .0428358980222266807, .0342738629130214331, .0253920653092620595, .0162743947309056706, .00701861000947009660 }; NGAUSS=16; // Check if one or both beams are nuclei int A_1 = _bbs.beam1().A(); int A_2 = _bbs.beam2().A(); if( A_1 == 1 && A_2 == 1)cout<<" This is pp, you should not be here..."<<endl; // CALCULATE P(int) FOR b=0.0 - bmax (fm) bmax = 25.0; sum = 0.; for(int IB=1;IB<=NGAUSS;IB++){ b = 0.5*bmax*xg[IB]+0.5*bmax; if( A_1 == 1 && A_2 != 1){ arg=-sig_N*_bbs.beam2().rho0()*_bbs.beam2().thickness(b); }else if(A_2 == 1 && A_1 != 1){ arg=-sig_N*_bbs.beam1().rho0()*_bbs.beam1().thickness(b); }else{ // Check which beam is target if( beam == 1 ){ arg=-sig_N*_bbs.beam1().rho0()*_bbs.beam1().thickness(b); }else if( beam==2 ){ arg=-sig_N*_bbs.beam2().rho0()*_bbs.beam2().thickness(b); }else{ cout<<" Something went wrong here, beam= "<<beam<<endl; } } Pint=1.0-exp(arg); // If this is a quantum Glauber calculation, use the quantum Glauber formula if (_quantumGlauber == 1){Pint=2.0*(1.0-exp(arg/2.0));} sum=sum+2.*pi*b*Pint*ag[IB]; b = 0.5*bmax*(-xg[IB])+0.5*bmax; if( A_1 == 1 && A_2 != 1){ arg=-sig_N*_bbs.beam2().rho0()*_bbs.beam2().thickness(b); }else if(A_2 == 1 && A_1 != 1){ arg=-sig_N*_bbs.beam1().rho0()*_bbs.beam1().thickness(b); }else{ // Check which beam is target if( beam == 1 ){ arg=-sig_N*_bbs.beam1().rho0()*_bbs.beam1().thickness(b); }else if(beam==2){ arg=-sig_N*_bbs.beam2().rho0()*_bbs.beam2().thickness(b); }else{ cout<<" Something went wrong here, beam= "<<beam<<endl; } } Pint=1.0-exp(arg); // If this is a quantum Glauber calculation, use the quantum Glauber formula if (_quantumGlauber == 1){Pint=2.0*(1.0-exp(arg/2.0));} sum=sum+2.*pi*b*Pint*ag[IB]; } sum=0.5*bmax*sum; sigma_A_r=sum; return sigma_A_r; } //______________________________________________________________________________ double photonNucleusCrossSection::sigma_N(const double Wgp) { // Nucleon Cross Section in (fm**2) double cs = sqrt(16. * pi * _vmPhotonCoupling * _slopeParameter * hbarc * hbarc * sigmagp(Wgp) / alpha); return cs; } //______________________________________________________________________________ double photonNucleusCrossSection::breitWigner(const double W, const double C) { // use simple fixed-width s-wave Breit-Wigner without coherent backgorund for rho' // (PDG '08 eq. 38.56) if(_particleType==FOURPRONG) { if (W < 4.01 * pionChargedMass) return 0; const double termA = _channelMass * _width; const double termA2 = termA * termA; const double termB = W * W - _channelMass * _channelMass; return C * _ANORM * _ANORM * termA2 / (termB * termB + termA2); } // Relativistic Breit-Wigner according to J.D. Jackson, // Nuovo Cimento 34, 6692 (1964), with nonresonant term. A is the strength // of the resonant term and b the strength of the non-resonant // term. C is an overall normalization. double ppi=0.,ppi0=0.,GammaPrim,rat; double aa,bb,cc; double nrbw_r; // width depends on energy - Jackson Eq. A.2 // if below threshold, then return 0. Added 5/3/2001 SRK // 0.5% extra added for safety margin // omega added here 10/26/2014 SRK if( _particleType==RHO ||_particleType==RHOZEUS || _particleType==OMEGA){ if (W < 2.01*pionChargedMass){ nrbw_r=0.; return nrbw_r; } ppi=sqrt( ((W/2.)*(W/2.)) - pionChargedMass * pionChargedMass); ppi0=0.358; } // handle phi-->K+K- properly if (_particleType == PHI){ if (W < 2.*kaonChargedMass){ nrbw_r=0.; return nrbw_r; } ppi=sqrt( ((W/2.)*(W/2.))- kaonChargedMass*kaonChargedMass); ppi0=sqrt( ((_channelMass/2.)*(_channelMass/2.))-kaonChargedMass*kaonChargedMass); } //handle J/Psi-->e+e- properly if (_particleType==JPSI || _particleType==JPSI2S){ if(W<2.*mel){ nrbw_r=0.; return nrbw_r; } ppi=sqrt(((W/2.)*(W/2.))-mel*mel); ppi0=sqrt(((_channelMass/2.)*(_channelMass/2.))-mel*mel); } if (_particleType==JPSI_ee){ if(W<2.*mel){ nrbw_r=0.; return nrbw_r; } ppi=sqrt(((W/2.)*(W/2.))-mel*mel); ppi0=sqrt(((_channelMass/2.)*(_channelMass/2.))-mel*mel); } if (_particleType==JPSI_mumu){ if(W<2.*muonMass){ nrbw_r=0.; return nrbw_r; } ppi=sqrt(((W/2.)*(W/2.))-muonMass*muonMass); ppi0=sqrt(((_channelMass/2.)*(_channelMass/2.))-muonMass*muonMass); } if (_particleType==JPSI2S_ee){ if(W<2.*mel){ nrbw_r=0.; return nrbw_r; } ppi=sqrt(((W/2.)*(W/2.))-mel*mel); ppi0=sqrt(((_channelMass/2.)*(_channelMass/2.))-mel*mel); } if (_particleType==JPSI2S_mumu){ if(W<2.*muonMass){ nrbw_r=0.; return nrbw_r; } ppi=sqrt(((W/2.)*(W/2.))-muonMass*muonMass); ppi0=sqrt(((_channelMass/2.)*(_channelMass/2.))-muonMass*muonMass); } if(_particleType==UPSILON || _particleType==UPSILON2S ||_particleType==UPSILON3S ){ if (W<2.*muonMass){ nrbw_r=0.; return nrbw_r; } ppi=sqrt(((W/2.)*(W/2.))-muonMass*muonMass); ppi0=sqrt(((_channelMass/2.)*(_channelMass/2.))-muonMass*muonMass); } if(_particleType==UPSILON_mumu || _particleType==UPSILON2S_mumu ||_particleType==UPSILON3S_mumu ){ if (W<2.*muonMass){ nrbw_r=0.; return nrbw_r; } ppi=sqrt(((W/2.)*(W/2.))-muonMass*muonMass); ppi0=sqrt(((_channelMass/2.)*(_channelMass/2.))-muonMass*muonMass); } if(_particleType==UPSILON_ee || _particleType==UPSILON2S_ee ||_particleType==UPSILON3S_ee ){ if (W<2.*mel){ nrbw_r=0.; return nrbw_r; } ppi=sqrt(((W/2.)*(W/2.))-mel*mel); ppi0=sqrt(((_channelMass/2.)*(_channelMass/2.))-mel*mel); } if(ppi==0.&&ppi0==0.) cout<<"Improper Gammaacrosssection::breitwigner, ppi&ppi0=0."<<endl; rat=ppi/ppi0; GammaPrim=_width*(_channelMass/W)*rat*rat*rat; aa=_ANORM*sqrt(GammaPrim*_channelMass*W); bb=W*W-_channelMass*_channelMass; cc=_channelMass*GammaPrim; // First real part squared nrbw_r = (( (aa*bb)/(bb*bb+cc*cc) + _BNORM)*( (aa*bb)/(bb*bb+cc*cc) + _BNORM)); // Then imaginary part squared nrbw_r = nrbw_r + (( (aa*cc)/(bb*bb+cc*cc) )*( (aa*cc)/(bb*bb+cc*cc) )); // Alternative, a simple, no-background BW, following J. Breitweg et al. // Eq. 15 of Eur. Phys. J. C2, 247 (1998). SRK 11/10/2000 // nrbw_r = (_ANORM*_mass*GammaPrim/(bb*bb+cc*cc))**2 nrbw_r = C*nrbw_r; return nrbw_r; }