Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F8723635
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
126 KB
Subscribers
None
View Options
Index: trunk/src/InclusiveDiffractiveCrossSections.cpp
===================================================================
--- trunk/src/InclusiveDiffractiveCrossSections.cpp (revision 537)
+++ trunk/src/InclusiveDiffractiveCrossSections.cpp (revision 538)
@@ -1,688 +1,719 @@
//==============================================================================
// InclusiveDiffractiveCrossSection.cpp
//
// Copyright (C) 2024 Tobias Toll and Thomas Ullrich
//
// This file is part of Sartre.
//
// This program 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.
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author: Tobias Toll
// Last update:
// $Date: 2024-06-03 11:27:05 -0400 (Mon, 03 Jun 2024) $
// $Author: ullrich $
//==============================================================================
#include "Math/SpecFunc.h"
#include "TFile.h"
#include <iostream>
#include <cmath>
#include <algorithm>
#include <algorithm>
#include "Constants.h"
#include "Nucleus.h"
#include "DipoleModel.h"
#include "AlphaStrong.h"
#include "Math/IntegratorMultiDim.h"
#include "Math/Functor.h"
#include "TMath.h"
#include "WaveOverlap.h"
#include "Kinematics.h"
//#include "TableGeneratorSettings.h"
#include "Settings.h"
#include "Enumerations.h"
#include "TF1.h"
#include "TF1.h"
#include "TH1F.h"
#include "cuba.h"
#include "InclusiveDiffractiveCrossSections.h"
#include "DglapEvolution.h"
#include "Math/WrappedTF1.h"
#include "Math/GaussIntegrator.h"
#include "DipoleModelParameters.h"
#define PR(x) cout << #x << " = " << (x) << endl;
-InclusiveDiffractiveCrossSections::InclusiveDiffractiveCrossSections()
+InclusiveDiffractiveCrossSections::InclusiveDiffractiveCrossSections(){}
+
+InclusiveDiffractiveCrossSections::~InclusiveDiffractiveCrossSections(){}
+
+double InclusiveDiffractiveCrossSections::operator()(double, double, double, double){return 0;}
+double InclusiveDiffractiveCrossSections::operator()(const double*){ return 0;}
+DipoleModel* InclusiveDiffractiveCrossSections::dipoleModel(){return 0;}
+double InclusiveDiffractiveCrossSections::unuranPDF(const double*){return 0;}
+double InclusiveDiffractiveCrossSections::unuranPDF_qqg(const double*){return 0;}
+void InclusiveDiffractiveCrossSections::setCheckKinematics(bool){}
+void InclusiveDiffractiveCrossSections::setFockState(FockState){}
+GammaPolarization InclusiveDiffractiveCrossSections::polarizationOfLastCall(){return transverse;}
+double InclusiveDiffractiveCrossSections::crossSectionOfLastCall(){return 0;}
+unsigned int InclusiveDiffractiveCrossSections::quarkSpeciesOfLastCall(){return 0;}
+double InclusiveDiffractiveCrossSections::quarkMassOfLastCall(){return 0;}
+double InclusiveDiffractiveCrossSections::crossSectionRatioLTOfLastCall() const{return 0;}
+void InclusiveDiffractiveCrossSections::setQuarkIndex(unsigned int){}
+double InclusiveDiffractiveCrossSections::dsigmadbetadz_T(double, double, double, double){ return 0; }
+double InclusiveDiffractiveCrossSections::dsigmadbetadz_L(double, double, double, double){ return 0; }
+double InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(double, double, double, double){return 0;}
+double InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(double, double, double, double){return 0;}
+
+double InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total(double, double, double, double, GammaPolarization){return 0;}
+
+double InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_qqg(double, double, double, double){return 0;}
+
+double* InclusiveDiffractiveCrossSections::dsigdbetadQ2dWdz_T_total(){return 0;}
+double* InclusiveDiffractiveCrossSections::dsigdbetadQ2dWdz_L_total(){return 0;}
+double* InclusiveDiffractiveCrossSections::dsigdbetadQ2dWdz_T_qqg(){return 0;}
+
+
+InclusiveDiffractiveCrossSectionsIntegrals::InclusiveDiffractiveCrossSectionsIntegrals()
{
mSettings = EventGeneratorSettings::instance();
mRandom = mSettings->randomGenerator();
mS = Kinematics::s(mSettings->eBeam(), mSettings->hBeam());
mPhotonFlux.setS(mS);
mCheckKinematics = true;
mCrossSectionRatioLT = 0;
mQ2=0;
// TableGeneratorSettings* settings = TableGeneratorSettings::instance();
if(mDipoleModel) delete mDipoleModel;
mDipoleModelParameterSet = mSettings->dipoleModelParameterSet();
DipoleModelType model=mSettings->dipoleModelType();
if (model==bSat) {
mDipoleModel = new DipoleModel_bSat(mSettings);
}
else if(model==bNonSat){
mDipoleModel = new DipoleModel_bNonSat(mSettings);
}
else {
cout << "Integrals::init(): Error, model not implemented: "<< model << endl;
exit(1);
}
mA=mSettings->A();
//Set up the integrals
//Amplitude0:
if(Amp0) delete Amp0;
- Amp0=new TF1("Amp0", this, &InclusiveDiffractiveCrossSections::uiAmplitude_0, 0, 30., 5);
+ Amp0=new TF1("Amp0", this, &InclusiveDiffractiveCrossSectionsIntegrals::uiAmplitude_0, 0, 30., 5);
if(WFAmp0) delete WFAmp0;
WFAmp0=new ROOT::Math::WrappedTF1(*Amp0);
GIAmp0.SetFunction(*WFAmp0);
GIAmp0.SetRelTolerance(1e-4);
//Amplitude1:
if(Amp1) delete Amp1;
- Amp1=new TF1("Amp1", this, &InclusiveDiffractiveCrossSections::uiAmplitude_1, 0, 30. , 5);
+ Amp1=new TF1("Amp1", this, &InclusiveDiffractiveCrossSectionsIntegrals::uiAmplitude_1, 0, 30. , 5);
if(WFAmp1) delete WFAmp1;
WFAmp1=new ROOT::Math::WrappedTF1(*Amp1);
GIAmp1.SetFunction(*WFAmp1);
GIAmp1.SetRelTolerance(1e-4);
//AmplitudeQQG:
if(Ampqqg) delete Ampqqg;
- Ampqqg=new TF1("Ampqqg", this, &InclusiveDiffractiveCrossSections::uiAmplitude_qqg, 0, 30., 4);
+ Ampqqg=new TF1("Ampqqg", this, &InclusiveDiffractiveCrossSectionsIntegrals::uiAmplitude_qqg, 0, 30., 4);
if(WFAmpqqg) delete WFAmpqqg;
WFAmpqqg=new ROOT::Math::WrappedTF1(*Ampqqg);
GIAmpqqg.SetFunction(*WFAmpqqg);
GIAmpqqg.SetRelTolerance(1e-4);
}
-InclusiveDiffractiveCrossSections::~InclusiveDiffractiveCrossSections(){
+InclusiveDiffractiveCrossSectionsIntegrals::~InclusiveDiffractiveCrossSectionsIntegrals(){
if(WFAmp0) delete WFAmp0;
if(Amp0) delete Amp0;
if(WFAmp1) delete WFAmp1;
if(Amp1) delete Amp1;
if(Ampqqg) delete Ampqqg;
}
-void InclusiveDiffractiveCrossSections::setCheckKinematics(bool val) {mCheckKinematics = val;}
+void InclusiveDiffractiveCrossSectionsIntegrals::setCheckKinematics(bool val) {mCheckKinematics = val;}
-void InclusiveDiffractiveCrossSections::setFockState(FockState val){
+void InclusiveDiffractiveCrossSectionsIntegrals::setFockState(FockState val){
mFockState=val;
}
-FockState InclusiveDiffractiveCrossSections::getFockState(){
+FockState InclusiveDiffractiveCrossSectionsIntegrals::getFockState(){
return mFockState;
}
-double InclusiveDiffractiveCrossSections::operator()(double MX2, double Q2, double W2, double z){
+double InclusiveDiffractiveCrossSectionsIntegrals::operator()(double MX2, double Q2, double W2, double z){
return dsigdMX2dQ2dW2dz_total_checked(MX2, Q2, W2, z);
}
-double InclusiveDiffractiveCrossSections::operator()(const double* array){
+double InclusiveDiffractiveCrossSectionsIntegrals::operator()(const double* array){
double result=0;
if(mFockState==QQ or mFockState==ALL){
result+=dsigdbetadQ2dW2dz_total_checked(array[0], array[1], array[2], array[3]);
}
else if(mFockState==QQG or
mFockState==ALL){
result+=dsigdbetadQ2dW2dz_total_qqg_checked(array[0], array[1], array[2], array[3]);
}
else{
- cout<<"InclusiveDiffractiveCrossSections::operator(): Fockstate is invalid, stopping"<<endl;
+ cout<<"InclusiveDiffractiveCrossSectionsIntegrals::operator(): Fockstate is invalid, stopping"<<endl;
exit(0);
}
return result;
}
-double InclusiveDiffractiveCrossSections::unuranPDF(const double* array){
+double InclusiveDiffractiveCrossSectionsIntegrals::unuranPDF(const double* array){
//
// array is: beta, log(Q2), W2, z
//
double result = 0;
double Q2 = exp(array[1]);
result = dsigdbetadQ2dW2dz_total_checked(array[0], Q2, array[2], array[3]);
result *= Q2; // Jacobian
return log(result);
}
-double InclusiveDiffractiveCrossSections::dsigdMX2dQ2dW2dz_total_checked(double MX2, double Q2, double W2, double z){
+double InclusiveDiffractiveCrossSectionsIntegrals::dsigdMX2dQ2dW2dz_total_checked(double MX2, double Q2, double W2, double z){
double beta=Q2/(Q2+MX2);
double jacobian=beta*beta/Q2;
double result= dsigdbetadQ2dW2dz_total_checked(beta, Q2, W2, z);
return jacobian*result;
}
-double InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(double beta, double Q2, double W2, double z){
+double InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_checked(double beta, double Q2, double W2, double z){
double result = 0;
//
// Check if in kinematically allowed region
double MX2=Kinematics::MX2(Q2, beta, 0);
if (mCheckKinematics && !Kinematics::valid(mS, beta, Q2, W2, z, sqrt(MX2), false, (mSettings->verboseLevel() > 2) )) {
if (mSettings->verboseLevel() > 2)
- cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(): warning, beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z="<< z
+ cout << "InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_checked(): warning, beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z="<< z
<< " is outside of kinematically allowed region. Return 0." << endl;
return 0;
}
double xpom=Kinematics::xpomeron(0, Q2, W2, sqrt(MX2));
if(mA>1)
dipoleModel()->createSigma_ep_LookupTable(xpom);
double csT = dsigdbetadQ2dW2dz_total(beta, Q2, W2, z, transverse);
double csL = dsigdbetadQ2dW2dz_total(beta, Q2, W2, z, longitudinal);
result = csT + csL;
mCrossSectionRatioLT=csL/csT;
//
// Polarization
//
if (mRandom->Uniform(result) <= csT)
mPolarization = transverse;
else
mPolarization = longitudinal;
//
// Quark Species
//
//
if(mPolarization == transverse){
bool isChosen=false;
double cs_rejected=0;
for(int i=0; i<4; i++){
double R=mRandom->Uniform(csT-cs_rejected);
double csTi=mDsigdbetadQ2dWdz_T_total[i];
if(R <= csTi){
mQuarkSpecies=i;
isChosen=true;
break;
}
cs_rejected+=mDsigdbetadQ2dWdz_T_total[i];
}
if(!isChosen) mQuarkSpecies=4;
}
else{
bool isChosen=false;
double cs_rejected=0;
for(int i=0; i<4; i++){
double R=mRandom->Uniform(csL-cs_rejected);
double csLi=mDsigdbetadQ2dWdz_L_total[i];
if(R <= csLi){
mQuarkSpecies=i;
isChosen=true;
break;
}
cs_rejected+=mDsigdbetadQ2dWdz_L_total[i];
}
if(!isChosen) mQuarkSpecies=4;
}
// Print-out at high verbose levels
//
if (mSettings->verboseLevel() > 10) { // Spinal Tap ;-)
- cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(): " << result;
+ cout << "InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_checked(): " << result;
cout << " at beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z;
cout << " (" << (mPolarization == transverse ? "transverse" : "longitudinal");
cout << ')' << endl;
}
//
// Check validity of return value
//
if (std::isnan(result)) {
- cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(): Error, return value = NaN at" << endl;
+ cout << "InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_checked(): Error, return value = NaN at" << endl;
cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z << endl;
result = 0;
}
if (std::isinf(result)) {
- cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(): Error, return value = inf at" << endl;
+ cout << "InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_checked(): Error, return value = inf at" << endl;
cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z << endl;
result = 0;
}
if (result < 0) {
- cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(): Error, negative cross-section at" << endl;
+ cout << "InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_checked(): Error, negative cross-section at" << endl;
cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << endl;
result = 0;
}
mTotalCS=result;
return result; //nb/GeV4
}
-double InclusiveDiffractiveCrossSections::dsigdbetadz_total(double beta, double Q2, double W2, double z, GammaPolarization pol) {
+double InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadz_total(double beta, double Q2, double W2, double z, GammaPolarization pol) {
double result = 0;
if(pol==transverse){
result = dsigmadbetadz_T(beta, Q2, W2, z);
}
else if(pol==longitudinal){
result = dsigmadbetadz_L(beta, Q2, W2, z);
}
return result; //nb
}
-double InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total(double beta, double Q2, double W2, double z, GammaPolarization pol) {
+double InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total(double beta, double Q2, double W2, double z, GammaPolarization pol) {
double result = 0;
for(int i=0; i<5; i++){
setQuarkIndex(i);
double tmpresult = dsigdbetadz_total(beta, Q2, W2, z, pol); //nb
if (mSettings->applyPhotonFlux()) tmpresult *= mPhotonFlux(Q2,W2,pol); //nb/GeV4
if(pol == transverse)
mDsigdbetadQ2dWdz_T_total[i]=tmpresult;
if(pol == longitudinal)
mDsigdbetadQ2dWdz_L_total[i]=tmpresult;
result+=tmpresult;
}
return result; //nb/GeV4
}
-double InclusiveDiffractiveCrossSections::crossSectionOfLastCall(){
+double InclusiveDiffractiveCrossSectionsIntegrals::crossSectionOfLastCall(){
return mTotalCS;
}
-GammaPolarization InclusiveDiffractiveCrossSections::polarizationOfLastCall(){
+GammaPolarization InclusiveDiffractiveCrossSectionsIntegrals::polarizationOfLastCall(){
return mPolarization;
}
-unsigned int InclusiveDiffractiveCrossSections::quarkSpeciesOfLastCall(){
+unsigned int InclusiveDiffractiveCrossSectionsIntegrals::quarkSpeciesOfLastCall(){
return mQuarkSpecies;
}
-double InclusiveDiffractiveCrossSections::quarkMassOfLastCall(){
+double InclusiveDiffractiveCrossSectionsIntegrals::quarkMassOfLastCall(){
// return Settings::quarkMass(mQuarkSpecies); //#TT tmp
- tt_quarkMass[mQuarkSpecies];
+ return tt_quarkMass[mQuarkSpecies];
}
-void InclusiveDiffractiveCrossSections::setQuarkIndex(unsigned int val){mQuarkIndex=val;}
+void InclusiveDiffractiveCrossSectionsIntegrals::setQuarkIndex(unsigned int val){mQuarkIndex=val;}
-double InclusiveDiffractiveCrossSections::dsigmadbetadz_T(double beta, double Q2, double W2, double z) {
+double InclusiveDiffractiveCrossSectionsIntegrals::dsigmadbetadz_T(double beta, double Q2, double W2, double z) {
double MX2 = Q2*(1-beta)/beta;
double xpom = Kinematics::xpomeron(0., Q2, W2, sqrt(MX2));
// double mf = Settings::quarkMass(mQuarkIndex);
double mf = tt_quarkMass[mQuarkIndex]; //#TT tmp
double sqrtArg = 1.-4.*mf*mf/MX2;
if (sqrtArg<0){
if (mSettings->verboseLevel() > 2)
cout<<"There is no phase-space for z, return 0."<<endl;
return 0;
}
double z0 = (1.-sqrt(sqrtArg))/2.;
if (z<z0 or z>1-z0){
if (mSettings->verboseLevel() > 2)
cout<<"z="<<z<<" which is smaller than z0="<<z0<<"or larger than (1-z0)="<<1-z0<<", return 0."<<endl;
return 0;
}
double pt2 = z*(1-z)*Q2-mf*mf;
if (pt2<0){
if (mSettings->verboseLevel() > 2)
cout<<"Not enough phase-space for quark transverse momenta, return 0."<<endl;
return 0;
}
if(z*(1-z)*MX2-mf*mf<0){ //kappa2<0
if (mSettings->verboseLevel() > 2)
cout<<"Not enough phase-space for quark production, return 0."<<endl;
return 0;
}
double epsilon2=z*(1-z)*Q2+mf*mf;
double ef=quarkCharge[mQuarkIndex];
double Phi0=Phi_0(beta, xpom, z, Q2, mf);
double Phi1=Phi_1(beta, xpom, z, Q2, mf);
double prefactor=Nc*Q2*alpha_em/(4.*M_PI*beta*beta)*ef*ef*z*(1-z); //GeV2
prefactor/=2.; //expanded z-range
double term1=epsilon2*(z*z+(1-z)*(1-z))*Phi1; //GeV2*fm6
double term2=mf*mf*Phi0; //GeV2*fm6
double result=prefactor*(term1+term2); //GeV4*fm6
result/=hbarc2*hbarc2; //fm2
result *= 1e7; //nb
return result;//nb
}
-double InclusiveDiffractiveCrossSections::dsigmadbetadz_L(double beta, double Q2, double W2, double z){
+double InclusiveDiffractiveCrossSectionsIntegrals::dsigmadbetadz_L(double beta, double Q2, double W2, double z){
double MX2 = Q2*(1-beta)/beta;
double xpom = Kinematics::xpomeron(0., Q2, W2, sqrt(MX2));
// double mf = Settings::quarkMass(mQuarkIndex);
double mf = tt_quarkMass[mQuarkIndex]; //#TT tmp
double pt2 = z*(1-z)*Q2-mf*mf;
if (pt2<0){
if (mSettings->verboseLevel() > 2)
cout<<"Not enough phase-space for quark transverse momenta, return 0."<<endl;
return 0;
}
double sqrtArg=1.-4.*mf*mf/MX2;
if (sqrtArg<0){
if (mSettings->verboseLevel() > 2)
cout<<"There is no phase-space for z, return 0."<<endl;
return 0;
}
double z0=(1.-sqrt(sqrtArg))/2.;
if (z<z0 or z>1-z0){
if (mSettings->verboseLevel() > 2)
cout<<"z="<<z<<" which is smaller than z0="<<z0<<"or larger than (1-z0)="<<1-z0<<", return 0."<<endl;
return 0;
}
if(z*(1-z)*MX2-mf*mf<0){ //kappa2<0
if (mSettings->verboseLevel() > 2)
cout<<"Not enough phase-space for quark production, return 0."<<endl;
return 0;
}
double ef=quarkCharge[mQuarkIndex];
double Phi0=Phi_0(beta, xpom, z, Q2, mf); //fm6
double term=Nc*Q2*Q2*alpha_em/(M_PI*beta*beta); //GeV4
term*=ef*ef*z*z*z*(1-z)*(1-z)*(1-z);
term*=Phi0; //fm6*GeV4
term/=2.; //expanded z-range
double result=term;
result/=hbarc2*hbarc2; //fm2
result *= 1e7; //nb
return result; //nb
}
-double InclusiveDiffractiveCrossSections::Phi_0(double beta, double xpom, double z, double Q2, double mf){
- TF1* Phi0=new TF1("Phi0", this, &InclusiveDiffractiveCrossSections::uiPhi_0, 0, 30., 0);
+double InclusiveDiffractiveCrossSectionsIntegrals::Phi_0(double beta, double xpom, double z, double Q2, double mf){
+ TF1* Phi0=new TF1("Phi0", this, &InclusiveDiffractiveCrossSectionsIntegrals::uiPhi_0, 0, 30., 0);
ROOT::Math::WrappedTF1* WFPhi0=new ROOT::Math::WrappedTF1(*Phi0);
ROOT::Math::GaussIntegrator GIPhi0;
GIPhi0.SetFunction(*WFPhi0);
GIPhi0.SetRelTolerance(1e-4);
Amp0->SetParameter(0, beta);
Amp0->SetParameter(1, xpom);
Amp0->SetParameter(2, z);
Amp0->SetParameter(3, Q2);
Amp0->SetParameter(5, mf);
double blow=0;
double result=GIPhi0.IntegralUp(blow); //fm6
delete Phi0;
delete WFPhi0;
return result;
}
-double InclusiveDiffractiveCrossSections::Phi_1(double beta, double xpom, double z, double Q2, double mf){
- TF1* Phi1=new TF1("Phi1", this, &InclusiveDiffractiveCrossSections::uiPhi_1, 0, 30., 0);
+double InclusiveDiffractiveCrossSectionsIntegrals::Phi_1(double beta, double xpom, double z, double Q2, double mf){
+ TF1* Phi1=new TF1("Phi1", this, &InclusiveDiffractiveCrossSectionsIntegrals::uiPhi_1, 0, 30., 0);
ROOT::Math::WrappedTF1* WFPhi1=new ROOT::Math::WrappedTF1(*Phi1);
ROOT::Math::GaussIntegrator GIPhi1;
GIPhi1.SetFunction(*WFPhi1);
GIPhi1.SetRelTolerance(1e-4);
Amp1->SetParameter(0, beta);
Amp1->SetParameter(1, xpom);
Amp1->SetParameter(2, z);
Amp1->SetParameter(3, Q2);
Amp1->SetParameter(5, mf);
double blow=0;
double result=GIPhi1.IntegralUp(blow); //fm6
delete Phi1;
delete WFPhi1;
return result;
}
-double InclusiveDiffractiveCrossSections::uiPhi_0(double *var, double *par){
+double InclusiveDiffractiveCrossSectionsIntegrals::uiPhi_0(double *var, double*){
double b=*var;
double amplitude=Amplitude_0(b); //fm2
double result=2*M_PI*b*amplitude*amplitude; //fm5
return result;
}
-double InclusiveDiffractiveCrossSections::uiPhi_1(double *var, double *par){
+double InclusiveDiffractiveCrossSectionsIntegrals::uiPhi_1(double *var, double*){
double b=*var; //fm
double amplitude=Amplitude_1(b); //fm2
double result=2*M_PI*b*amplitude*amplitude; //fm5
return result;
}
-double InclusiveDiffractiveCrossSections::Amplitude_0(double b){
+double InclusiveDiffractiveCrossSectionsIntegrals::Amplitude_0(double b){
//Gauss Integrator defined in header file and set in constructor
Amp0->SetParameter(4, b);
double rlow=1e-3;
double result=GIAmp0.IntegralUp(rlow); //fm2
return result;
}
-double InclusiveDiffractiveCrossSections::Amplitude_1(double b){
+double InclusiveDiffractiveCrossSectionsIntegrals::Amplitude_1(double b){
//Gauss Integrator defined in header file and set in constructor
Amp1->SetParameter(4, b);
double rlow=1e-3;
double result=GIAmp1.IntegralUp(rlow); //fm2
return result;
}
-double InclusiveDiffractiveCrossSections::uiAmplitude_0(double *var, double *par){
+double InclusiveDiffractiveCrossSectionsIntegrals::uiAmplitude_0(double *var, double *par){
double r=*var;
double beta=par[0];
double xpom=par[1];
double z=par[2];
double Q2=par[3];
double b=par[4];
double mf=par[5];
double MX2=Q2*(1-beta)/beta;
double kappa2=z*(1-z)*MX2-mf*mf;
double kappa=sqrt(kappa2);
double epsilon2=z*(1-z)*Q2+mf*mf;
double epsilon=sqrt(epsilon2); //GeV
double besselK0=TMath::BesselK0(epsilon*r/hbarc);
double besselJ0=TMath::BesselJ0(kappa*r/hbarc);
double dsigmadb2=0;
if(mA==1)
dsigmadb2=mDipoleModel->dsigmadb2ep(r, b, xpom);
else
dsigmadb2=mDipoleModel->coherentDsigmadb2(r, b, xpom);
return r*besselK0*besselJ0*dsigmadb2; //fm
}
-double InclusiveDiffractiveCrossSections::uiAmplitude_1(double *var, double *par){
+double InclusiveDiffractiveCrossSectionsIntegrals::uiAmplitude_1(double *var, double *par){
double r=*var; //fm
double beta=par[0];
double xpom=par[1];
double z=par[2];
double Q2=par[3]; //GeV2
double b=par[4];
double mf=par[5];
double MX2=Q2*(1-beta)/beta; //GeV2
double kappa2=z*(1-z)*MX2-mf*mf; //GeV2
double kappa=sqrt(kappa2); //GeV
double epsilon2=z*(1-z)*Q2+mf*mf;
double epsilon=sqrt(epsilon2); //GeV
double besselK1=TMath::BesselK1(epsilon*r/hbarc);
double besselJ1=TMath::BesselJ1(kappa*r/hbarc);
double dsigmadb2=0; //GeV0
if(mA==1)
dsigmadb2=mDipoleModel->dsigmadb2ep(r, b, xpom);
else
dsigmadb2=mDipoleModel->coherentDsigmadb2(r, b, xpom);
return r*besselK1*besselJ1*dsigmadb2; //fm
}
-DipoleModel* InclusiveDiffractiveCrossSections::dipoleModel(){
+DipoleModel* InclusiveDiffractiveCrossSectionsIntegrals::dipoleModel(){
return mDipoleModel;
}
-double InclusiveDiffractiveCrossSections::crossSectionRatioLTOfLastCall() const {return mCrossSectionRatioLT;}
+double InclusiveDiffractiveCrossSectionsIntegrals::crossSectionRatioLTOfLastCall() const {return mCrossSectionRatioLT;}
//===================================================
// QQG Calculations
//===================================================
-double InclusiveDiffractiveCrossSections::unuranPDF_qqg(const double* array){
+double InclusiveDiffractiveCrossSectionsIntegrals::unuranPDF_qqg(const double* array){
//
// array is: beta, log(Q2), W2, z
//
double result = 0;
double Q2 = exp(array[1]);
double z=array[3];
result = dsigdbetadQ2dW2dz_total_qqg_checked(array[0], Q2, array[2], z);
result *= Q2; // Jacobian log(Q2)->Q2
return log(result);
}
-double InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(double beta, double Q2, double W2, double z){
+double InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_qqg_checked(double beta, double Q2, double W2, double z){
//
// Check if in kinematically allowed region
//
double MX2=Kinematics::MX2(Q2, beta, 0);
if(mCheckKinematics && z<beta) {
if (mSettings->verboseLevel() > 2)
cout<<"z<beta, beta="<<beta<<", z="<<z<<endl;
return 0; // For QQG beta < z < 1
}
if (mCheckKinematics && !Kinematics::valid(mS, beta, Q2, W2, z, sqrt(MX2), false, (mSettings->verboseLevel() > 2) )) {
if (mSettings->verboseLevel() > 2)
- cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(): warning, beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z="<< z
+ cout << "InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_qqg_checked(): warning, beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z="<< z
<< " is outside of kinematically allowed region. Return 0." << endl;
return 0;
}
double xpom=Kinematics::xpomeron(0, Q2, W2, sqrt(MX2));
if(mA>1)
dipoleModel()->createSigma_ep_LookupTable(xpom);
double result = dsigdbetadQ2dW2dz_qqg(beta, Q2, W2, z);
//
// Quark Species
//
//
bool isChosen=false;
double cs_rejected=0;
for(int i=0; i<4; i++){
double R=mRandom->Uniform(result-cs_rejected);
double csTi=mDsigdbetadQ2dWdz_T_qqg[i];
if(R <= csTi){
mQuarkSpecies=i;
isChosen=true;
break;
}
cs_rejected+=mDsigdbetadQ2dWdz_T_qqg[i];
}
if(!isChosen) mQuarkSpecies=4;
// Print-out at high verbose levels
//
if (mSettings->verboseLevel() > 10) { // Spinal Tap ;-)
- cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(): " << result;
+ cout << "InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_qqg_checked(): " << result;
cout << " at beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z<< endl;
}
//
// Check validity of return value
//
if (std::isnan(result)) {
- cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(): Error, return value = NaN at" << endl;
+ cout << "InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_qqg_checked(): Error, return value = NaN at" << endl;
cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z << endl;
result = 0;
}
if (std::isinf(result)) {
- cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(): Error, return value = inf at" << endl;
+ cout << "InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_qqg_checked(): Error, return value = inf at" << endl;
cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z << endl;
result = 0;
}
if (result < 0) {
- cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(): Error, negative cross-section at" << endl;
+ cout << "InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_total_qqg_checked(): Error, negative cross-section at" << endl;
cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << endl;
result = 0;
}
mTotalCS_qqg=result;
return result; //nb/GeV4
}
-double InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_qqg(double beta, double Q2, double W2, double z) {
+double InclusiveDiffractiveCrossSectionsIntegrals::dsigdbetadQ2dW2dz_qqg(double beta, double Q2, double W2, double z) {
double result = 0;
for(int i=0; i<5; i++){
setQuarkIndex(i);
// double mf = Settings::quarkMass(mQuarkIndex);
double mf = tt_quarkMass[i]; //#TT tmp
double Mqq2=(z/beta-1)*Q2;
if(Mqq2<4*mf*mf) continue; //Not enough phase-space for the q and qbar
double tmpresult = dsigmadbetadz_QQG(beta, Q2, W2, z); //nb
if (mSettings->applyPhotonFlux()) tmpresult *= mPhotonFlux(Q2,W2,transverse); //nb/GeV4
mDsigdbetadQ2dWdz_T_qqg[i]=tmpresult;
result+=tmpresult;
}
return result; //nb/GeV4
}
-double InclusiveDiffractiveCrossSections::dsigmadbetadz_QQG(double beta, double Q2, double W2, double ztilde) {
+double InclusiveDiffractiveCrossSectionsIntegrals::dsigmadbetadz_QQG(double beta, double Q2, double W2, double ztilde) {
double MX2 = Q2*(1-beta)/beta;
double xpom = Kinematics::xpomeron(0., Q2, W2, sqrt(MX2));
double Phi=Phi_qqg(xpom, ztilde, Q2);
double alpha_S=0.14;
double ef=quarkCharge[mQuarkIndex];
double betafactor=(1-beta/ztilde)*
(1-beta/ztilde)+beta/ztilde*beta/ztilde;
double result=alpha_S*alpha_em/(2*M_PI*M_PI*Q2)*betafactor*ef*ef*Phi; //GeV-2
result*=hbarc2; //fm2
result *= 1e7; //nb
return result; //nb
}
-double InclusiveDiffractiveCrossSections::Phi_qqg(double xpom, double z, double Q2){
+double InclusiveDiffractiveCrossSectionsIntegrals::Phi_qqg(double xpom, double z, double Q2){
Ampqqg->SetParameter(0, xpom);
Ampqqg->SetParameter(1, z);
mQ2=Q2;
- ROOT::Math::Functor wf(this, &InclusiveDiffractiveCrossSections::uiPhi_qqg, 2);
+ ROOT::Math::Functor wf(this, &InclusiveDiffractiveCrossSectionsIntegrals::uiPhi_qqg, 2);
ROOT::Math::IntegratorMultiDim ig(ROOT::Math::IntegrationMultiDim::kADAPTIVE);
ig.SetFunction(wf);
ig.SetAbsTolerance(0.);
ig.SetRelTolerance(1e-4);
double lo[2]={0.,1e-4}; //b, k2
double hi[2]={5., Q2}; //b, k2
double result = ig.Integral(lo, hi)/hbarc; //GeV0
return result; //GeV0
}
-double InclusiveDiffractiveCrossSections::uiPhi_qqg(const double* var) {
+double InclusiveDiffractiveCrossSectionsIntegrals::uiPhi_qqg(const double* var) {
double b=var[0];
double k2=var[1];
double Q2=mQ2;
Ampqqg->SetParameter(2, sqrt(k2));
Ampqqg->SetParameter(3, b);
double rlow=1e-3;
double amp_qqg=GIAmpqqg.IntegralUp(rlow); //fm2
amp_qqg/=hbarc2; //GeV-2
double result = (2*M_PI)*b/hbarc*k2*k2*log(Q2/k2)*amp_qqg*amp_qqg; //GeV-1
return result; //GeV-1
}
-double InclusiveDiffractiveCrossSections::uiAmplitude_qqg(double *var, double *par){
+double InclusiveDiffractiveCrossSectionsIntegrals::uiAmplitude_qqg(double *var, double *par){
double r=*var; //fm
if(r>100.) return 0; //IntegralUp sometimes tries too large values that break the dipole model
double xpom=par[0];
double z=par[1];
double k=par[2]; //GeV
double b=par[3];
double besselK2=ROOT::Math::cyl_bessel_k(2, sqrt(z)*k*r/hbarc);
double besselJ2=ROOT::Math::cyl_bessel_j(2, sqrt(1-z)*k*r/hbarc);
double dsigmadb2=0; //GeV0
if(mA==1)
dsigmadb2=mDipoleModel->dsigmadb2ep(r, b, xpom);
else
dsigmadb2=mDipoleModel->coherentDsigmadb2(r, b, xpom);
double term=1-0.5*dsigmadb2;
double dsigmadb2tilde=2*(1-term*term);
double result=r*besselK2*besselJ2*dsigmadb2tilde; //fm
return result;
}
Index: trunk/src/InclusiveDiffractiveCrossSectionsFromTables.h
===================================================================
--- trunk/src/InclusiveDiffractiveCrossSectionsFromTables.h (revision 0)
+++ trunk/src/InclusiveDiffractiveCrossSectionsFromTables.h (revision 538)
@@ -0,0 +1,95 @@
+#ifndef InclusiveDiffractiveCrossSectionsFromTables_h
+#define InclusiveDiffractiveCrossSectionsFromTables_h
+#include "AlphaStrong.h"
+#include "TH1.h"
+#include "TMath.h"
+#include "TF1.h"
+#include "Math/WrappedTF1.h"
+#include "Math/GaussIntegrator.h"
+#include "DipoleModel.h"
+#include "PhotonFlux.h"
+#include "Enumerations.h"
+#include "Constants.h"
+#include "Table.h"
+#include "THn.h"
+#include <vector>
+#include "InclusiveDiffractiveCrossSections.h"
+
+using namespace std;
+
+class InclusiveDiffractionCrossSectionsFromTables : public InclusiveDiffractiveCrossSections {
+
+public:
+ InclusiveDiffractionCrossSectionsFromTables();
+ ~InclusiveDiffractionCrossSectionsFromTables();
+
+ double operator()(double beta, double Q2, double W2, double z);
+ double operator()(const double* array);
+
+ double unuranPDF(const double*);
+ double unuranPDF_qqg(const double*);
+
+ GammaPolarization polarizationOfLastCall() ;
+ double crossSectionOfLastCall();
+
+ unsigned int quarkSpeciesOfLastCall();
+ double quarkMassOfLastCall();
+ double crossSectionRatioLTOfLastCall() const;
+ void setCheckKinematics(bool);
+ void setFockState(FockState);
+ FockState getFockState();
+
+ double dsigdbetadQ2dW2dz_total(double beta, double Q2, double W2, double z, GammaPolarization) ;
+
+ double dsigdbetadQ2dW2dz_qqg(double beta, double Q2, double W2, double z);
+
+ double dsigdbetadQ2dW2dz_total_checked(double beta, double Q2, double W2, double z);
+ double dsigdbetadQ2dW2dz_total_qqg_checked(double beta, double Q2, double W2, double z);
+
+ double dsigmadbetadz_T(double, double, double, double) ;
+ double dsigmadbetadz_L(double, double, double, double) ;
+ double dsigmadbetadz_QQG(double, double, double, double) ;
+
+ double mDsigdbetadQ2dWdz_L_total[5];
+ double mDsigdbetadQ2dWdz_T_total[5];
+ double mDsigdbetadQ2dWdz_T_qqg[5];
+
+ void setQuarkIndex(unsigned int);
+
+ double interpolate(double beta, double Q2, double W2, double z, GammaPolarization pol, FockState fock, int quark);
+
+ vector<double> mgrid(THnF* hist,int axis, int len);
+
+ vector<THnF*> tableQQ_T;
+ vector<THnF*> tableQQ_L;
+ vector<THnF*> tableQQG;
+
+ DipoleModel* dipoleModel();
+
+protected:
+ double dsigdMX2dQ2dW2dz_total_checked(double MX2, double Q2, double W2, double z);
+ double dsigdbetadz_total(double beta, double Q2, double W2, double z, GammaPolarization pol);
+
+private:
+ TRandom3* mRandom;
+ GammaPolarization mPolarization;
+ PhotonFlux mPhotonFlux;
+ EventGeneratorSettings* mSettings;
+ unsigned int mQuarkSpecies;
+ double mTotalCS, mTotalCS_qqg;
+ FockState mFockState;
+
+ double mS, mQ2;
+
+ bool mCheckKinematics;
+
+ unsigned int mA;
+ unsigned int mQuarkIndex;
+ double mCrossSectionRatioLT;
+
+ DipoleModel* mDipoleModel;
+ DipoleModelParameterSet mDipoleModelParameterSet;
+
+
+};
+#endif
Index: trunk/src/linterp.h
===================================================================
--- trunk/src/linterp.h (revision 0)
+++ trunk/src/linterp.h (revision 538)
@@ -0,0 +1,421 @@
+
+//
+// Copyright (c) 2012 Ronaldo Carpio
+//
+// Permission to use, copy, modify, distribute and sell this software
+// and its documentation for any purpose is hereby granted without fee,
+// provided that the above copyright notice appear in all copies and
+// that both that copyright notice and this permission notice appear
+// in supporting documentation. The authors make no representations
+// about the suitability of this software for any purpose.
+// It is provided "as is" without express or implied warranty.
+//
+
+/*
+This is a C++ header-only library for N-dimensional linear interpolation on a rectangular grid. Implements two methods:
+* Multilinear: Interpolate using the N-dimensional hypercube containing the point. Interpolation step is O(2^N)
+* Simplicial: Interpolate using the N-dimensional simplex containing the point. Interpolation step is O(N log N), but less accurate.
+Requires boost/multi_array library.
+*/
+
+#ifndef _linterp_h
+#define _linterp_h
+
+#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
+#include <float.h>
+#include <cstdarg>
+#include <string>
+#include <vector>
+#include <array>
+#include <functional>
+#include <boost/multi_array.hpp>
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/numeric/ublas/matrix_proxy.hpp>
+#include <boost/numeric/ublas/storage.hpp>
+
+using std::vector;
+using std::array;
+typedef unsigned int uint;
+typedef vector<int> iVec;
+typedef vector<double> dVec;
+
+
+// TODO:
+// - specify behavior past grid boundaries.
+// 1) clamp
+// 2) return a pre-determined value (e.g. NaN)
+
+// compile-time params:
+// 1) number of dimensions
+// 2) scalar type T
+// 3) copy data or not (default: false). The grids will always be copied
+// 4) ref count class (default: none)
+// 5) continuous or not
+
+// run-time constructor params:
+// 1) f
+// 2) grids
+// 3) behavior outside grid: default=clamp
+// 4) value to return outside grid, defaut=nan
+
+struct EmptyClass {};
+
+template <int N, class T, bool CopyData = true, bool Continuous = true, class ArrayRefCountT = EmptyClass, class GridRefCountT = EmptyClass>
+class NDInterpolator {
+public:
+ typedef T value_type;
+ typedef ArrayRefCountT array_ref_count_type;
+ typedef GridRefCountT grid_ref_count_type;
+
+ static const int m_N = N;
+ static const bool m_bCopyData = CopyData;
+ static const bool m_bContinuous = Continuous;
+
+ typedef boost::numeric::ublas::array_adaptor<T> grid_type;
+ typedef boost::const_multi_array_ref<T, N> array_type;
+ typedef std::unique_ptr<array_type> array_type_ptr;
+
+ array_type_ptr m_pF;
+ ArrayRefCountT m_ref_F; // reference count for m_pF
+ vector<T> m_F_copy; // if CopyData == true, this holds the copy of F
+
+ vector<grid_type> m_grid_list;
+ vector<GridRefCountT> m_grid_ref_list; // reference counts for grids
+ vector<vector<T> > m_grid_copy_list; // if CopyData == true, this holds the copies of the grids
+
+ // constructors assume that [f_begin, f_end) is a contiguous array in C-order
+ // non ref-counted constructor.
+ template <class IterT1, class IterT2, class IterT3>
+ NDInterpolator(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end) {
+ init(grids_begin, grids_len_begin, f_begin, f_end);
+ }
+
+ // ref-counted constructor
+ template <class IterT1, class IterT2, class IterT3, class RefCountIterT>
+ NDInterpolator(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end, ArrayRefCountT &refF, RefCountIterT grid_refs_begin) {
+ init_refcount(grids_begin, grids_len_begin, f_begin, f_end, refF, grid_refs_begin);
+ }
+
+ template <class IterT1, class IterT2, class IterT3>
+ void init(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end) {
+ set_grids(grids_begin, grids_len_begin, m_bCopyData);
+ set_f_array(f_begin, f_end, m_bCopyData);
+ }
+ template <class IterT1, class IterT2, class IterT3, class RefCountIterT>
+ void init_refcount(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end, ArrayRefCountT &refF, RefCountIterT grid_refs_begin) {
+ set_grids(grids_begin, grids_len_begin, m_bCopyData);
+ set_grids_refcount(grid_refs_begin, grid_refs_begin + N);
+ set_f_array(f_begin, f_end, m_bCopyData);
+ set_f_refcount(refF);
+ }
+
+ template <class IterT1, class IterT2>
+ void set_grids(IterT1 grids_begin, IterT2 grids_len_begin, bool bCopy) {
+ m_grid_list.clear();
+ m_grid_ref_list.clear();
+ m_grid_copy_list.clear();
+ for (int i=0; i<N; i++) {
+ int gridLength = grids_len_begin[i];
+ if (bCopy == false) {
+ T const *grid_ptr = &(*grids_begin[i]);
+ m_grid_list.push_back(grid_type(gridLength, (T*) grid_ptr )); // use the given pointer
+ } else {
+ m_grid_copy_list.push_back( vector<T>(grids_begin[i], grids_begin[i] + grids_len_begin[i]) ); // make our own copy of the grid
+ T *begin = &(m_grid_copy_list[i][0]);
+ m_grid_list.push_back(grid_type(gridLength, begin)); // use our copy
+ }
+ }
+ }
+ template <class IterT1, class RefCountIterT>
+ void set_grids_refcount(RefCountIterT refs_begin, RefCountIterT refs_end) {
+ assert(refs_end - refs_begin == N);
+ m_grid_ref_list.assign(refs_begin, refs_begin + N);
+ }
+
+ // assumes that [f_begin, f_end) is a contiguous array in C-order
+ template <class IterT>
+ void set_f_array(IterT f_begin, IterT f_end, bool bCopy) {
+ unsigned int nGridPoints = 1;
+ array<int,N> sizes;
+ for (unsigned int i=0; i<m_grid_list.size(); i++) {
+ sizes[i] = m_grid_list[i].size();
+ nGridPoints *= sizes[i];
+ }
+
+ int f_len = f_end - f_begin;
+ if ( (m_bContinuous && f_len != nGridPoints) || (!m_bContinuous && f_len != 2 * nGridPoints) ) {
+ throw std::invalid_argument("f has wrong size");
+ }
+ for (unsigned int i=0; i<m_grid_list.size(); i++) {
+ if (!m_bContinuous) { sizes[i] *= 2; }
+ }
+
+ m_F_copy.clear();
+ if (bCopy == false) {
+ m_pF.reset(new array_type(f_begin, sizes));
+ } else {
+ m_F_copy = vector<T>(f_begin, f_end);
+ m_pF.reset(new array_type(&m_F_copy[0], sizes));
+ }
+ }
+ void set_f_refcount(ArrayRefCountT &refF) {
+ m_ref_F = refF;
+ }
+
+ // -1 is before the first grid point
+ // N-1 (where grid.size() == N) is after the last grid point
+ int find_cell(int dim, T x) const {
+ grid_type const &grid(m_grid_list[dim]);
+ if (x < *(grid.begin())) return -1;
+ else if (x >= *(grid.end()-1)) return grid.size()-1;
+ else {
+ auto i_upper = std::upper_bound(grid.begin(), grid.end(), x);
+ return i_upper - grid.begin() - 1;
+ }
+ }
+
+ // return the value of f at the given cell and vertex
+ T get_f_val(array<int,N> const &cell_index, array<int,N> const &v_index) const {
+ array<int,N> f_index;
+
+ if (m_bContinuous) {
+ for (int i=0; i<N; i++) {
+ if (cell_index[i] < 0) {
+ f_index[i] = 0;
+ } else if (cell_index[i] >= m_grid_list[i].size()-1) {
+ f_index[i] = m_grid_list[i].size()-1;
+ } else {
+ f_index[i] = cell_index[i] + v_index[i];
+ }
+ }
+ } else {
+ for (int i=0; i<N; i++) {
+ if (cell_index[i] < 0) {
+ f_index[i] = 0;
+ } else if (cell_index[i] >= m_grid_list[i].size()-1) {
+ f_index[i] = (2*m_grid_list[i].size())-1;
+ } else {
+ f_index[i] = 1 + (2*cell_index[i]) + v_index[i];
+ }
+ }
+ }
+ return (*m_pF)(f_index);
+ }
+
+ T get_f_val(array<int,N> const &cell_index, int v) const {
+ array<int,N> v_index;
+ for (int dim=0; dim<N; dim++) {
+ v_index[dim] = (v >> (N-dim-1)) & 1; // test if the i-th bit is set
+ }
+ return get_f_val(cell_index, v_index);
+ }
+};
+
+template <int N, class T, bool CopyData = true, bool Continuous = true, class ArrayRefCountT = EmptyClass, class GridRefCountT = EmptyClass>
+class InterpSimplex : public NDInterpolator<N,T,CopyData,Continuous,ArrayRefCountT,GridRefCountT> {
+public:
+ typedef NDInterpolator<N,T,CopyData,Continuous,ArrayRefCountT,GridRefCountT> super;
+
+ template <class IterT1, class IterT2, class IterT3>
+ InterpSimplex(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end)
+ : super(grids_begin, grids_len_begin, f_begin, f_end)
+ {}
+ template <class IterT1, class IterT2, class IterT3, class RefCountIterT>
+ InterpSimplex(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end, ArrayRefCountT &refF, RefCountIterT ref_begins)
+ : super(grids_begin, grids_len_begin, f_begin, f_end, refF, ref_begins)
+ {}
+
+ template <class IterT>
+ T interp(IterT x_begin) const {
+ array<T,1> result;
+ array< array<T,1>, N > coord_iter;
+ for (int i=0; i<N; i++) {
+ coord_iter[i][0] = x_begin[i];
+ }
+ interp_vec(1, coord_iter.begin(), coord_iter.end(), result.begin());
+ return result[0];
+ }
+
+ template <class IterT1, class IterT2>
+ void interp_vec(int n, IterT1 coord_iter_begin, IterT1 coord_iter_end, IterT2 i_result) const {
+ assert(N == coord_iter_end - coord_iter_begin);
+
+ array<int,N> cell_index, v_index;
+ array<std::pair<T, int>,N> xipair;
+ int c;
+ T y, v0, v1;
+ //mexPrintf("%d\n", n);
+ for (int i=0; i<n; i++) { // for each point
+ for (int dim=0; dim<N; dim++) {
+ typename super::grid_type const &grid(super::m_grid_list[dim]);
+ c = this->find_cell(dim, coord_iter_begin[dim][i]);
+ //mexPrintf("%d\n", c);
+ if (c == -1) { // before first grid point
+ y = 1.0;
+ } else if (c == grid.size()-1) { // after last grid point
+ y = 0.0;
+ } else {
+ //mexPrintf("%f %f\n", grid[c], grid[c+1]);
+ y = (coord_iter_begin[dim][i] - grid[c]) / (grid[c + 1] - grid[c]);
+ if (y < 0.0) y=0.0;
+ else if (y > 1.0) y=1.0;
+ }
+ xipair[dim].first = y;
+ xipair[dim].second = dim;
+ cell_index[dim] = c;
+ }
+ // sort xi's and get the permutation
+ std::sort(xipair.begin(), xipair.end(), [](std::pair<T, int> const &a, std::pair<T, int> const &b) {
+ return (a.first < b.first);
+ });
+ // walk the vertices of the simplex determined by the permutation
+ for (int j=0; j<N; j++) {
+ v_index[j] = 1;
+ }
+ v0 = this->get_f_val(cell_index, v_index);
+ y = v0;
+ for (int j=0; j<N; j++) {
+ v_index[xipair[j].second]--;
+ v1 = this->get_f_val(cell_index, v_index);
+ y += (1.0 - xipair[j].first) * (v1-v0); // interpolate
+ v0 = v1;
+ }
+ *i_result++ = y;
+ }
+ }
+};
+
+
+template <int N, class T, bool CopyData = true, bool Continuous = true, class ArrayRefCountT = EmptyClass, class GridRefCountT = EmptyClass>
+class InterpMultilinear : public NDInterpolator<N,T,CopyData,Continuous,ArrayRefCountT,GridRefCountT> {
+public:
+ typedef NDInterpolator<N,T,CopyData,Continuous,ArrayRefCountT,GridRefCountT> super;
+
+ template <class IterT1, class IterT2, class IterT3>
+ InterpMultilinear(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end)
+ : super(grids_begin, grids_len_begin, f_begin, f_end)
+ {}
+ template <class IterT1, class IterT2, class IterT3, class RefCountIterT>
+ InterpMultilinear(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end, ArrayRefCountT &refF, RefCountIterT ref_begins)
+ : super(grids_begin, grids_len_begin, f_begin, f_end, refF, ref_begins)
+ {}
+
+ template <class IterT1, class IterT2>
+ static T linterp_nd_unitcube(IterT1 f_begin, IterT1 f_end, IterT2 xi_begin, IterT2 xi_end) {
+ int n = xi_end - xi_begin;
+ int f_len = f_end - f_begin;
+ assert(1 << n == f_len);
+ T sub_lower, sub_upper;
+ if (n == 1) {
+ sub_lower = f_begin[0];
+ sub_upper = f_begin[1];
+ } else {
+ sub_lower = linterp_nd_unitcube(f_begin, f_begin + (f_len/2), xi_begin + 1, xi_end);
+ sub_upper = linterp_nd_unitcube(f_begin + (f_len/2), f_end, xi_begin + 1, xi_end);
+ }
+ T result = sub_lower + (*xi_begin)*(sub_upper - sub_lower);
+ return result;
+ }
+
+ template <class IterT>
+ T interp(IterT x_begin) const {
+ array<T,1> result;
+ array< array<T,1>, N > coord_iter;
+ for (int i=0; i<N; i++) {
+ coord_iter[i][0] = x_begin[i];
+ }
+ interp_vec(1, coord_iter.begin(), coord_iter.end(), result.begin());
+ return result[0];
+ }
+
+ template <class IterT1, class IterT2>
+ void interp_vec(int n, IterT1 coord_iter_begin, IterT1 coord_iter_end, IterT2 i_result) const {
+ assert(N == coord_iter_end - coord_iter_begin);
+ array<int,N> index;
+ int c;
+ T y, xi;
+ vector<T> f(1 << N);
+ array<T,N> x;
+
+ for (int i=0; i<n; i++) { // loop over each point
+ for (int dim=0; dim<N; dim++) { // loop over each dimension
+ auto const &grid(super::m_grid_list[dim]);
+ xi = coord_iter_begin[dim][i];
+ c = this->find_cell(dim, coord_iter_begin[dim][i]);
+ if (c == -1) { // before first grid point
+ y = 1.0;
+ } else if (c == grid.size()-1) { // after last grid point
+ y = 0.0;
+ } else {
+ y = (coord_iter_begin[dim][i] - grid[c]) / (grid[c + 1] - grid[c]);
+ if (y < 0.0) y=0.0;
+ else if (y > 1.0) y=1.0;
+ }
+ index[dim] = c;
+ x[dim] = y;
+ }
+ // copy f values at vertices
+ for (int v=0; v < (1 << N); v++) { // loop over each vertex of hypercube
+ f[v] = this->get_f_val(index, v);
+ }
+ *i_result++ = linterp_nd_unitcube(f.begin(), f.end(), x.begin(), x.end());
+ }
+ }
+};
+
+
+typedef InterpSimplex<1,double> NDInterpolator_1_S;
+typedef InterpSimplex<2,double> NDInterpolator_2_S;
+typedef InterpSimplex<3,double> NDInterpolator_3_S;
+typedef InterpSimplex<4,double> NDInterpolator_4_S;
+typedef InterpSimplex<5,double> NDInterpolator_5_S;
+
+typedef InterpMultilinear<1,double> NDInterpolator_1_ML;
+typedef InterpMultilinear<2,double> NDInterpolator_2_ML;
+typedef InterpMultilinear<3,double> NDInterpolator_3_ML;
+typedef InterpMultilinear<4,double> NDInterpolator_4_ML;
+typedef InterpMultilinear<5,double> NDInterpolator_5_ML;
+
+
+// C interface
+extern "C" {
+ void linterp_simplex_1(double **grids_begin, int *grid_len_begin, double *pF, int xi_len, double **xi_begin, double *pResult);
+ void linterp_simplex_2(double **grids_begin, int *grid_len_begin, double *pF, int xi_len, double **xi_begin, double *pResult);
+ void linterp_simplex_3(double **grids_begin, int *grid_len_begin, double *pF, int xi_len, double **xi_begin, double *pResult);
+}
+
+void inline linterp_simplex_1(double **grids_begin, int *grid_len_begin, double *pF, int xi_len, double **xi_begin, double *pResult) {
+ const int N=1;
+ size_t total_size = 1;
+ for (int i=0; i<N; i++) {
+ total_size *= grid_len_begin[i];
+ }
+ InterpSimplex<N, double, false> interp_obj(grids_begin, grid_len_begin, pF, pF + total_size);
+ interp_obj.interp_vec(xi_len, xi_begin, xi_begin + N, pResult);
+}
+
+void inline linterp_simplex_2(double **grids_begin, int *grid_len_begin, double *pF, int xi_len, double **xi_begin, double *pResult) {
+ const int N=2;
+ size_t total_size = 1;
+ for (int i=0; i<N; i++) {
+ total_size *= grid_len_begin[i];
+ }
+ InterpSimplex<N, double, false> interp_obj(grids_begin, grid_len_begin, pF, pF + total_size);
+ interp_obj.interp_vec(xi_len, xi_begin, xi_begin + N, pResult);
+}
+
+void inline linterp_simplex_3(double **grids_begin, int *grid_len_begin, double *pF, int xi_len, double **xi_begin, double *pResult) {
+ const int N=3;
+ size_t total_size = 1;
+ for (int i=0; i<N; i++) {
+ total_size *= grid_len_begin[i];
+ }
+ InterpSimplex<N, double, false> interp_obj(grids_begin, grid_len_begin, pF, pF + total_size);
+ interp_obj.interp_vec(xi_len, xi_begin, xi_begin + N, pResult);
+}
+
+
+
+#endif //_linterp_h
Index: trunk/src/InclusiveDiffractiveCrossSections.h
===================================================================
--- trunk/src/InclusiveDiffractiveCrossSections.h (revision 537)
+++ trunk/src/InclusiveDiffractiveCrossSections.h (revision 538)
@@ -1,126 +1,170 @@
//==============================================================================
// InclusiveDiffractiveCrossSection.h
//
// Copyright (C) 2024 Tobias Toll and Thomas Ullrich
//
// This file is part of Sartre.
//
// This program 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.
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author: Tobias Toll
// Last update:
// $Date: 2024-06-03 11:27:05 -0400 (Mon, 03 Jun 2024) $
// $Author: ullrich $
//==============================================================================
#ifndef InclusiveDiffractiveCrossSections_h
#define InclusiveDiffractiveCrossSections_h
#include "AlphaStrong.h"
#include "TH1.h"
#include "TMath.h"
#include "TF1.h"
#include "Math/WrappedTF1.h"
#include "Math/GaussIntegrator.h"
#include "DipoleModel.h"
#include "PhotonFlux.h"
#include "Enumerations.h"
#include "Constants.h"
+#include "Table.h"
+#include "THn.h"
class DipoleModel;
class DipoleModelParameters;
-class InclusiveDiffractiveCrossSections {
-
+
+class InclusiveDiffractiveCrossSections{
public:
InclusiveDiffractiveCrossSections();
- ~InclusiveDiffractiveCrossSections();
+ virtual ~InclusiveDiffractiveCrossSections();
+ virtual double operator()(double beta, double Q2, double W2, double z);
+ virtual double operator()(const double* array);
+
+ virtual DipoleModel* dipoleModel();
+ virtual double unuranPDF(const double*);
+ virtual double unuranPDF_qqg(const double*);
+ virtual void setCheckKinematics(bool);
+ virtual void setFockState(FockState);
+
+ virtual GammaPolarization polarizationOfLastCall() ;
+ virtual double crossSectionOfLastCall();
+ virtual unsigned int quarkSpeciesOfLastCall();
+ virtual double quarkMassOfLastCall();
+ virtual double crossSectionRatioLTOfLastCall() const;
+
+ virtual void setQuarkIndex(unsigned int);
+
+ virtual double dsigmadbetadz_T(double, double, double, double) ;
+ virtual double dsigmadbetadz_L(double, double, double, double) ;
+
+ virtual double dsigdbetadQ2dW2dz_total_checked(double beta, double Q2, double W2, double z);
+ virtual double dsigdbetadQ2dW2dz_total_qqg_checked(double beta, double Q2, double W2, double z);
+
+ virtual double dsigdbetadQ2dW2dz_total(double beta, double Q2, double W2, double z, GammaPolarization) ;
+
+ virtual double dsigdbetadQ2dW2dz_qqg(double beta, double Q2, double W2, double z);
+
+ virtual double* dsigdbetadQ2dWdz_T_total();
+ virtual double* dsigdbetadQ2dWdz_L_total();
+ virtual double* dsigdbetadQ2dWdz_T_qqg();
+
+};
+
+class InclusiveDiffractiveCrossSectionsIntegrals: public InclusiveDiffractiveCrossSections{
+
+public:
+ InclusiveDiffractiveCrossSectionsIntegrals();
+ ~InclusiveDiffractiveCrossSectionsIntegrals();
double operator()(double beta, double Q2, double W2, double z);
double operator()(const double* array);
double unuranPDF(const double*);
double unuranPDF_qqg(const double*);
GammaPolarization polarizationOfLastCall() ;
double crossSectionOfLastCall();
unsigned int quarkSpeciesOfLastCall();
double quarkMassOfLastCall();
double crossSectionRatioLTOfLastCall() const;
void setCheckKinematics(bool);
void setFockState(FockState);
FockState getFockState();
double dsigdbetadQ2dW2dz_total(double beta, double Q2, double W2, double z, GammaPolarization) ;
double dsigdbetadQ2dW2dz_qqg(double beta, double Q2, double W2, double z);
// InclusiveDiffractiveCrossSections(const InclusiveDiffractiveCrossSections&);
// InclusiveDiffractiveCrossSections& operator=(const InclusiveDiffractiveCrossSections&);
double dsigdbetadQ2dW2dz_total_checked(double beta, double Q2, double W2, double z);
double dsigdbetadQ2dW2dz_total_qqg_checked(double beta, double Q2, double W2, double z);
DipoleModel* dipoleModel();
double dsigmadbetadz_T(double, double, double, double) ;
double dsigmadbetadz_L(double, double, double, double) ;
double dsigmadbetadz_QQG(double, double, double, double) ;
- double mDsigdbetadQ2dWdz_L_total[5];
- double mDsigdbetadQ2dWdz_T_total[5];
- double mDsigdbetadQ2dWdz_T_qqg[5];
+ double* dsigdbetadQ2dWdz_T_total(){return mDsigdbetadQ2dWdz_L_total;}
+ double* dsigdbetadQ2dWdz_L_total(){return mDsigdbetadQ2dWdz_T_total;}
+ double* dsigdbetadQ2dWdz_T_qqg(){ return mDsigdbetadQ2dWdz_T_qqg;};
void setQuarkIndex(unsigned int);
protected:
double dsigdMX2dQ2dW2dz_total_checked(double MX2, double Q2, double W2, double z);
double dsigdbetadz_total(double beta, double Q2, double W2, double z, GammaPolarization pol);
private:
TRandom3* mRandom;
GammaPolarization mPolarization;
PhotonFlux mPhotonFlux;
EventGeneratorSettings* mSettings;
unsigned int mQuarkSpecies;
double mTotalCS, mTotalCS_qqg;
FockState mFockState;
double mS, mQ2;
bool mCheckKinematics;
double Phi_0(double, double, double, double, double);
double Phi_1(double, double, double, double, double);
double Phi_qqg(double, double, double);
double uiPhi_0(double*, double*);
double uiPhi_1(double*, double*);
double Amplitude_0(double);
double Amplitude_1(double);
double uiAmplitude_0(double*, double*);
double uiAmplitude_1(double*, double*);
double uiPhi_qqg(const double*);
double uiAmplitude_qqg(double*, double*);
unsigned int mA;
unsigned int mQuarkIndex;
double mCrossSectionRatioLT;
+ double mDsigdbetadQ2dWdz_L_total[5];
+ double mDsigdbetadQ2dWdz_T_total[5];
+ double mDsigdbetadQ2dWdz_T_qqg[5];
+
DipoleModel* mDipoleModel;
DipoleModelParameterSet mDipoleModelParameterSet;
TF1 *Amp0, *Amp1, *Ampqqg;
ROOT::Math::WrappedTF1 *WFAmp0, *WFAmp1, *WFAmpqqg;
ROOT::Math::GaussIntegrator GIAmp0, GIAmp1, GIAmpqqg;
};
#endif
Index: trunk/src/SartreInclusiveDiffraction.h
===================================================================
--- trunk/src/SartreInclusiveDiffraction.h (revision 537)
+++ trunk/src/SartreInclusiveDiffraction.h (revision 538)
@@ -1,120 +1,124 @@
//==============================================================================
// SartreInclusiveDiffraction.h
//
// Copyright (C) 2024 Tobias Toll and Thomas Ullrich
//
// This file is part of Sartre.
//
// This program 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.
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author: Tobias Toll
// Last update:
// $Date: 2024-06-03 11:27:05 -0400 (Mon, 03 Jun 2024) $
// $Author: ullrich $
//==============================================================================
#ifndef SartreInclusiveDiffraction_h
#define SartreInclusiveDiffraction_h
#include "Event.h"
#include "EventGeneratorSettings.h"
#include "InclusiveFinalStateGenerator.h"
#include "InclusiveDiffractiveCrossSections.h"
+#include "InclusiveDiffractiveCrossSectionsFromTables.h"
#include "FrangibleNucleus.h"
#include "Enumerations.h"
#include "TLorentzVector.h"
#include "Math/Functor.h"
#include "TUnuran.h"
#include <ctime>
#include <iostream>
#include <vector>
using namespace std;
class TUnuranMultiContDist;
class SartreInclusiveDiffraction {
public:
SartreInclusiveDiffraction();
virtual ~SartreInclusiveDiffraction();
virtual bool init(const char* = 0);
virtual bool init(const string&);
virtual Event* generateEvent();
virtual double totalCrossSection(); // in kinematic limits used for generation
virtual double totalCrossSection(double lower[4], double upper[4]); // beta, Q2, W, z
virtual double integrationVolume();
EventGeneratorSettings* runSettings();
const FrangibleNucleus* nucleus() const;
void listStatus(ostream& os=cout) const;
time_t runTime() const;
vector<pair<double,double> > kinematicLimits(); // t, Q2, W
private:
virtual double calculateTotalCrossSection(double lower[4], double upper[4]); //beta, Q2, W, z
private:
TRandom3* mRandom;
SartreInclusiveDiffraction(const SartreInclusiveDiffraction&);
SartreInclusiveDiffraction operator=(const SartreInclusiveDiffraction&);
bool mIsInitialized;
time_t mStartTime;
unsigned long mEvents;
unsigned long mTries;
double mTotalCrossSection;
double mTotalCrossSection_qq, mTotalCrossSection_qqg;
TLorentzVector mElectronBeam;
TLorentzVector mHadronBeam;
double mS;
unsigned int mA;
int mVmID;
DipoleModelType mDipoleModelType;
DipoleModelParameterSet mDipoleModelParameterSet;
Event *mCurrentEvent;
FrangibleNucleus *mNucleus;
FrangibleNucleus *mUpcNucleus;
+
+ bool mUseCrossSectionTables;
InclusiveDiffractiveCrossSections *mCrossSection;
+ InclusiveDiffractionCrossSectionsFromTables *mCrossSectionFromTables;
EventGeneratorSettings *mSettings;
double mLowerLimit[4]; // beta, Q2, W2, z
double mUpperLimit[4]; // beta, Q2, W2, z
double mLowerLimit_qqg[4]; // beta, Q2, W2, z
double mUpperLimit_qqg[4]; // beta, Q2, W2, z
ROOT::Math::Functor *mPDF_Functor;
TUnuran *mUnuran;
TUnuranMultiContDist *mPDF;
ROOT::Math::Functor *mPDF_Functor_qqg;
TUnuran *mUnuran_qqg;
TUnuranMultiContDist *mPDF_qqg;
unsigned long mEventCounter;
unsigned long mTriesCounter;
InclusiveFinalStateGenerator mFinalStateGenerator;
double cross_section_wrapper(double*, double*);
double crossSectionsClassWrapper(const double*);
};
ostream& operator<<(ostream& os, const TLorentzVector&);
#endif
Index: trunk/src/InclusiveDiffractiveCrossSectionsFromTables.cpp
===================================================================
--- trunk/src/InclusiveDiffractiveCrossSectionsFromTables.cpp (revision 0)
+++ trunk/src/InclusiveDiffractiveCrossSectionsFromTables.cpp (revision 538)
@@ -0,0 +1,579 @@
+#include "InclusiveDiffractiveCrossSectionsFromTables.h"
+#include <TFile.h>
+#include "Math/SpecFunc.h"
+#include "TFile.h"
+#include <iostream>
+#include <cmath>
+#include <algorithm>
+#include <algorithm>
+#include "Constants.h"
+#include "Nucleus.h"
+#include "DipoleModel.h"
+#include "AlphaStrong.h"
+#include "Math/IntegratorMultiDim.h"
+#include "Math/Functor.h"
+#include "TMath.h"
+#include "TableGeneratorSettings.h"
+#include "Settings.h"
+#include "Enumerations.h"
+#include "DglapEvolution.h"
+#include "Math/WrappedTF1.h"
+#include "Math/GaussIntegrator.h"
+#include "Kinematics.h"
+#include "linterp.h"
+
+#define PR(x) cout << #x << " = " << (x) << endl;
+
+using namespace std;
+
+InclusiveDiffractionCrossSectionsFromTables::InclusiveDiffractionCrossSectionsFromTables(){
+
+ mSettings = EventGeneratorSettings::instance();
+ mRandom = mSettings->randomGenerator();
+ mS = Kinematics::s(mSettings->eBeam(), mSettings->hBeam());
+ mPhotonFlux.setS(mS);
+ mCheckKinematics = true;
+ mCrossSectionRatioLT = 0;
+
+ mQ2=0;
+
+ mA=mSettings->A();
+
+ if(mDipoleModel) delete mDipoleModel;
+
+ mDipoleModelParameterSet = mSettings->dipoleModelParameterSet();
+ DipoleModelType model=mSettings->dipoleModelType();
+ if (model==bSat) {
+ mDipoleModel = new DipoleModel_bSat(mSettings);
+ }
+ else if(model==bNonSat){
+ mDipoleModel = new DipoleModel_bNonSat(mSettings);
+ }
+ else {
+ cout << "Integrals::init(): Error, model not implemented: "<< model << endl;
+ exit(1);
+ }
+
+ //
+ // Set up the lookup tables:
+ //
+ TFile* fileQQ_T0 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q0_bin0-10000_TQQ.root", "READ");
+ TFile* fileQQ_T1 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q1_bin0-10000_TQQ.root", "READ");
+ TFile* fileQQ_T2 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q2_bin0-10000_TQQ.root", "READ");
+ TFile* fileQQ_T3 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q3_bin0-10000_TQQ.root", "READ");
+
+ TFile* fileQQ_L0 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q0_bin0-10000_LQQ.root", "READ");
+ TFile* fileQQ_L1 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q1_bin0-10000_LQQ.root", "READ");
+ TFile* fileQQ_L2 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q2_bin0-10000_LQQ.root", "READ");
+ TFile* fileQQ_L3 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q3_bin0-10000_LQQ.root", "READ");
+
+ TFile* fileQQG_0 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q0_bin0-10000_TQQG.root", "READ");
+ TFile* fileQQG_1 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q1_bin0-10000_TQQG.root", "READ");
+ TFile* fileQQG_2 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q2_bin0-10000_TQQG.root", "READ");
+ TFile* fileQQG_3 = TFile::Open("/Users/tbu/sartre_SVN/sartre/examples/inclusiveTables/incdifftest_bSat_STU_q3_bin0-10000_TQQG.root", "READ");
+
+ tableQQ_T.clear();
+ tableQQ_L.clear();
+ tableQQG.clear();
+
+ // Retrieve the histograms
+ THnF* histQQ_T0 = dynamic_cast<THnF*>(fileQQ_T0->Get("table"));
+ THnF* histQQ_T1 = dynamic_cast<THnF*>(fileQQ_T1->Get("table"));
+ THnF* histQQ_T2 = dynamic_cast<THnF*>(fileQQ_T2->Get("table"));
+ THnF* histQQ_T3 = dynamic_cast<THnF*>(fileQQ_T3->Get("table"));
+
+ THnF* histQQ_L0 = dynamic_cast<THnF*>(fileQQ_L0->Get("table"));
+ THnF* histQQ_L1 = dynamic_cast<THnF*>(fileQQ_L1->Get("table"));
+ THnF* histQQ_L2 = dynamic_cast<THnF*>(fileQQ_L2->Get("table"));
+ THnF* histQQ_L3 = dynamic_cast<THnF*>(fileQQ_L3->Get("table"));
+
+ THnF* histQQG_0 = dynamic_cast<THnF*>(fileQQG_0->Get("table"));
+ THnF* histQQG_1 = dynamic_cast<THnF*>(fileQQG_1->Get("table"));
+ THnF* histQQG_2 = dynamic_cast<THnF*>(fileQQG_2->Get("table"));
+ THnF* histQQG_3 = dynamic_cast<THnF*>(fileQQG_3->Get("table"));
+
+ tableQQ_T.push_back(histQQ_T0);
+ tableQQ_T.push_back(histQQ_T1);
+ tableQQ_T.push_back(histQQ_T2);
+ tableQQ_T.push_back(histQQ_T3);
+
+ tableQQ_L.push_back(histQQ_L0);
+ tableQQ_L.push_back(histQQ_L1);
+ tableQQ_L.push_back(histQQ_L2);
+ tableQQ_L.push_back(histQQ_L3);
+
+ tableQQG.push_back(histQQG_0);
+ tableQQG.push_back(histQQG_1);
+ tableQQG.push_back(histQQG_2);
+ tableQQG.push_back(histQQG_3);
+
+ // if (!hist4D) {
+ // std::cerr << "Error: Histogram 'hist4D' not found!" << std::endl;
+ // file->Close();
+ // return -1;
+ // }
+}
+InclusiveDiffractionCrossSectionsFromTables::~InclusiveDiffractionCrossSectionsFromTables(){
+}
+
+void InclusiveDiffractionCrossSectionsFromTables::setCheckKinematics(bool val) {mCheckKinematics = val;}
+
+void InclusiveDiffractionCrossSectionsFromTables::setFockState(FockState val){
+ mFockState=val;
+}
+
+FockState InclusiveDiffractionCrossSectionsFromTables::getFockState(){
+ return mFockState;
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::operator()(double MX2, double Q2, double W2, double z){
+ return dsigdMX2dQ2dW2dz_total_checked(MX2, Q2, W2, z);
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::operator()(const double* array){
+ double result=0;
+ if(mFockState==QQ or mFockState==ALL){
+ result+=dsigdbetadQ2dW2dz_total_checked(array[0], array[1], array[2], array[3]);
+ }
+ else if(mFockState==QQG or
+ mFockState==ALL){
+ result+=dsigdbetadQ2dW2dz_total_qqg_checked(array[0], array[1], array[2], array[3]);
+ }
+ else{
+ cout<<"InclusiveDiffractiveCrossSections::operator(): Fockstate is invalid, stopping"<<endl;
+ exit(0);
+ }
+ return result;
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::unuranPDF(const double* array){
+ //
+ // array is: beta, log(Q2), W2, z
+ //
+ double result = 0;
+ double Q2 = exp(array[1]);
+ result = dsigdbetadQ2dW2dz_total_checked(array[0], Q2, array[2], array[3]);
+ result *= Q2; // Jacobian
+ return log(result);
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::dsigdMX2dQ2dW2dz_total_checked(double MX2, double Q2, double W2, double z){
+ double beta=Q2/(Q2+MX2);
+ double jacobian=beta*beta/Q2;
+ double result= dsigdbetadQ2dW2dz_total_checked(beta, Q2, W2, z);
+ return jacobian*result;
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::dsigdbetadQ2dW2dz_total_checked(double beta, double Q2, double W2, double z){
+ double result = 0;
+
+ //
+ // Check if in kinematically allowed region
+ double MX2=Kinematics::MX2(Q2, beta, 0);
+ if (mCheckKinematics && !Kinematics::valid(mS, beta, Q2, W2, z, sqrt(MX2), false, (mSettings->verboseLevel() > 2) )) {
+ if (mSettings->verboseLevel() > 2)
+ cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(): warning, beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z="<< z
+ << " is outside of kinematically allowed region. Return 0." << endl;
+ return 0;
+ }
+ double csT = dsigdbetadQ2dW2dz_total(beta, Q2, W2, z, transverse);
+ double csL = dsigdbetadQ2dW2dz_total(beta, Q2, W2, z, longitudinal);
+ result = csT + csL;
+
+ mCrossSectionRatioLT=csL/csT;
+ //
+ // Polarization
+ //
+ if (mRandom->Uniform(result) <= csT)
+ mPolarization = transverse;
+ else
+ mPolarization = longitudinal;
+ //
+ // Quark Species
+ //
+ //
+ if(mPolarization == transverse){
+ bool isChosen=false;
+ double cs_rejected=0;
+ for(int i=0; i<4; i++){
+ double R=mRandom->Uniform(csT-cs_rejected);
+ double csTi=mDsigdbetadQ2dWdz_T_total[i];
+ if(R <= csTi){
+ mQuarkSpecies=i;
+ isChosen=true;
+ break;
+ }
+ cs_rejected+=mDsigdbetadQ2dWdz_T_total[i];
+ }
+ if(!isChosen) mQuarkSpecies=4;
+ }
+ else{
+ bool isChosen=false;
+ double cs_rejected=0;
+ for(int i=0; i<4; i++){
+ double R=mRandom->Uniform(csL-cs_rejected);
+ double csLi=mDsigdbetadQ2dWdz_L_total[i];
+ if(R <= csLi){
+ mQuarkSpecies=i;
+ isChosen=true;
+ break;
+ }
+ cs_rejected+=mDsigdbetadQ2dWdz_L_total[i];
+ }
+ if(!isChosen) mQuarkSpecies=4;
+ }
+ // Print-out at high verbose levels
+ //
+ if (mSettings->verboseLevel() > 10) { // Spinal Tap ;-)
+ cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(): " << result;
+ cout << " at beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z;
+ cout << " (" << (mPolarization == transverse ? "transverse" : "longitudinal");
+ cout << ')' << endl;
+ }
+ //
+ // Check validity of return value
+ //
+ if (std::isnan(result)) {
+ cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(): Error, return value = NaN at" << endl;
+ cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z << endl;
+ result = 0;
+ }
+ if (std::isinf(result)) {
+ cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(): Error, return value = inf at" << endl;
+ cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z << endl;
+ result = 0;
+ }
+ if (result < 0) {
+ cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_checked(): Error, negative cross-section at" << endl;
+ cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << endl;
+ result = 0;
+ }
+ mTotalCS=result;
+ return result; //nb/GeV4
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::dsigdbetadz_total(double beta, double Q2, double W2, double z, GammaPolarization pol) {
+ double result = 0;
+ if(pol==transverse){
+ result = dsigmadbetadz_T(beta, Q2, W2, z);
+ }
+ else if(pol==longitudinal){
+ result = dsigmadbetadz_L(beta, Q2, W2, z);
+ }
+ return result; //nb
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::dsigdbetadQ2dW2dz_total(double beta, double Q2, double W2, double z, GammaPolarization pol) {
+ double result = 0;
+ for(int i=0; i<4; i++){
+ setQuarkIndex(i);
+ double tmpresult = dsigdbetadz_total(beta, Q2, W2, z, pol); //nb
+ if (mSettings->applyPhotonFlux()) tmpresult *= mPhotonFlux(Q2,W2,pol); //nb/GeV4
+ if(pol == transverse)
+ mDsigdbetadQ2dWdz_T_total[i]=tmpresult;
+ if(pol == longitudinal)
+ mDsigdbetadQ2dWdz_L_total[i]=tmpresult;
+ result+=tmpresult;
+ }
+ return result; //nb/GeV4
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::crossSectionOfLastCall(){
+ return mTotalCS;
+}
+
+GammaPolarization InclusiveDiffractionCrossSectionsFromTables::polarizationOfLastCall(){
+ return mPolarization;
+}
+
+unsigned int InclusiveDiffractionCrossSectionsFromTables::quarkSpeciesOfLastCall(){
+ return mQuarkSpecies;
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::quarkMassOfLastCall(){
+ // return Settings::quarkMass(mQuarkSpecies); //#TT tmp
+ return tt_quarkMass[mQuarkSpecies];
+}
+
+void InclusiveDiffractionCrossSectionsFromTables::setQuarkIndex(unsigned int val){mQuarkIndex=val;}
+
+double InclusiveDiffractionCrossSectionsFromTables::dsigmadbetadz_T(double beta, double Q2, double W2, double z) {
+
+ double MX2 = Q2*(1-beta)/beta;
+ // double mf = Settings::quarkMass(mQuarkIndex);
+ double mf = tt_quarkMass[mQuarkIndex]; //#TT tmp
+ double sqrtArg = 1.-4.*mf*mf/MX2;
+ if (sqrtArg<0){
+ if (mSettings->verboseLevel() > 2)
+ cout<<"There is no phase-space for z, return 0."<<endl;
+ return 0;
+ }
+ double z0 = (1.-sqrt(sqrtArg))/2.;
+ if (z<z0 or z>1-z0){
+ if (mSettings->verboseLevel() > 2)
+ cout<<"z="<<z<<" which is smaller than z0="<<z0<<"or larger than (1-z0)="<<1-z0<<", return 0."<<endl;
+ return 0;
+ }
+ double pt2 = z*(1-z)*Q2-mf*mf;
+ if (pt2<0){
+ if (mSettings->verboseLevel() > 2)
+ cout<<"Not enough phase-space for quark transverse momenta, return 0."<<endl;
+ return 0;
+ }
+ if(z*(1-z)*MX2-mf*mf<0){ //kappa2<0
+ if (mSettings->verboseLevel() > 2)
+ cout<<"Not enough phase-space for quark production, return 0."<<endl;
+ return 0;
+ }
+ double result = interpolate(beta, Q2, W2, z, transverse, QQ, mQuarkIndex);
+ return result;
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::dsigmadbetadz_L(double beta, double Q2, double W2, double z){
+
+ double MX2 = Q2*(1-beta)/beta;
+ // double mf = Settings::quarkMass(mQuarkIndex);
+ double mf = tt_quarkMass[mQuarkIndex]; //#TT tmp
+ double pt2 = z*(1-z)*Q2-mf*mf;
+ if (pt2<0){
+ if (mSettings->verboseLevel() > 2)
+ cout<<"Not enough phase-space for quark transverse momenta, return 0."<<endl;
+ return 0;
+ }
+ double sqrtArg=1.-4.*mf*mf/MX2;
+ if (sqrtArg<0){
+ if (mSettings->verboseLevel() > 2)
+ cout<<"There is no phase-space for z, return 0."<<endl;
+ return 0;
+ }
+ double z0=(1.-sqrt(sqrtArg))/2.;
+ if (z<z0 or z>1-z0){
+ if (mSettings->verboseLevel() > 2)
+ cout<<"z="<<z<<" which is smaller than z0="<<z0<<"or larger than (1-z0)="<<1-z0<<", return 0."<<endl;
+ return 0;
+ }
+ if(z*(1-z)*MX2-mf*mf<0){ //kappa2<0
+ if (mSettings->verboseLevel() > 2)
+ cout<<"Not enough phase-space for quark production, return 0."<<endl;
+ return 0;
+ }
+ double result = interpolate(beta, Q2, W2, z, longitudinal, QQ, mQuarkIndex);
+ return result;
+}
+
+DipoleModel* InclusiveDiffractionCrossSectionsFromTables::dipoleModel(){
+ return mDipoleModel;
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::crossSectionRatioLTOfLastCall() const {return mCrossSectionRatioLT;}
+
+//===================================================
+// QQG Calculations
+//===================================================
+
+double InclusiveDiffractionCrossSectionsFromTables::unuranPDF_qqg(const double* array){
+ //
+ // array is: beta, log(Q2), W2, z
+ //
+ double result = 0;
+ double Q2 = exp(array[1]);
+
+ double z=array[3];
+ result = dsigdbetadQ2dW2dz_total_qqg_checked(array[0], Q2, array[2], z);
+ result *= Q2; // Jacobian log(Q2)->Q2
+ return log(result);
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::dsigdbetadQ2dW2dz_total_qqg_checked(double beta, double Q2, double W2, double z){
+ //
+ // Check if in kinematically allowed region
+ //
+ double MX2=Kinematics::MX2(Q2, beta, 0);
+ if(mCheckKinematics && z<beta) {
+ if (mSettings->verboseLevel() > 2)
+ cout<<"z<beta, beta="<<beta<<", z="<<z<<endl;
+ return 0; // For QQG beta < z < 1
+ }
+ if (mCheckKinematics && !Kinematics::valid(mS, beta, Q2, W2, z, sqrt(MX2), false, (mSettings->verboseLevel() > 2) )) {
+ if (mSettings->verboseLevel() > 2)
+ cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(): warning, beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z="<< z
+ << " is outside of kinematically allowed region. Return 0." << endl;
+ return 0;
+ }
+
+ double result = dsigdbetadQ2dW2dz_qqg(beta, Q2, W2, z);
+ //
+ // Quark Species
+ //
+ //
+ bool isChosen=false;
+ double cs_rejected=0;
+ for(int i=0; i<4; i++){
+ double R=mRandom->Uniform(result-cs_rejected);
+ double csTi=mDsigdbetadQ2dWdz_T_qqg[i];
+ if(R <= csTi){
+ mQuarkSpecies=i;
+ isChosen=true;
+ break;
+ }
+ cs_rejected+=mDsigdbetadQ2dWdz_T_qqg[i];
+ }
+ if(!isChosen) mQuarkSpecies=4;
+ // Print-out at high verbose levels
+ //
+ if (mSettings->verboseLevel() > 10) { // Spinal Tap ;-)
+ cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(): " << result;
+ cout << " at beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z<< endl;
+ }
+ //
+ // Check validity of return value
+ //
+ if (std::isnan(result)) {
+ cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(): Error, return value = NaN at" << endl;
+ cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z << endl;
+ result = 0;
+ }
+ if (std::isinf(result)) {
+ cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(): Error, return value = inf at" << endl;
+ cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << z << endl;
+ result = 0;
+ }
+ if (result < 0) {
+ cout << "InclusiveDiffractiveCrossSections::dsigdbetadQ2dW2dz_total_qqg_checked(): Error, negative cross-section at" << endl;
+ cout << " beta=" << beta << ", Q2=" << Q2 << ", W=" << sqrt(W2) << ", z=" << endl;
+ result = 0;
+ }
+ mTotalCS_qqg=result;
+ return result; //nb/GeV4
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::dsigdbetadQ2dW2dz_qqg(double beta, double Q2, double W2, double z) {
+ double result = 0;
+ for(int i=0; i<4; i++){
+ setQuarkIndex(i);
+ // double mf = Settings::quarkMass(mQuarkIndex);
+ double mf = tt_quarkMass[i]; //#TT tmp
+ double Mqq2=(z/beta-1)*Q2;
+ if(Mqq2<4*mf*mf) {
+ continue; //Not enough phase-space for the q and qbar
+ }
+ double tmpresult = dsigmadbetadz_QQG(beta, Q2, W2, z); //nb
+ if (mSettings->applyPhotonFlux()) tmpresult *= mPhotonFlux(Q2,W2,transverse); //nb/GeV4
+ mDsigdbetadQ2dWdz_T_qqg[i]=tmpresult;
+ result+=tmpresult;
+ }
+ return result; //nb/GeV4
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::dsigmadbetadz_QQG(double beta, double Q2, double W2, double ztilde) {
+ double result = interpolate(beta, Q2, W2, ztilde, transverse, QQG, mQuarkIndex);
+ return result;
+}
+
+double InclusiveDiffractionCrossSectionsFromTables::interpolate(double beta, double Q2, double W2, double z, GammaPolarization pol, FockState fock, int quark){
+ THnF* hist4D=0;// = dynamic_cast<THnF*>(file->Get("hist4D"));
+ if(pol==transverse and fock==QQ){
+ hist4D=tableQQ_T.at(quark);
+ }
+ else if(pol==longitudinal and fock==QQ){
+ hist4D=tableQQ_L.at(quark);
+ }
+ else if(fock==QQG){
+ hist4D=tableQQG.at(quark);
+ }
+ else{
+ cout<<"There is nothing to interpolate, ending"<<endl;
+ exit(2);
+ }
+
+ int nDims = hist4D->GetNdimensions();
+
+ vector <double>MinRange(nDims); //beta, Q2,W2, z
+ vector <double>MaxRange(nDims); //beta, Q2,W2, z
+ vector <int>Bins(nDims); //beta, Q2,W2, z
+ for (int dim = 0; dim < 4; dim++) {
+ TAxis* axis = hist4D->GetAxis(dim); // Get the axis for this dimension
+ if (!axis) {
+ std::cerr << "Error: Cannot retrieve axis for dimension " << dim << std::endl;
+ continue;
+ }
+ // Get the number of bins and range
+ int nBins = axis->GetNbins();
+ double minRange = axis->GetXmin();
+ double maxRange = axis->GetXmax();
+ Bins[dim]= nBins;
+ MinRange[dim]= minRange;
+ MaxRange[dim]= maxRange;
+ }
+ // construct the grid in each dimension.
+ // note that we will pass in a sequence of iterators pointing to the beginning of each grid
+ std::vector<double> gridBeta = mgrid(hist4D,0, Bins[0]);
+ std::vector<double> gridQ2 = mgrid(hist4D,1, Bins[1]) ;
+ std::vector<double> gridW2 = mgrid(hist4D,2, Bins[2]);
+ std::vector<double> gridZ = mgrid(hist4D,3, Bins[3]) ;
+
+ // print_grid_vector(gridQ2, "gridQ2");
+ // print_grid_vector(gridW2, "gridW2");
+ // print_grid_vector(gridBeta, "gridBeta");
+ // print_grid_vector(gridZ, "gridZ");
+
+ std::vector< std::vector<double>::iterator > grid_iter_list;
+ grid_iter_list.push_back(gridQ2.begin());
+ grid_iter_list.push_back(gridW2.begin());
+ grid_iter_list.push_back(gridBeta.begin());
+ grid_iter_list.push_back(gridZ.begin());
+
+ // cout<<"grid\t"<<*(gridQ2.begin())<<endl;
+ // the size of the grid in each dimension
+ array<int,4> grid_sizes;
+ grid_sizes[0] = Bins[0];
+ grid_sizes[1] = Bins[1];
+ grid_sizes[2] = Bins[2];
+ grid_sizes[3] = Bins[3];
+
+
+ // for(unsigned long i=0;i<grid_sizes.size(); i++)
+ // std::cout<<"Grid size \t"<<grid_sizes[i]<<std::endl;
+
+ // total number of elements
+ int num_elements = grid_sizes[0] * grid_sizes[1]* grid_sizes[2]* grid_sizes[3];
+ // std::cout<<"num_elements = "<<num_elements<<std::endl;
+ // fill in the values of f(x) at the gridpoints.
+ // we will pass in a contiguous sequence, values are assumed to be laid out C-style
+ std::vector<double> f_values(num_elements);
+ int count = 0;
+
+
+ for (int ibeta=1; ibeta<=grid_sizes[0]; ibeta++) {
+ for (int iQ2=1; iQ2<=grid_sizes[1]; iQ2++) {
+ for (int iW2=1; iW2<=grid_sizes[2]; iW2++) {
+ for (int iZ=1; iZ<=grid_sizes[3]; iZ++) {
+ int binIndex[] = {ibeta, iQ2, iW2, iZ};
+ f_values[count] = hist4D->GetBinContent(binIndex);
+ count++;
+ }
+ }
+ }
+ }
+ // std::cout<<"done"<<std::endl;
+
+ // construct the interpolator. the last two arguments are pointers to the underlying data
+ InterpMultilinear <4, double> interp_ML(grid_iter_list.begin(), grid_sizes.begin(), f_values.data(), f_values.data() + num_elements);
+
+ // InterpMultilinear interp_ML(grid_iter_list.begin(), grid_sizes.begin(), f_values.data(), f_values.data() + num_elements);
+
+ // interpolate:
+ array<double,4> args = {beta, Q2, W2, z};
+ double result=interp_ML.interp(args.begin());
+ return exp(result);
+}
+
+vector<double> InclusiveDiffractionCrossSectionsFromTables::mgrid(THnF* hist,int axis, int len){
+ vector<double> gridtype(len);
+ for(int i = 0; i <len; i++){
+ double val = hist->GetAxis(axis)->GetBinCenter(i+1);
+ gridtype[i] = val;
+ }
+ return gridtype;
+}
+
Index: trunk/src/SartreInclusiveDiffraction.cpp
===================================================================
--- trunk/src/SartreInclusiveDiffraction.cpp (revision 537)
+++ trunk/src/SartreInclusiveDiffraction.cpp (revision 538)
@@ -1,852 +1,861 @@
//==============================================================================
// SartreInclusiveDiffraction.cpp
//
// Copyright (C) 2024 Tobias Toll and Thomas Ullrich
//
// This file is part of Sartre.
//
// This program 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.
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author: Tobias Toll
// Last update:
// $Date: 2024-06-03 11:27:05 -0400 (Mon, 03 Jun 2024) $
// $Author: ullrich $
//==============================================================================
//
// Note:
// When not using runcards, the user must first create an instance of
// SartreInclusiveDiffraction and then get the settings via one of:
// SartreInclusiveDiffraction::runSettings()
// EventGeneratorSettings::instance()
// Once init() is called settings cannot be changed any more.
//==============================================================================
#include "Version.h"
#include "Kinematics.h"
#include "Constants.h"
#include "SartreInclusiveDiffraction.h"
#include "Math/Functor.h"
#include "ModeFinderFunctor.h"
#include "Math/BrentMinimizer1D.h"
#include "Math/IntegratorMultiDim.h"
#include "Math/GSLMinimizer.h"
#include "TUnuranMultiContDist.h"
#include <string>
#include <limits>
#include <cmath>
#include <iomanip>
#include "TH2D.h"
#include "TFile.h"
#include "TF3.h"
+#include "InclusiveDiffractiveCrossSectionsFromTables.h"
using namespace std;
#define PR(x) cout << #x << " = " << (x) << endl;
SartreInclusiveDiffraction::SartreInclusiveDiffraction()
{
mSettings = EventGeneratorSettings::instance();
mRandom = mSettings->randomGenerator();
mIsInitialized = false;
mCurrentEvent = 0;
mNucleus = 0;
mUpcNucleus= 0;
// mSettings = 0;
mPDF_Functor = 0;
mPDF = 0;
mEventCounter = 0;
mTriesCounter = 0;
mTotalCrossSection = 0;
mTotalCrossSection_qqg = 0;
mTotalCrossSection_qq = 0;
mCrossSection = 0;
mUnuran = 0;
mEvents = 0;
mTries = 0;
mS = 0;
mA = 0;
+ mUseCrossSectionTables=true;
}
SartreInclusiveDiffraction::~SartreInclusiveDiffraction()
{
delete mNucleus;
delete mUpcNucleus;
delete mPDF_Functor;
delete mPDF;
delete mCrossSection;
delete mUnuran;
delete mCurrentEvent;
}
bool SartreInclusiveDiffraction::init(const char* runcard)
{
mStartTime = time(0);
bool ok;
//
// Reset member variables.
// Note that one instance of Sartre should be able to get
// initialized multiple times.
//
mEvents = 0;
mTries = 0;
mTotalCrossSection = 0;
mTotalCrossSection_qqg = 0;
mTotalCrossSection_qq = 0;
//
// Print header
//
string ctstr(ctime(&mStartTime));
ctstr.erase(ctstr.size()-1, 1);
cout << "/========================================================================\\" << endl;
cout << "| |" << endl;
cout << "| Sartre, Version " << setw(54) << left << VERSION << right << '|' << endl;
cout << "| |" << endl;
cout << "| An event generator for inclusive diffraction |" << endl;
cout << "| in ep and eA collisions based on the dipole model. |" << endl;
cout << "| |" << endl;
cout << "| Copyright (C) 2010-2024 Tobias Toll and Thomas Ullrich |" << endl;
cout << "| |" << endl;
cout << "| This program is free software: you can redistribute it and/or modify |" << endl;
cout << "| it under the terms of the GNU General Public License as published by |" << endl;
cout << "| the Free Software Foundation, either version 3 of the License, or |" << endl;
cout << "| any later version. |" << endl;
cout << "| |" << endl;
cout << "| Code compiled on " << setw(12) << left << __DATE__;
cout << setw(41) << left << __TIME__ << right << '|' << endl;
cout << "| Run started at " << setw(55) << left << ctstr.c_str() << right << '|' << endl;
cout << "\\========================================================================/" << endl;
mSettings = EventGeneratorSettings::instance(); // EventGeneratorSettings is a singleton
mSettings->setInclusiveDiffractionMode(true);
//
// Read runcard if available
//
if (runcard) {
if (!mSettings->readSettingsFromFile(runcard)) {
cout << "Error, reading runcard '" << runcard << "'. File doesn't exist or is not readable." << endl;
exit(1);
}
else
cout << "Runcard is '" << runcard << "'." << endl;
}
else
cout << "No runcard provided." << endl;
//
// Set beam particles and center of mass energy
//
mElectronBeam = mSettings->eBeam();
mHadronBeam = mSettings->hBeam();
mS = Kinematics::s(mElectronBeam, mHadronBeam);
mA = mSettings->A();
-
+
bool allowBreakup = mSettings->enableNuclearBreakup();
if (mA == 1) allowBreakup = false;
if (allowBreakup) {
if (!getenv("SARTRE_DIR")) {
cout << "Error, environment variable 'SARTRE_DIR' is not defined. It is required\n"
"to locate tables needed for the generation if nuclear breakups." << endl;
exit(1);
}
}
if (mNucleus) delete mNucleus;
mNucleus = new FrangibleNucleus(mA, allowBreakup);
string upcNucleusName;
cout << "Sartre is running in inclusive diffraction mode" << endl;
cout << "Hadron beam species: " << mNucleus->name() << " (" << mA << ")" << endl;
cout << "Hadron beam: " << mHadronBeam << endl;
cout << "Electron beam: " << mElectronBeam << endl;
//
// Get details about the processes and models
//
mDipoleModelType = mSettings->dipoleModelType();
mDipoleModelParameterSet = mSettings->dipoleModelParameterSet();
cout << "Dipole model: " << mSettings->dipoleModelName().c_str() << endl;
cout << "Dipole model parameter set: " << mSettings->dipoleModelParameterSetName().c_str() << endl;
cout << "Process is ";
if (mA > 1)
cout << "e + " << mNucleus->name() << " -> e' + " << mNucleus->name() << "' + X"<< endl;
else
cout << "e + p -> e' + p' + X"<< endl;
//
// Print-out seed for reference
//
cout << "Random generator seed: " << mSettings->seed() << endl;
//
// Load in the tables containing the amplitude moments
//
if (!getenv("SARTRE_DIR")) {
cout << "Error, required environment variable 'SARTRE_DIR' is not defined." << endl;
exit(1);
}
//
// Kinematic limits and generator range
//
// There are 3 ranges we have to deal with
// 1. the kinematic range requested by the user
// if given.
// The user can only control Q2 and W but not t.
// For UPC that's xpom.
// 2. the range of the table(s)
// 3. the kinematically allowed range
//
// Of course (3) is more complex than a simple cube/square.
// However, we deal with the detailed shape of the kinematic
// range later using Kinematics::valid() when we generate the
// individual events.
// For setting up UNU.RAN we have to get the cubic/square
// envelope that satifies (1)-(3).
// Note, that they are correlated which makes the order
// in which we do things a bit tricky.
//
//
// Step 2:
// Kinematic limits might overrule boundaries from step 1
//
// let:
// 0: beta
// 1: Q2
// 2: W2
// 3: z
//
// Setup cross-section functor
// It is this functor that is used by all other functors,
// functions, and wrappers when dealing with cross-sections.
//
if (mCrossSection) delete mCrossSection;
- mCrossSection = new InclusiveDiffractiveCrossSections;
+ if(!mUseCrossSectionTables){
+ mCrossSection = new InclusiveDiffractiveCrossSections;
+ }
+ else{
+ mCrossSection = new InclusiveDiffractionCrossSectionsFromTables;
+ }
//
// Here we need to put in Q2 > mu02.
// The calculation goes haywire for Q2 becoming too small
//
double mu02 = mCrossSection->dipoleModel()->getParameters()->mu02();
// double mf = Settings::quarkMass(0);
double mf=tt_quarkMass[0];
//Now for the diffractive mass:
double kineMX2min = 4*mf*mf;//max(mu02, 4*mf*mf);
// This gives the limits for W2 and for inelasticity y:
double kineW2min = kineMX2min+protonMass2;
double kineYmin = Kinematics::ymin(mS, kineMX2min);
// ...and y gives the limit for Q2, unless it's smaller than the cut-off mu02:
double kineQ2min = Kinematics::Q2min(kineYmin);
kineQ2min = max(kineQ2min, mu02);
//The maximum momenta are given by s:
double kineQ2max = Kinematics::Q2max(mS);
double kineW2max = mS-kineQ2min-protonMass2;
//
// Now for all the fractions, making sure they make sense
//
double kineBetamax = kineQ2max/(kineQ2max+kineMX2min);
double kineBetamin = Kinematics::betamin(kineQ2min, mS, sqrt(kineW2min), 0);
double kineMX2max = (1.-kineBetamin)/kineBetamin*kineQ2max;
kineMX2max=min(kineMX2max, kineW2max-protonMass2);
double kineZmin=(1-sqrt(1-4*mf*mf/kineMX2max))/2.;
double kineZmax=1-kineZmin;
mLowerLimit[0] = kineBetamin;
mUpperLimit[0] = kineBetamax;
mLowerLimit[1] = kineQ2min;
mUpperLimit[1] = kineQ2max;
mLowerLimit[2] = kineW2min;
mUpperLimit[2] = kineW2max;
mLowerLimit[3] = kineZmin;
mUpperLimit[3] = kineZmax;
// Step 3:
// Deal with user provided limits.
// User settings are ignored (switched off) if min >= max.
// Only allow user limits for Q2, W2, and beta,
// not z.
//
bool W2orQ2changed=false;
if (mSettings->Wmin() < mSettings->Wmax()) { // W2 first
if (mSettings->W2min() < mLowerLimit[2]) {
cout << "Warning, requested lower limit of W (" << mSettings->Wmin() << ") "
<< "is smaller than limit given by lookup tables and/or kinematic range (" << sqrt(mLowerLimit[2]) << "). ";
cout << "Limit has no effect." << endl;
}
else {
mLowerLimit[2] = mSettings->W2min();
W2orQ2changed=true;
}
if (mSettings->W2max() > mUpperLimit[2]) {
cout << "Warning, requested upper limit of W (" << mSettings->Wmax() << ") "
<< "exceeds limit given by lookup tables and/or kinematic range (" << sqrt(mUpperLimit[2]) << "). ";
cout << "Limit has no effect." << endl;
}
else {
mUpperLimit[2] = mSettings->W2max();
W2orQ2changed=true;
}
}
if (mSettings->Q2min() < mSettings->Q2max()) { // Q2
if (mSettings->Q2min() < mLowerLimit[1]) {
cout << "Warning, requested lower limit of Q2 (" << mSettings->Q2min() << ") "
<< "is smaller than limit given by lookup tables and/or kinematic range (" << mLowerLimit[1] << "). ";
cout << "Limit has no effect." << endl;
}
else {
mLowerLimit[1] = mSettings->Q2min();
W2orQ2changed=true;
}
if (mSettings->Q2max() > mUpperLimit[1]) {
cout << "Warning, requested upper limit of Q2 (" << mSettings->Q2max() << ") "
<< "exceeds limit given by lookup tables and/or kinematic range (" << mUpperLimit[1] << "). ";
cout << "Limit has no effect." << endl;
}
else {
mUpperLimit[1] = mSettings->Q2max();
W2orQ2changed=true;
}
}
if (W2orQ2changed){//mLowerLimit beta, Q2, W2, z
//kineBetamax = kineQ2max/(kineQ2max+kineMX2min);
mUpperLimit[0] = mUpperLimit[1]/(mUpperLimit[1]+kineMX2min);
//kineBetamin = Kinematics::betamin(kineQ2min, mS, sqrt(kineW2min), 0);
mLowerLimit[0] = Kinematics::betamin(mLowerLimit[1], mS, sqrt(mLowerLimit[2]), 0);
// kineMX2max = (1.-kineBetamin)/kineBetamin*kineQ2max;
// kineMX2max=min(kineMX2max, kineW2max-protonMass2);
kineMX2max = (1.-mLowerLimit[0])/mLowerLimit[0]*mUpperLimit[1];
kineMX2max=min(kineMX2max, mUpperLimit[2]-protonMass2);
// kineZmin=(1-sqrt(1-4*mf*mf/kineMX2max))/2.;
// kineZmax=1-kineZmin;
mLowerLimit[3]=(1-sqrt(1-4*mf*mf/kineMX2max))/2.;
mUpperLimit[3]=1-mLowerLimit[3];
}
if (mSettings->betamin() < mSettings->betamax()) { // beta
if (mSettings->betamin() < mLowerLimit[0]) {
cout << "Warning, requested lower limit of beta (" << mSettings->betamin() << ") "
<< "is smaller than limit given by lookup tables and/or kinematic range (" << mLowerLimit[0] << "). ";
cout << "Limit has no effect." << endl;
}
else {
mLowerLimit[0] = mSettings->betamin();
}
if (mSettings->betamax() > mUpperLimit[0]) {
cout << "Warning, requested upper limit of Q2 (" << mSettings->betamax() << ") "
<< "exceeds limit given by lookup tables and/or kinematic range (" << mUpperLimit[0] << "). ";
cout << "Limit has no effect." << endl;
}
else {
mUpperLimit[0] = mSettings->betamax();
}
}
//
// Check if any phase space is left
//
if (mLowerLimit[0] >= mUpperLimit[0]) {
cout << "Invalid range in beta: beta=[" << mLowerLimit[0] << ", " << mUpperLimit[0] << "]." << endl;
exit(1);
}
if (mLowerLimit[1] >= mUpperLimit[1]) {
cout << "Invalid range in Q2: Q2=[";
cout << mLowerLimit[1] << ", " << mUpperLimit[1] << "]." << endl;
exit(1);
}
if (mLowerLimit[2] >= mUpperLimit[2]) {
cout << "Invalid range in W: W=[" << sqrt(mLowerLimit[2]) << ", " << sqrt(mUpperLimit[2]) << "]." << endl;
exit(1);
}
//
// Print-out limits (all verbose levels)
//
if (true){//}(mSettings->verbose()) {
cout << "Sartre was thrown into the world, restricted by kinematics and user inputs alike:" << endl;
cout << setw(10) << " beta=[" << mLowerLimit[0] << ", " << mUpperLimit[0] << "]" << endl;
cout << setw(10) << "Q2=[" << mLowerLimit[1] << ", " << mUpperLimit[1] << "]" << endl;
cout << setw(10) << " W=[" << sqrt(mLowerLimit[2]) << ", " << sqrt(mUpperLimit[2]) << "]" << endl;
cout << setw(10) << " z=[" << mLowerLimit[3] << ", " << mUpperLimit[3] << "]" << endl;
cout << setw(10) << " MX2=[" << kineMX2min << ", " << kineMX2max << "]" << endl;
cout << setw(10) << " y=[" << kineYmin << ", 1" << "]" << endl;
}
//
// UNU.RAN needs the domain (boundaries) and the mode.
// The domain is already defined, here we find the mode, which is tricky.
// The max. cross-section is clearly at the domain boundary in Q2=Q2min.
// The position in W2 and beta is not obvious. The mode should be at z=0.5.
// The approach here is to use the BrentMinimizer1D that
// performs first a scan a then a Brent fit.
//
mCrossSection->setCheckKinematics(false);
double theMode[4];
//
// Find the mode.
// Assume that the mode is at W2=W2max, Q2=Q2min, z=0.5
// Start with beta=0.5 => MX2=Q2
// It is kinemtically easier to use MX2 instead of beta here.
//
if (mSettings->verbose()) cout << "Finding mode of pdf:" << endl;
theMode[1] = mLowerLimit[1]; // Q2
theMode[2] = mUpperLimit[2]; // W2
theMode[3] = 0.5; // z
double MX2min=mLowerLimit[1]*(1-mUpperLimit[0])/mUpperLimit[0];
MX2min=max(kineMX2min, MX2min);
double MX2max=mLowerLimit[1]*(1-mLowerLimit[0])/mLowerLimit[0];
MX2max=min(kineMX2max, MX2max);
InclusiveDiffractionModeFinderFunctor modeFunctor(mCrossSection, theMode[1], theMode[2], theMode[3], MX2min, MX2max);
-
+
ROOT::Math::BrentMinimizer1D minimizer;
minimizer.SetFunction(modeFunctor, MX2min, MX2max);
minimizer.SetNpx(static_cast<int>(mUpperLimit[0]-mLowerLimit[0]));
ok = minimizer.Minimize(100000, 0, 1.e-8);
if (! ok) {
cout << "Error, failed to find mode of pdf." << endl;
exit(1);
}
theMode[0] = minimizer.XMinimum(); // Mx2
double MX2=theMode[0];
theMode[0]=theMode[1]/(theMode[1]+MX2); //Mx2->beta
double crossSectionAtMode = (*mCrossSection)(MX2, theMode[1], theMode[2], theMode[3]);
if (mSettings->verbose()) {
cout << "\tlocation: beta=" << theMode[0] << ", Q2=" << theMode[1] << ", W=" << sqrt(theMode[2]) << ", z=" << theMode[3];
cout << "; value: " << crossSectionAtMode << endl;
}
mCrossSection->setCheckKinematics(true);
// domain and mode for Q2 -> log(Q2)
mLowerLimit[1] = log(mLowerLimit[1]);
mUpperLimit[1] = log(mUpperLimit[1]);
theMode[1] = log(theMode[1]);
if (mPDF_Functor) delete mPDF_Functor;
if (mPDF) delete mPDF;
mPDF_Functor = new ROOT::Math::Functor(mCrossSection, &InclusiveDiffractiveCrossSections::unuranPDF, 4);
mPDF = new TUnuranMultiContDist(*mPDF_Functor, true); // last arg = pdf in log or not
mPDF->SetDomain(mLowerLimit, mUpperLimit);
mPDF->SetMode(theMode);
if (mUnuran) delete mUnuran;
mUnuran = new TUnuran;
mCrossSection->setCheckKinematics(false); // avoid numeric glitch in Init()
mUnuran->Init(*mPDF, "method=hitro");
mCrossSection->setCheckKinematics(true);
mUnuran->SetSeed(mSettings->seed());
//
// Burn in generator
//
double xrandom[4];
- for (int i=0; i<1; i++) {
+ for (int i=0; i<100; i++) {
mUnuran->SampleMulti(xrandom);
- cout<<"QQ: beta="<<xrandom[0];
- cout<<" Q2="<<exp(xrandom[1]);
- cout<<" W="<<sqrt(xrandom[2]);
- cout<<" z="<<xrandom[3]<<endl;
+// cout<<"QQ: beta="<<xrandom[0];
+// cout<<" Q2="<<exp(xrandom[1]);
+// cout<<" W="<<sqrt(xrandom[2]);
+// cout<<" z="<<xrandom[3]<<endl;
}
-
//
// Set up QQG unu.ran:
//
//The mode is simpler for QQG, as it is at minimum beta
//The limits are the same, except for z which is a different quantity in QQG.
mLowerLimit_qqg[0]=mLowerLimit[0]; //beta
mLowerLimit_qqg[1]=mLowerLimit[1]; //log(Q2)
mLowerLimit_qqg[2]=mLowerLimit[2]; //W2
//z>beta*(1+4*mf*mf/Q2);
- mLowerLimit_qqg[3]=mLowerLimit[0] * (1+4*mf*mf/exp(mUpperLimit[1]));
+ mLowerLimit_qqg[3]=mLowerLimit[0] * (1+4*mf*mf/exp(mUpperLimit[1]))+1e-10;
mUpperLimit_qqg[0]=mUpperLimit[0]; //beta
mUpperLimit_qqg[1]=mUpperLimit[1]; //log(Q2)
mUpperLimit_qqg[2]=mUpperLimit[2]; //W2
mUpperLimit_qqg[3]=mUpperLimit[3]; //z
double theMode_qqg[4];
theMode_qqg[0]=mLowerLimit_qqg[0]; //beta
theMode_qqg[1]=mLowerLimit_qqg[1]; //log(Q2)
theMode_qqg[2]=mUpperLimit_qqg[2]; //W2
- theMode_qqg[3]=theMode_qqg[0]*(1+4*mf*mf/exp(theMode_qqg[1])); //z
+ theMode_qqg[3]=theMode_qqg[0]*(1+4*mf*mf/exp(theMode_qqg[1]))+1e-10; //z
if (mPDF_Functor_qqg) delete mPDF_Functor_qqg;
if (mPDF_qqg) delete mPDF_qqg;
mPDF_Functor_qqg = new ROOT::Math::Functor(mCrossSection, &InclusiveDiffractiveCrossSections::unuranPDF_qqg, 4);
mPDF_qqg = new TUnuranMultiContDist(*mPDF_Functor_qqg, true); // last arg = pdf in log or not
//Rescale the domain in z (and fix it in the pdf)
mPDF_qqg->SetDomain(mLowerLimit_qqg, mUpperLimit_qqg);
mPDF_qqg->SetMode(theMode_qqg);
-
+
mCrossSection->setCheckKinematics(false);
if (mUnuran_qqg) delete mUnuran_qqg;
mUnuran_qqg = new TUnuran;
mUnuran_qqg->Init(*mPDF_qqg, "method=hitro");
mUnuran_qqg->SetSeed(mSettings->seed());
- mCrossSection->setCheckKinematics(true);
+// mCrossSection->setCheckKinematics(true);
//
// Burn in QQG generator
//
- for (int i=0; i<1; i++) {
+ for (int i=0; i<100; i++) {
mUnuran_qqg->SampleMulti(xrandom);
- cout<<"QQG: beta="<<xrandom[0];
- cout<<" Q2="<<exp(xrandom[1]);
- cout<<" W="<<sqrt(xrandom[2]);
- cout<<" z="<<xrandom[3]<<endl;
+// cout<<"QQG: beta="<<xrandom[0];
+// cout<<" Q2="<<exp(xrandom[1]);
+// cout<<" W="<<sqrt(xrandom[2]);
+// cout<<" z="<<xrandom[3]<<endl;
}
- mEventCounter = 0;
- mTriesCounter = 0;
- mIsInitialized = true;
- cout << "Sartre for InclusiveDiffraction is initialized." << endl << endl;
//
// Calculate total cross section in given
// kinematic limits. This will be used to
// decide which type of event to generate,
// q-qbar or q-qbar-g
//
- cout<<"Calculating cross sections over the given kinematic range..."<<endl;
- cout<<"(This may take while, use your radical freedom and do other things.)"<<endl;
- mCrossSection->setFockState(QQ);
- mTotalCrossSection=0;
- mTotalCrossSection_qq=totalCrossSection();
- cout<<" The QQ cross section is: "<<mTotalCrossSection_qq<<" nb. (1/2)"<<endl;
- mCrossSection->setFockState(QQG);
- mTotalCrossSection=0;
- mTotalCrossSection_qqg=totalCrossSection();
- cout<<"The QQG cross section is: "<<mTotalCrossSection_qqg<<" nb. (2/2)"<<endl;
- cout<<"Total Cross Section: "<<mTotalCrossSection_qqg+mTotalCrossSection_qq<<" nb"<<endl;
- mTotalCrossSection=mTotalCrossSection_qqg+mTotalCrossSection_qq;
+// cout<<"Calculating cross sections over the given kinematic range..."<<endl;
+// cout<<"(This may take while, use your radical freedom and do other things.)"<<endl;
+// mCrossSection->setFockState(QQ);
+// mTotalCrossSection=0;
+// mTotalCrossSection_qq=totalCrossSection();
+// cout<<" The QQ cross section is: "<<mTotalCrossSection_qq<<" nb. (1/2)"<<endl;
+// mCrossSection->setFockState(QQG);
+// mTotalCrossSection=0;
+// mTotalCrossSection_qqg=totalCrossSection();
+// cout<<"The QQG cross section is: "<<mTotalCrossSection_qqg<<" nb. (2/2)"<<endl;
+// cout<<"Total Cross Section: "<<mTotalCrossSection_qqg+mTotalCrossSection_qq<<" nb"<<endl;
+// mTotalCrossSection=mTotalCrossSection_qqg+mTotalCrossSection_qq;
+
+ mEventCounter = 0;
+ mTriesCounter = 0;
+ mIsInitialized = true;
+ cout << "Sartre for InclusiveDiffraction is initialized." << endl << endl;
+
return true;
}
double SartreInclusiveDiffraction::cross_section_wrapper(double* xx, double* par){
double arg[4]={xx[0], xx[1], xx[2], par[0]};
double result=mCrossSection->unuranPDF(arg);
return -result;
}
bool SartreInclusiveDiffraction::init(const string& str) // overloaded version of init()
{
if (str.empty())
return init();
else
return init(str.c_str());
}
vector<pair<double,double> > SartreInclusiveDiffraction::kinematicLimits()
{
vector<pair<double,double> > array;
array.push_back(make_pair(mLowerLimit[0], mUpperLimit[0])); // t
array.push_back(make_pair(exp(mLowerLimit[1]), exp(mUpperLimit[1]))); // Q2 or xpom
if (!mSettings->UPC())
array.push_back(make_pair(sqrt(mLowerLimit[2]), sqrt(mUpperLimit[2]))); // W
return array;
}
Event* SartreInclusiveDiffraction::generateEvent()
{
if (!mIsInitialized) {
cout << "SartreInclusiveDiffraction::generateEvent(): Error, Sartre is not initialized yet." << endl;
cout << " Call init() before trying to generate events." << endl;
return 0;
}
//
// Decide which Fock-state to generate:
//
bool isQQ=false;
if(mRandom->Uniform(mTotalCrossSection) <= mTotalCrossSection_qq)
isQQ=true;
//
// Generate one event
//
double xrandom[4];
while (true) {
mTriesCounter++;
delete mCurrentEvent;
mCurrentEvent = new Event;
//
// xrandom[i]
// i=0: beta
// i=1: Q2
// i=2: W2
// i=3: z
//
if(isQQ)
mUnuran->SampleMulti(xrandom);
else
mUnuran_qqg->SampleMulti(xrandom);
xrandom[1] = exp(xrandom[1]); // log(Q2) -> Q2
double MX2=xrandom[1]*(1-xrandom[0])/xrandom[0];
bool isValidEvent;
isValidEvent = Kinematics::valid( mS, xrandom[0], xrandom[1], xrandom[2], xrandom[3], sqrt(MX2), true, (mSettings->verboseLevel() > 1));
if (!isValidEvent) {
if (mSettings->verboseLevel() > 2)
cout << "SartreInclusiveDiffraction::generateEvent(): event rejected, not within kinematic limits" << endl;
continue;
}
//
// Fill beam particles in Event structure
// Kinematics for eA is reported as 'per nucleon'
//
mCurrentEvent->eventNumber = mEventCounter;
mCurrentEvent->beta = xrandom[0]; // beta
mCurrentEvent->Q2 = xrandom[1]; // Q2
mCurrentEvent->x = Kinematics::x(xrandom[1], xrandom[2]); // x
mCurrentEvent->xpom=mCurrentEvent->x/xrandom[0]; //xpom=x/beta
mCurrentEvent->y = Kinematics::y(xrandom[1], mCurrentEvent->x, mS); // y
mCurrentEvent->s = mS; // s
mCurrentEvent->W = sqrt(xrandom[2]);
mCurrentEvent->z = xrandom[3];
mCurrentEvent->MX = sqrt(MX2);
if(isQQ)
mCurrentEvent->polarization = mCrossSection->polarizationOfLastCall();
else
mCurrentEvent->polarization = transverse;
// mCurrentEvent->diffractiveMode = mCrossSection->diffractiveModeOfLastCall();
mCurrentEvent->quarkSpecies = mCrossSection->quarkSpeciesOfLastCall();
if(isQQ)
mCurrentEvent->crossSectionRatioLT=mCrossSection->crossSectionRatioLTOfLastCall();
else
mCurrentEvent->crossSectionRatioLT=0;
//
// The following needs to be modified for QQG
//
double dsigmadb2=0;
double z=xrandom[3];
double eps2=z*(1-z)*(mCurrentEvent->Q2+MX2);
double r_average=1./sqrt(eps2);
if (mA == 1) {
dsigmadb2=mCrossSection->dipoleModel()->dsigmadb2ep(r_average*hbarc, 0, mCurrentEvent->xpom);
}
else {
dsigmadb2=mCrossSection->dipoleModel()->coherentDsigmadb2(r_average*hbarc, 0, mCurrentEvent->xpom);
}
mCurrentEvent->Omega=-2.*log(1-dsigmadb2/2.);
Particle eIn, hIn;
eIn.index = 0;
eIn.pdgId = 11; // e-
eIn.status = 1;
eIn.p = mElectronBeam;
hIn.index = 1;
hIn.pdgId = mNucleus->pdgID();
hIn.status = 1;
hIn.p = mHadronBeam;
mCurrentEvent->particles.push_back(eIn);
mCurrentEvent->particles.push_back(hIn);
//
// Generate the final state particles
//
bool ok;
if (isQQ) {
ok = mFinalStateGenerator.generate(mA, mCurrentEvent, QQ);
}
else {
ok = mFinalStateGenerator.generate(mA, mCurrentEvent, QQG);
}
if (!ok) {
if (mSettings->verboseLevel() > 1) cout << "SartreInclusiveDiffraction::generateEvent(): failed to generate final state" << endl;
continue;
}
break;
}
mEventCounter++;
//
// Nuclear breakup
//
// If the event is incoherent the final state generator does produce a
// 'virtual' proton with m > m_p which is used in Nucleus to calculate
// the excitation energy and the boost.
//
int indexOfScatteredHadron = 6;
bool allowBreakup = mSettings->enableNuclearBreakup();
if (mA == 1) allowBreakup = false;
if (mNucleus) mNucleus->resetBreakup(); // clear previous event in any case
if (allowBreakup && mCurrentEvent->diffractiveMode == incoherent && mNucleus) {
int nFragments = mNucleus->breakup(mCurrentEvent->particles[indexOfScatteredHadron].p);
//
// Merge the list of products into the event list.
// We loose some information here. The user can always go back to
// the nucleus and check the decay products for more details.
// In the original list the energy is per nuclei, here we transform it
// to per nucleon to stay consistent with Sartre conventions.
//
const vector<BreakupProduct>& products = mNucleus->breakupProducts();
for (int i=0; i<nFragments; i++) {
Particle fragment;
fragment.index = mCurrentEvent->particles.size();
fragment.pdgId = products[i].pdgId;
fragment.status = 1;
fragment.p = products[i].p*(1/static_cast<double>(products[i].A));
fragment.parents.push_back(indexOfScatteredHadron);
mCurrentEvent->particles.push_back(fragment);
}
}
return mCurrentEvent;
}
double SartreInclusiveDiffraction::totalCrossSection()
{
if (mTotalCrossSection == 0) {
//
// Limits of integration in beta, Q2, W2, z
//
double xmin[4];
double xmax[4];
copy(mLowerLimit, mLowerLimit+4, xmin);
copy(mUpperLimit, mUpperLimit+4, xmax);
//
// At this point mLowerLimit[1] and mUpperLimit[1]
// are in log(Q2)
//
xmin[1] = exp(xmin[1]); // log Q2 limit
xmax[1] = exp(xmax[1]); // log Q2 limit
mTotalCrossSection = calculateTotalCrossSection(xmin, xmax);
}
return mTotalCrossSection;
}
double SartreInclusiveDiffraction::totalCrossSection(double lower[4], double upper[4]) // beta, Q2, W, z
{
lower[2] *= lower[2]; upper[2] *= upper[2]; // W -> W2
double result = calculateTotalCrossSection(lower, upper);
return result;
}
double SartreInclusiveDiffraction::integrationVolume(){
//
// Limits of integration in beta, Q2, W2, z
//
double xmin[4];
double xmax[4];
copy(mLowerLimit, mLowerLimit+4, xmin);
copy(mUpperLimit, mUpperLimit+4, xmax);
//
// At this point mLowerLimit[1] and mUpperLimit[1]
// are in log(Q2)
//
xmin[1] = exp(xmin[1]); // log Q2 limit
xmax[1] = exp(xmax[1]); // log Q2 limit
double volume = (xmax[0]-xmin[0]) * (xmax[1]-xmin[1]) * (xmax[2]-xmin[2]) * (xmax[3]-xmin[3]);
return volume; //GeV4
}
EventGeneratorSettings* SartreInclusiveDiffraction::runSettings()
{
return EventGeneratorSettings::instance();
}
double SartreInclusiveDiffraction::crossSectionsClassWrapper(const double* var){
return (*mCrossSection)(var);
}
double SartreInclusiveDiffraction::calculateTotalCrossSection(double lower[4], double upper[4])
{
double result = 0;
if (!mIsInitialized) {
cout << "SartreInclusiveDiffraction::calculateTotalCrossSection(): Error, Sartre is not initialized yet." << endl;
cout << " Call init() before trying to generate events." << endl;
return result;
}
//
// Calculate integral using adaptive numerical method
//
// Options: ADAPTIVE, kVEGAS, kPLAIN, kMISER
// no abs tolerance given -> relative only
- const double precision = 1e-1;//5e-4;
- unsigned int numberofcalls = 1;//1000000;
+ const double precision = 5e-4;
+// unsigned int numberofcalls = 1000000;
+ unsigned int numberofcalls = 0;//1e5;
ROOT::Math::Functor wfL(this, &SartreInclusiveDiffraction::crossSectionsClassWrapper, 4);
ROOT::Math::IntegratorMultiDim ig(ROOT::Math::IntegrationMultiDim::kADAPTIVE, 0, precision, numberofcalls);
ig.SetFunction(wfL);
result = ig.Integral(lower, upper);
//
// If it fails we switch to a MC integration which is usually more robust
// although not as accurate. This should happen very rarely if at all.
//
if (result <= numeric_limits<float>::epsilon()) {
cout << "SartreInclusiveDiffraction::calculateTotalCrossSection(): warning, adaptive integration failed - switching to VEGAS method." << endl;
ROOT::Math::IntegratorMultiDim igAlt(ROOT::Math::IntegrationMultiDim::kVEGAS);
igAlt.SetFunction(wfL);
igAlt.SetRelTolerance(precision);
igAlt.SetAbsTolerance(0);
result = igAlt.Integral(lower, upper);
}
return result;
}
const FrangibleNucleus* SartreInclusiveDiffraction::nucleus() const {return mNucleus;}
void SartreInclusiveDiffraction::listStatus(ostream& os) const
{
os << "Event summary: " << mEventCounter<< " events generated, " << mTriesCounter << " tried" << endl;
time_t delta = runTime();
os << "Total time used: " << delta/60 << " min " << delta - 60*(delta/60) << " sec" << endl;
}
time_t SartreInclusiveDiffraction::runTime() const
{
time_t now = time(0);
return now-mStartTime;
}
//==============================================================================
//
// Utility functions and operators (helpers)
//
//==============================================================================
ostream& operator<<(ostream& os, const TLorentzVector& v)
{
os << v.Px() << '\t' << v.Py() << '\t' << v.Pz() << '\t' << v.E() << '\t';
double m2 = v*v;
if (m2 < 0)
os << '(' << -sqrt(-m2) << ')';
else
os << '(' << sqrt(m2) << ')';
return os;
}
Index: trunk/src/CMakeLists.txt
===================================================================
--- trunk/src/CMakeLists.txt (revision 537)
+++ trunk/src/CMakeLists.txt (revision 538)
@@ -1,181 +1,182 @@
#===============================================================================
# CMakeLists.txt (src)
#
# Copyright (C) 2010-2024 Tobias Toll and Thomas Ullrich
#
# This file is part of Sartre.
#
# This program 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.
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
# Author: Thomas Ullrich
# Last update:
# $Date$
# $Author$
#===============================================================================
include(ExternalProject)
cmake_minimum_required (VERSION 3.5)
#
# Compiler flags for release and debug version
#
set(CMAKE_C_FLAGS "-W")
set(CMAKE_C_FLAGS_DEBUG "-g")
set(CMAKE_C_FLAGS_RELEASE "-O")
message("COMPILER = ${CMAKE_CXX_COMPILER_ID}")
set(CMAKE_CXX_FLAGS "-W -Wall -Wextra -pedantic -Wno-long-long")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-potentially-evaluated-expression")
endif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
#
# Find external required packages
# (see also FindGSL.cmake and FindROOT.cmke in cmake/modules)
# Herer we need only the root library to create the table
# tools.
#
# GSL
find_package(GSL REQUIRED)
include_directories(${GSL_INCLUDE_DIR})
# ROOT
find_package(ROOT REQUIRED)
include_directories(${ROOT_INCLUDE_DIR})
set(LIBS ${LIBS} ${ROOT_LIBRARIES})
# strip leading and trailing blanks
string(REGEX REPLACE "\n$" "" LIBS "${LIBS}")
string(STRIP "${LIBS}" LIBS)
#BOOST
-if (MULTITHREADED)
+#if (MULTITHREADED)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
find_package(Boost 1.39 COMPONENTS thread REQUIRED)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIR})
endif(Boost_FOUND)
-endif (MULTITHREADED)
+#endif (MULTITHREADED)
# strip leading and trailing blanks
string(REGEX REPLACE "\n$" "" LIBS "${LIBS}")
string(STRIP "${LIBS}" LIBS)
# PYTHIA8
find_package(Pythia8 REQUIRED)
include_directories(${PYTHIA8_INCLUDE_DIR})
set(LIBS ${LIBS} ${PYTHIA8_LIBRARIES})
# strip leading and trailing blanks
string(REGEX REPLACE "\n$" "" LIBS "${LIBS}")
string(STRIP "${LIBS}" LIBS)
#
# Include files from sartre package
#
include_directories(${PROJECT_SOURCE_DIR}/src)
include_directories(${PROJECT_SOURCE_DIR}/gemini)
include_directories(${PROJECT_SOURCE_DIR}/cuba)
#
# Cuba is built using the autoconf shipped with it
#
ExternalProject_Add(
cuba
DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/cuba ${PROJECT_BINARY_DIR}/cuba
SOURCE_DIR ${PROJECT_BINARY_DIR}/cuba
PREFIX ${PROJECT_BINARY_DIR}/cuba
CONFIGURE_COMMAND ${PROJECT_BINARY_DIR}/cuba/configure --prefix=${PROJECT_BINARY_DIR}/cuba/build
BUILD_COMMAND make lib
BUILD_IN_SOURCE 1
)
#
# Defines source files for sartre library
#
set(SARTRE_SRC "AlphaStrong.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "Amplitudes.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "BreakupProduct.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "CrossSection.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "DglapEvolution.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "DipoleModel.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "DipoleModelParameters.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "EicSmearFormatWriter.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "Event.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "EventGeneratorSettings.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "ExclusiveFinalStateGenerator.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "FinalStateGenerator.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "FrangibleNucleus.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "InclusiveDiffractiveCrossSections.cpp")
+set(SARTRE_SRC ${SARTRE_SRC} "InclusiveDiffractiveCrossSectionsFromTables.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "InclusiveFinalStateGenerator.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "Integrals.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "Kinematics.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "ModeFinderFunctor.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "Nucleon.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "Nucleus.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "PhotonFlux.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "Sartre.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "SartreInclusiveDiffraction.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "Settings.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "Table.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "TableCollection.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "TableGeneratorNucleus.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "TableGeneratorSettings.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "TwoBodyVectorMesonDecay.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "VectorMesonDecayMass.cpp")
set(SARTRE_SRC ${SARTRE_SRC} "WaveOverlap.cpp")
add_library(sartre ${SARTRE_SRC})
#
# Table tools (all stand alone programs)
#
add_executable(tableInspector tableInspector.cpp)
add_executable(tableMerger tableMerger.cpp)
add_executable(tableQuery tableQuery.cpp)
add_executable(tableDumper tableDumper.cpp)
add_executable(tableVarianceMaker tableVarianceMaker.cpp)
target_link_libraries(tableInspector sartre ${LIBS})
target_link_libraries(tableMerger sartre ${LIBS})
target_link_libraries(tableQuery sartre ${LIBS})
target_link_libraries(tableDumper sartre ${LIBS})
target_link_libraries(tableVarianceMaker sartre ${LIBS})
add_dependencies(tableInspector sartre)
add_dependencies(tableMerger sartre)
add_dependencies(tableQuery sartre)
add_dependencies(tableDumper sartre)
add_dependencies(tableVarianceMaker sartre)
#
# Install library and include files (make install) within
# the distribution tree. Top level CMakeLists.txt will install
# Sartre in final destination.
#
install(TARGETS sartre DESTINATION sartre/lib)
install(FILES "${PROJECT_BINARY_DIR}/cuba/build/lib/libcuba.a" DESTINATION sartre/lib)
FILE(GLOB AllIncludeFiles *.h)
install(FILES ${AllIncludeFiles} DESTINATION sartre/include)
install(FILES "${PROJECT_BINARY_DIR}/cuba/build/include/cuba.h" DESTINATION sartre/include)
install(TARGETS tableInspector DESTINATION sartre/bin)
install(TARGETS tableMerger DESTINATION sartre/bin)
install(TARGETS tableQuery DESTINATION sartre/bin)
install(TARGETS tableDumper DESTINATION sartre/bin)
install(TARGETS tableVarianceMaker DESTINATION sartre/bin)
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Jan 20, 9:01 PM (23 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4242367
Default Alt Text
(126 KB)
Attached To
rSARTRESVN sartresvn
Event Timeline
Log In to Comment