Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cc6e0cb..5220347 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,59 +1,59 @@
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(CepGen)
set(PROJECT_VERSION 1)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic-errors -std=c++11 -g")
else()
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.7)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic-errors -std=c++11 -g")
else()
message(FATAL_ERROR "gcc version >= 4.7 is required")
endif()
endif()
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/cmake)
set(CEPGEN_SOURCE_DIR ${PROJECT_SOURCE_DIR}/CepGen)
-set(CEPGEN_LIBRARIES CepGenCore CepGenEvent CepGenPhysics CepGenProcesses CepGenStructureFunctions CepGenExporter CepGenExternalHadronisers)
+set(CEPGEN_LIBRARIES CepGenCore CepGenEvent CepGenPhysics CepGenProcesses CepGenStructureFunctions CepGenExporter CepGenIO CepGenExternalHadronisers)
#----- define all individual modules to be built beforehand
-set(CEPGEN_MODULES Processes Event Physics StructureFunctions Export Hadronisers)
+set(CEPGEN_MODULES Processes Event Physics StructureFunctions Export IO Hadronisers)
#----- enable fortran (for Pythia/Herwig/...)
enable_language(Fortran)
#----- include external paths
set(CEPGEN_EXTERNAL_REQS "")
include(UseEnvironment)
#----- build all the intermediate objects
include_directories(${PROJECT_SOURCE_DIR})
add_subdirectory(${CEPGEN_SOURCE_DIR})
foreach(_module ${CEPGEN_MODULES})
include_directories(${CEPGEN_SOURCE_DIR}/${_module})
add_subdirectory(${CEPGEN_SOURCE_DIR}/${_module})
endforeach()
#----- copy the input cards and other files
file(GLOB input_cards RELATIVE ${PROJECT_SOURCE_DIR} Cards/*)
foreach(_files ${input_cards})
configure_file(${_files} ${_files} COPYONLY)
endforeach()
configure_file(${CEPGEN_SOURCE_DIR}/README README COPYONLY)
#----- installation rules
set(MODS "")
foreach(_module ${CEPGEN_MODULES})
list(APPEND MODS CepGen/${module})
endforeach()
install(DIRECTORY ${MODS} DESTINATION include/CepGen FILES_MATCHING PATTERN "*.h")
#----- set the tests/utils directory
add_subdirectory(test)
diff --git a/CepGen/CMakeLists.txt b/CepGen/CMakeLists.txt
index 4c7a7a1..f6a46b8 100644
--- a/CepGen/CMakeLists.txt
+++ b/CepGen/CMakeLists.txt
@@ -1,11 +1,10 @@
file(GLOB core_sources Core/*.cpp *.cpp)
file(GLOB cards_sources Cards/*.cpp)
-file(GLOB io_sources IO/FortranInterface.cpp)
include_directories(${PROJECT_SOURCE_DIR})
-add_library(CepGenCore SHARED ${core_sources} ${cards_sources} ${io_sources})
+add_library(CepGenCore SHARED ${core_sources} ${cards_sources})
target_link_libraries(CepGenCore rt)
install(TARGETS CepGenCore DESTINATION lib)
diff --git a/CepGen/Cards/ConfigHandler.cpp b/CepGen/Cards/ConfigHandler.cpp
index 6b7f8e7..531987f 100644
--- a/CepGen/Cards/ConfigHandler.cpp
+++ b/CepGen/Cards/ConfigHandler.cpp
@@ -1,309 +1,310 @@
#include "ConfigHandler.h"
#include "CepGen/Core/Exception.h"
#include "CepGen/Processes/GamGamLL.h"
#include "CepGen/Processes/PPtoLL.h"
#include "CepGen/Processes/PPtoWW.h"
#include "CepGen/Hadronisers/Pythia8Hadroniser.h"
namespace CepGen
{
namespace Cards
{
//----- specialization for CepGen input cards
ConfigHandler::ConfigHandler( const char* file )
{
#ifdef LIBCONFIG
libconfig::Config cfg;
try { cfg.readFile( file ); } catch ( const libconfig::ParseException& pe ) {
FatalError( Form( "Failed to parse the configuration card \"%s\".\n\tParser error: %s (at line %d)", file, pe.getError(), pe.getLine() ) );
}
try {
const libconfig::Setting& root = cfg.getRoot();
const libconfig::Setting& proc = root["process"];
//--- type of process to consider
const char* proc_name = proc["name"]; const std::string str_proc_name = proc_name;
if ( str_proc_name == "lpair" ) params_.setProcess( new Process::GamGamLL );
else if ( str_proc_name == "pptoll" ) params_.setProcess( new Process::PPtoLL );
else if ( str_proc_name == "pptoww" ) params_.setProcess( new Process::PPtoWW );
else FatalError( Form( "Unrecognised process: %s", proc_name ) );
//--- process mode
int int_mode; const char* mode;
if ( proc.lookupValue( "mode", int_mode ) ) {
params_.kinematics.mode = (Kinematics::ProcessMode)int_mode;
}
else if ( proc.lookupValue( "mode", mode ) ) {
const std::string str_mode = mode;
if ( str_mode == "elastic/elastic" ) params_.kinematics.mode = Kinematics::ProcessMode::ElasticElastic;
else if ( str_mode == "elastic/inelastic" ) params_.kinematics.mode = Kinematics::ProcessMode::ElasticInelastic;
else if ( str_mode == "inelastic/elastic" ) params_.kinematics.mode = Kinematics::ProcessMode::InelasticElastic;
else if ( str_mode == "inelastic/inelastic" ) params_.kinematics.mode = Kinematics::ProcessMode::InelasticInelastic;
else FatalError( Form( "Unrecognised interaction mode: %s", mode ) );
}
//--- process kinematics
if ( proc.exists( "in_kinematics" ) ) parseIncomingKinematics( proc["in_kinematics"] );
if ( proc.exists( "out_kinematics" ) ) parseOutgoingKinematics( proc["out_kinematics"] );
//--- hadroniser parameters
if ( root.exists( "hadroniser" ) ) parseHadroniser( root["hadroniser"] );
//--- generation parameters
if ( root.exists( "integrator" ) ) parseIntegrator( root["integrator"] );
if ( root.exists( "vegas" ) ) parseIntegrator( root["vegas"] ); //FIXME for backward compatibility
if ( root.exists( "generator" ) ) parseGenerator( root["generator"] );
//--- taming functions
if ( proc.exists( "taming_functions" ) ) parseTamingFunctions( proc["taming_functions"] );
} catch ( const libconfig::SettingNotFoundException& nfe ) {
FatalError( Form( "Failed to retrieve the field \"%s\".", nfe.getPath() ) );
} catch ( const libconfig::SettingTypeException& te ) {
FatalError( Form( "Field \"%s\" has wrong type.", te.getPath() ) );
}
#else
InWarning( "libconfig++ is not present on this machine" );
#endif
}
#ifdef LIBCONFIG
void
ConfigHandler::parseIncomingKinematics( const libconfig::Setting& kin )
{
try {
if ( kin.exists( "beam1_pz" ) ) params_.kinematics.inp.first = (double)kin["beam1_pz"];
if ( kin.exists( "beam2_pz" ) ) params_.kinematics.inp.second = (double)kin["beam2_pz"];
if ( kin.exists( "structure_functions" ) ) {
const char* sf = kin["structure_functions" ]; const std::string sf_str = sf;
if ( sf_str == "electron" ) params_.kinematics.structure_functions = StructureFunctions::Electron;
else if ( sf_str == "elastic proton" ) params_.kinematics.structure_functions = StructureFunctions::ElasticProton;
else if ( sf_str == "Suri-Yennie" ) params_.kinematics.structure_functions = StructureFunctions::SuriYennie;
else if ( sf_str == "Szczurek-Uleshchenko" ) params_.kinematics.structure_functions = StructureFunctions::SzczurekUleshchenko;
else if ( sf_str == "Fiore" ) params_.kinematics.structure_functions = StructureFunctions::FioreBrasse;
else if ( sf_str == "ALLM" ) params_.kinematics.structure_functions = StructureFunctions::ALLM97;
else if ( sf_str == "ALLM;91" ) params_.kinematics.structure_functions = StructureFunctions::ALLM91;
else if ( sf_str == "ALLM;97" ) params_.kinematics.structure_functions = StructureFunctions::ALLM97;
//else if ( sf_str == "ALLM;HHT" ) params_.kinematics.structure_functions = StructureFunctions::ALLM_HHT;
//else if ( sf_str == "ALLM;HHT-FT" ) params_.kinematics.structure_functions = StructureFunctions::ALLM_HHT_FT;
else if ( sf_str == "ALLM;GD07p" ) params_.kinematics.structure_functions = StructureFunctions::GD07p;
else if ( sf_str == "ALLM;GD11p" ) params_.kinematics.structure_functions = StructureFunctions::GD11p;
+ else if ( sf_str == "Schaefer" ) params_.kinematics.structure_functions = StructureFunctions::Schaefer;
else FatalError( Form( "Invalid structure functions mode: %s", sf ) );
}
} catch ( const libconfig::SettingNotFoundException& nfe ) {
FatalError( Form( "Failed to retrieve the field \"%s\".", nfe.getPath() ) );
} catch ( const libconfig::SettingTypeException& te ) {
FatalError( Form( "Field \"%s\" has wrong type.", te.getPath() ) );
}
}
void
ConfigHandler::parseOutgoingKinematics( const libconfig::Setting& kin )
{
try {
if ( kin.exists( "pair" ) ) {
- Particle::ParticleCode pair = (Particle::ParticleCode)(int)kin["pair"];
+ ParticleCode pair = (ParticleCode)(int)kin["pair"];
params_.kinematics.central_system = { pair, pair };
}
if ( kin.exists( "min_pt" ) ) params_.kinematics.cuts.central[Cuts::pt_single].min() = (double)kin["min_pt"];
if ( kin.exists( "max_pt" ) ) params_.kinematics.cuts.central[Cuts::pt_single].max() = (double)kin["max_pt"];
if ( kin.exists( "min_ptdiff" ) ) params_.kinematics.cuts.central[Cuts::pt_diff].min() = (double)kin["min_ptdiff"];
if ( kin.exists( "max_ptdiff" ) ) params_.kinematics.cuts.central[Cuts::pt_diff].max() = (double)kin["max_ptdiff"];
if ( kin.exists( "min_rapiditydiff" ) ) params_.kinematics.cuts.central[Cuts::rapidity_diff].min() = (double)kin["min_rapiditydiff"];
if ( kin.exists( "max_rapiditydiff" ) ) params_.kinematics.cuts.central[Cuts::rapidity_diff].max() = (double)kin["max_rapiditydiff"];
if ( kin.exists( "min_energy" ) ) params_.kinematics.cuts.central[Cuts::energy_single].min() = (double)kin["min_energy"];
if ( kin.exists( "max_energy" ) ) params_.kinematics.cuts.central[Cuts::energy_single].max() = (double)kin["max_energy"];
if ( kin.exists( "min_eta" ) ) params_.kinematics.cuts.central[Cuts::eta_single].min() = (double)kin["min_eta"];
if ( kin.exists( "max_eta" ) ) params_.kinematics.cuts.central[Cuts::eta_single].max() = (double)kin["max_eta"];
if ( kin.exists( "min_rapidity" ) ) params_.kinematics.cuts.central[Cuts::rapidity_single].min() = (double)kin["min_rapidity"];
if ( kin.exists( "max_rapidity" ) ) params_.kinematics.cuts.central[Cuts::rapidity_single].max() = (double)kin["max_rapidity"];
if ( kin.exists( "min_mx" ) ) params_.kinematics.cuts.remnants[Cuts::mass].min() = (double)kin["min_mx"];
if ( kin.exists( "max_mx" ) ) params_.kinematics.cuts.remnants[Cuts::mass].max() = (double)kin["max_mx"];
} catch ( const libconfig::SettingNotFoundException& nfe ) {
FatalError( Form( "Failed to retrieve the field \"%s\".", nfe.getPath() ) );
} catch ( const libconfig::SettingTypeException& te ) {
FatalError( Form( "Field \"%s\" has wrong type.", te.getPath() ) );
}
}
void
ConfigHandler::parseIntegrator( const libconfig::Setting& integr )
{
try {
if ( integr.exists( "algorithm" ) ) {
const std::string algo = integr["algorithm"];
if ( algo == "Vegas" ) params_.integrator.type = Integrator::Vegas;
else if ( algo == "MISER" ) params_.integrator.type = Integrator::MISER;
}
if ( integr.exists( "num_points" ) ) params_.integrator.npoints = (int)integr["num_points"];
if ( integr.exists( "num_integration_calls" ) ) params_.integrator.ncvg = (int)integr["num_integration_calls"];
if ( integr.exists( "num_integration_iterations" ) ) params_.integrator.itvg = (int)integr["num_integration_iterations"];
if ( integr.exists( "seed" ) ) params_.integrator.seed = (unsigned long)integr["seed"];
} catch ( const libconfig::SettingNotFoundException& nfe ) {
FatalError( Form( "Failed to retrieve the field \"%s\".", nfe.getPath() ) );
}
}
void
ConfigHandler::parseGenerator( const libconfig::Setting& gen )
{
params_.generation.enabled = true;
try {
if ( gen.exists( "num_events" ) ) params_.generation.maxgen = (int)gen["num_events"];
if ( gen.exists( "print_every" ) ) params_.generation.gen_print_every = (int)gen["print_every"];
} catch ( const libconfig::SettingNotFoundException& nfe ) {
FatalError( Form( "Failed to retrieve the field \"%s\".", nfe.getPath() ) );
}
}
void
ConfigHandler::parseTamingFunctions( const libconfig::Setting& tf )
{
if ( !tf.isList() ) FatalError( "The taming functions definition must be wrapped within a list!" );
for ( unsigned short i = 0; i < tf.getLength(); ++i ) {
params_.taming_functions.add( tf[i]["variable"], tf[i]["expression"] );
}
}
void
ConfigHandler::parseHadroniser( const libconfig::Setting& hadr )
{
try {
std::string hadr_name = hadr["name"];
if ( hadr_name == "pythia8" ) {
#ifdef PYTHIA8
Hadroniser::Pythia8Hadroniser* pythia8 = new Hadroniser::Pythia8Hadroniser;
long long seed = ( hadr.exists( "seed" ) ) ? hadr["seed"] : -1ll;
pythia8->setSeed( seed );
pythia8->readString( Form( "Beams:eCM = %.2f", params_.kinematics.sqrtS() ) );
if ( hadr.exists( "pythiaPreConfiguration" ) ) {
libconfig::Setting& configs = hadr["pythiaPreConfiguration"];
if ( !configs.isList() ) throw libconfig::SettingTypeException( configs );
for ( unsigned short i = 0; i < configs.getLength(); ++i ) {
std::string config = configs[i];
pythia8->readString( config );
}
}
pythia8->init();
if ( hadr.exists( "pythiaConfiguration" ) ) {
libconfig::Setting& configs = hadr["pythiaConfiguration"];
if ( !configs.isList() ) throw libconfig::SettingTypeException( configs );
for ( unsigned short i = 0; i < configs.getLength(); ++i ) {
std::string config = configs[i];
pythia8->readString( config );
}
}
params_.setHadroniser( pythia8 );
#endif
}
} catch ( const libconfig::SettingTypeException& nfe ) {
FatalError( Form( "Wrong type to the field \"%s\".", nfe.getPath() ) );
} catch ( const libconfig::SettingNotFoundException& nfe ) {
FatalError( Form( "Failed to retrieve the field \"%s\".", nfe.getPath() ) );
}
}
void
ConfigHandler::writeProcess( const Parameters* params, libconfig::Setting& root )
{
libconfig::Setting& proc = root.add( "process", libconfig::Setting::TypeGroup );
proc.add( "name", libconfig::Setting::TypeString ) = params->processName();
std::ostringstream os; os << params->kinematics.mode;
proc.add( "mode", libconfig::Setting::TypeString ) = os.str();
}
void
ConfigHandler::writeIncomingKinematics( const Parameters* params, libconfig::Setting& root )
{
libconfig::Setting& kin = root.add( "in_kinematics", libconfig::Setting::TypeGroup );
kin.add( "beam1_pz", libconfig::Setting::TypeFloat ) = params->kinematics.inp.first;
kin.add( "beam2_pz", libconfig::Setting::TypeFloat ) = params->kinematics.inp.second;
std::ostringstream os; os << params->kinematics.structure_functions;
kin.add( "structure_function", libconfig::Setting::TypeString ) = os.str();
}
void
ConfigHandler::writeOutgoingKinematics( const Parameters* params, libconfig::Setting& root )
{
libconfig::Setting& kin = root.add( "out_kinematics", libconfig::Setting::TypeGroup );
if ( params->kinematics.central_system.size() > 0 )
kin.add( "pair", libconfig::Setting::TypeInt ) = (int)params->kinematics.central_system[0];
if ( params->kinematics.cuts.central.count( Cuts::pt_single ) ) {
kin.add( "min_pt", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.central.at( Cuts::pt_single ).min();
kin.add( "max_pt", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.central.at( Cuts::pt_single ).max();
}
if ( params->kinematics.cuts.central.count( Cuts::pt_diff ) ) {
kin.add( "min_ptdiff", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.central.at( Cuts::pt_diff ).min();
kin.add( "max_ptdiff", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.central.at( Cuts::pt_diff ).max();
}
if ( params->kinematics.cuts.central.count( Cuts::rapidity_diff ) ) {
kin.add( "min_rapiditydiff", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.central.at( Cuts::rapidity_diff ).min();
kin.add( "max_rapiditydiff", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.central.at( Cuts::rapidity_diff ).max();
}
if ( params->kinematics.cuts.central.count( Cuts::energy_single ) ) {
kin.add( "min_energy", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.central.at( Cuts::energy_single ).min();
kin.add( "max_energy", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.central.at( Cuts::energy_single ).max();
}
if ( params->kinematics.cuts.central.count( Cuts::eta_single ) ) {
kin.add( "min_eta", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.central.at( Cuts::eta_single ).min();
kin.add( "max_eta", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.central.at( Cuts::eta_single ).max();
}
if ( params->kinematics.cuts.remnants.count( Cuts::mass ) ) {
kin.add( "min_mx", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.remnants.at( Cuts::mass ).min();
kin.add( "max_mx", libconfig::Setting::TypeFloat ) = params->kinematics.cuts.remnants.at( Cuts::mass ).max();
}
}
void
ConfigHandler::writeTamingFunctions( const Parameters* params, libconfig::Setting& root )
{
libconfig::Setting& tf = root.add( "taming_functions", libconfig::Setting::TypeList );
for ( std::map<std::string,TamingFunction>::const_iterator it = params->taming_functions.begin(); it != params->taming_functions.end(); ++it ) {
libconfig::Setting& fun = tf.add( libconfig::Setting::TypeGroup );
fun.add( "variable", libconfig::Setting::TypeString ) = it->first;
fun.add( "expression", libconfig::Setting::TypeString ) = it->second.expression;
}
}
void
ConfigHandler::writeIntegrator( const Parameters* params, libconfig::Setting& root )
{
libconfig::Setting& integr = root.add( "integrator", libconfig::Setting::TypeGroup );
std::ostringstream os; os << params->integrator.type;
integr.add( "algorithm", libconfig::Setting::TypeString ) = os.str();
integr.add( "num_points", libconfig::Setting::TypeInt ) = (int)params->integrator.npoints;
integr.add( "num_integration_calls", libconfig::Setting::TypeInt ) = (int)params->integrator.ncvg;
integr.add( "num_integration_iterations", libconfig::Setting::TypeInt ) = (int)params->integrator.itvg;
integr.add( "seed", libconfig::Setting::TypeInt64 ) = (long)params->integrator.seed;
}
void
ConfigHandler::writeGenerator( const Parameters* params, libconfig::Setting& root )
{
if ( !params->generation.enabled ) return;
libconfig::Setting& gen = root.add( "generator", libconfig::Setting::TypeGroup );
gen.add( "num_events", libconfig::Setting::TypeInt ) = (int)params->generation.maxgen;
gen.add( "print_every", libconfig::Setting::TypeInt ) = (int)params->generation.gen_print_every;
}
#endif
void
ConfigHandler::store( const Parameters* params, const char* file )
{
#ifdef LIBCONFIG
libconfig::Config cfg;
libconfig::Setting& root = cfg.getRoot();
writeProcess( params, root );
writeIncomingKinematics( params, root["process"] );
writeOutgoingKinematics( params, root["process"] );
writeTamingFunctions( params, root["process"] );
writeIntegrator( params, root );
writeGenerator( params, root );
cfg.writeFile( file );
#endif
}
}
}
diff --git a/CepGen/Cards/LpairHandler.cpp b/CepGen/Cards/LpairHandler.cpp
index 903e751..2472f54 100644
--- a/CepGen/Cards/LpairHandler.cpp
+++ b/CepGen/Cards/LpairHandler.cpp
@@ -1,148 +1,148 @@
#include "LpairHandler.h"
#include "CepGen/Core/Exception.h"
#include "CepGen/Processes/GamGamLL.h"
#include "CepGen/Processes/PPtoLL.h"
#include "CepGen/Processes/PPtoWW.h"
#include "CepGen/Hadronisers/Pythia8Hadroniser.h"
#include <fstream>
namespace CepGen
{
namespace Cards
{
//----- specialization for LPAIR input cards
LpairHandler::LpairHandler( const char* file ) :
- pair_( Particle::invalidParticle )
+ pair_( invalidParticle )
{
std::ifstream f( file, std::fstream::in );
if ( !f.is_open() ) {
FatalError( Form( "Failed to parse file \"%s\"", file ) );
return;
}
init( &params_ );
std::ostringstream os;
os << Form( "File '%s' succesfully opened! The following parameters are set:\n", file );
std::map<std::string, std::string> m_params;
std::string key, value;
while ( f >> key >> value ) {
if ( key[0] == '#' ) continue; // FIXME need to ensure there is no extra space before!
setParameter( key, value );
m_params.insert( std::pair<std::string,std::string>( key, value ) );
if ( getDescription( key ) != "null" ) os << ">> " << key << " = " << std::setw( 15 ) << getParameter( key ) << " (" << getDescription( key ) << ")" << std::endl;
}
f.close();
if ( proc_name_ == "lpair" ) params_.setProcess( new Process::GamGamLL() );
else if ( proc_name_ == "pptoll" ) params_.setProcess( new Process::PPtoLL() );
else if ( proc_name_ == "pptoww" ) params_.setProcess( new Process::PPtoWW() );
else FatalError( Form( "Unrecognised process name: %s", proc_name_.c_str() ) );
if ( integr_type_ == "Vegas" ) params_.integrator.type = Integrator::Vegas;
else if ( integr_type_ == "MISER" ) params_.integrator.type = Integrator::MISER;
#ifdef PYTHIA8
if ( hadr_name_ == "pythia8" ) params_.setHadroniser( new Hadroniser::Pythia8Hadroniser );
#endif
if ( m_params.count( "IEND" ) ) setValue<bool>( "IEND", ( std::stoi( m_params["IEND"] ) > 1 ) );
//--- for LPAIR: specify the lepton pair to be produced
- if ( pair_ != Particle::invalidParticle ) {
+ if ( pair_ != invalidParticle ) {
params_.kinematics.central_system = { pair_, pair_ };
}
Information( os.str() );
}
void
LpairHandler::init( Parameters* params )
{
registerParameter<std::string>( "PROC", "Process name to simulate", &proc_name_ );
registerParameter<std::string>( "ITYP", "Integration algorithm", &integr_type_ );
registerParameter<std::string>( "HADR", "Hadronisation algorithm", &hadr_name_ );
registerParameter<bool>( "IEND", "Generation type", &params->generation.enabled );
registerParameter<unsigned int>( "DEBG", "Debugging verbosity", (unsigned int*)&Logger::get().level );
registerParameter<unsigned int>( "NCVG", "Number of function calls", &params->integrator.ncvg );
registerParameter<unsigned int>( "NCSG", "Number of points to probe", &params->integrator.npoints );
registerParameter<unsigned int>( "ITVG", "Number of integration iterations", &params->integrator.itvg );
registerParameter<unsigned int>( "SEED", "Random generator seed", (unsigned int*)&params->integrator.seed );
registerParameter<unsigned int>( "MODE", "Subprocess' mode", (unsigned int*)&params->kinematics.mode );
registerParameter<unsigned int>( "PMOD", "Outgoing primary particles' mode", (unsigned int*)&params->kinematics.structure_functions );
registerParameter<unsigned int>( "EMOD", "Outgoing primary particles' mode", (unsigned int*)&params->kinematics.structure_functions );
registerParameter<unsigned int>( "PAIR", "Outgoing particles' PDG id", (unsigned int*)&pair_ );
registerParameter<unsigned int>( "NGEN", "Number of events to generate", &params->generation.maxgen );
registerParameter<double>( "INPP", "Momentum (1st primary particle)", &params->kinematics.inp.first );
registerParameter<double>( "INPE", "Momentum (2nd primary particle)", &params->kinematics.inp.second );
registerParameter<double>( "PTCT", "Minimal transverse momentum (single central outgoing particle)", &params->kinematics.cuts.central[Cuts::pt_single].min() );
registerParameter<double>( "MSCT", "Minimal central system mass", &params->kinematics.cuts.central[Cuts::mass_sum].min() );
registerParameter<double>( "ECUT", "Minimal energy (single central outgoing particle)", &params->kinematics.cuts.central[Cuts::energy_single].min() );
//registerParameter<double>( "THMN", "Minimal polar production angle for the central particles", &params->kinematics.eta_min );
//registerParameter<double>( "THMX", "Maximal polar production angle for the central particles", &params->kinematics.eta_max );
registerParameter<double>( "ETMN", "Minimal pseudo-rapidity (central outgoing particles)", &params->kinematics.cuts.central[Cuts::eta_single].min() );
registerParameter<double>( "ETMX", "Maximal pseudo-rapidity (central outgoing particles)", &params->kinematics.cuts.central[Cuts::eta_single].max() );
registerParameter<double>( "YMIN", "Minimal rapidity (central outgoing particles)", &params->kinematics.cuts.central[Cuts::rapidity_single].min() );
registerParameter<double>( "YMAX", "Maximal rapidity (central outgoing particles)", &params->kinematics.cuts.central[Cuts::rapidity_single].max() );
registerParameter<double>( "Q2MN", "Minimal Q^2 (exchanged parton)", &params->kinematics.cuts.initial[Cuts::q2].min() );
registerParameter<double>( "Q2MX", "Maximal Q^2 (exchanged parton)", &params->kinematics.cuts.initial[Cuts::q2].max() );
registerParameter<double>( "MXMN", "Minimal invariant mass of proton remnants", &params->kinematics.cuts.remnants[Cuts::mass].min() );
registerParameter<double>( "MXMX", "Maximal invariant mass of proton remnants", &params->kinematics.cuts.remnants[Cuts::mass].max() );
}
void
LpairHandler::store( const char* file )
{
std::ofstream f( file, std::fstream::out | std::fstream::trunc );
if ( !f.is_open() ) {
InError( Form( "Failed to open file \"%s\" for writing", file ) );
return;
}
for ( const auto& it : p_strings_ ) { if ( it.second.value ) f << it.first << " = " << *it.second.value << "\n"; }
for ( const auto& it : p_ints_ ) { if ( it.second.value ) f << it.first << " = " << *it.second.value << "\n"; }
for ( const auto& it : p_doubles_ ) { if ( it.second.value ) f << it.first << " = " << *it.second.value << "\n"; }
for ( const auto& it : p_bools_ ) { if ( it.second.value ) f << it.first << " = " << *it.second.value << "\n"; }
f.close();
}
void
LpairHandler::setParameter( std::string key, std::string value )
{
try { setValue<double>( key.c_str(), std::stod( value ) ); } catch ( std::invalid_argument& ) {}
try { setValue<unsigned int>( key.c_str(), std::stoi( value ) ); } catch ( std::invalid_argument& ) {}
//setValue<bool>( key.c_str(), std::stoi( value ) );
setValue<std::string>( key.c_str(), value );
}
std::string
LpairHandler::getParameter( std::string key ) const
{
double dd = getValue<double>( key.c_str() );
if ( dd != -999. ) return std::to_string( dd );
unsigned int ui = getValue<unsigned int>( key.c_str() );
if ( ui != 999 ) return std::to_string( ui );
//if ( out = getValue<bool>( key.c_str() ) );
return getValue<std::string>( key.c_str() );
}
std::string
LpairHandler::getDescription( std::string key ) const
{
if ( p_strings_.count( key ) ) return p_strings_.find( key )->second.description;
if ( p_ints_.count( key ) ) return p_ints_.find( key )->second.description;
if ( p_doubles_.count( key ) ) return p_doubles_.find( key )->second.description;
if ( p_bools_.count( key ) ) return p_bools_.find( key )->second.description;
return "null";
}
}
}
diff --git a/CepGen/Cards/LpairHandler.h b/CepGen/Cards/LpairHandler.h
index a7da1fa..78a9e16 100644
--- a/CepGen/Cards/LpairHandler.h
+++ b/CepGen/Cards/LpairHandler.h
@@ -1,105 +1,105 @@
#ifndef CepGen_Cards_LpairReader_h
#define CepGen_Cards_LpairReader_h
#include "Handler.h"
using std::string;
using std::map;
namespace CepGen
{
namespace Cards
{
/// LPAIR-like steering cards parser and writer
class LpairHandler : public Handler
{
public:
/// Read a LPAIR steering card
LpairHandler( const char* file );
/// Store a configuration into a LPAIR steering card
void store( const char* file );
private:
template<class T> struct Parameter {
Parameter( const char* key, const char* descr, T* value ) : key( key ), description( descr ), value( value ) {}
std::string key, description;
T* value;
};
/// Register a parameter to be steered to a configuration variable
template<class T> void registerParameter( const char* key, const char* description, T* def ) {}
/// Set a parameter value
template<class T> void setValue( const char* key, T value ) {}
/// Retrieve a parameter value
template<class T> T getValue( const char* key ) const {}
void setParameter( std::string key, std::string value );
std::string getParameter( std::string key ) const;
std::string getDescription( std::string key ) const;
std::map<std::string, Parameter<std::string> > p_strings_;
std::map<std::string, Parameter<double> > p_doubles_;
std::map<std::string, Parameter<unsigned int> > p_ints_;
std::map<std::string, Parameter<bool> > p_bools_;
void init( Parameters* );
- Particle::ParticleCode pair_;
+ ParticleCode pair_;
std::string proc_name_, hadr_name_, integr_type_;
};
//----- specialised registerers
template<> inline void LpairHandler::registerParameter<std::string>( const char* key, const char* description, std::string* def ) { p_strings_.insert( std::make_pair( key, Parameter<std::string>( key, description, def ) ) ); }
template<> inline void LpairHandler::registerParameter<double>( const char* key, const char* description, double* def ) { p_doubles_.insert( std::make_pair( key, Parameter<double>( key, description, def ) ) ); }
template<> inline void LpairHandler::registerParameter<unsigned int>( const char* key, const char* description, unsigned int* def ) { p_ints_.insert( std::make_pair( key, Parameter<unsigned int>( key, description, def ) ) ); }
template<> inline void LpairHandler::registerParameter<bool>( const char* key, const char* description, bool* def ) { p_bools_.insert( std::make_pair( key, Parameter<bool>( key, description, def ) ) ); }
//----- specialised setters
template<> inline void LpairHandler::setValue<std::string>( const char* key, std::string value ) {
auto it = p_strings_.find( key );
if ( it != p_strings_.end() ) *it->second.value = value;
}
template<> inline void LpairHandler::setValue<double>( const char* key, double value ) {
auto it = p_doubles_.find( key );
if ( it != p_doubles_.end() ) *it->second.value = value;
}
template<> inline void LpairHandler::setValue<unsigned int>( const char* key, unsigned int value ) {
auto it = p_ints_.find( key );
if ( it != p_ints_.end() ) *it->second.value = value;
}
template<> inline void LpairHandler::setValue<bool>( const char* key, bool value ) {
auto it = p_bools_.find( key );
if ( it != p_bools_.end() ) *it->second.value = value;
}
//----- specialised getters
/// Retrieve a string parameter value
template<> inline std::string LpairHandler::getValue( const char* key ) const {
const auto& it = p_strings_.find( key );
if ( it != p_strings_.end() ) return *it->second.value;
return "null";
}
/// Retrieve a floating point parameter value
template<> inline double LpairHandler::getValue( const char* key ) const {
const auto& it = p_doubles_.find( key );
if ( it != p_doubles_.end() ) return *it->second.value;
return -999.;
}
/// Retrieve an integer parameter value
template<> inline unsigned int LpairHandler::getValue( const char* key ) const {
const auto& it = p_ints_.find( key );
if ( it != p_ints_.end() ) return *it->second.value;
return 999;
}
/// Retrieve a boolean parameter value
template<> inline bool LpairHandler::getValue( const char* key ) const {
const auto& it = p_bools_.find( key );
if ( it != p_bools_.end() ) return *it->second.value;
return true;
}
}
}
#endif
diff --git a/CepGen/Core/Generator.cpp b/CepGen/Core/Generator.cpp
index b56e13b..1a2898d 100644
--- a/CepGen/Core/Generator.cpp
+++ b/CepGen/Core/Generator.cpp
@@ -1,140 +1,141 @@
#include "CepGen/Generator.h"
#include "CepGen/Parameters.h"
+#include "CepGen/Version.h"
#include "CepGen/Core/Integrator.h"
#include "CepGen/Core/Exception.h"
#include "CepGen/Processes/GenericProcess.h"
#include "CepGen/Event/Event.h"
#include <fstream>
namespace CepGen
{
Generator::Generator() :
parameters( std::unique_ptr<Parameters>( new Parameters ) ),
cross_section_( -1. ), cross_section_error_( -1. ), has_cross_section_( false )
{
if ( Logger::get().level > Logger::Nothing ) {
Debugging( "Generator initialized" );
try { printHeader(); } catch ( Exception& e ) { e.dump(); }
}
srand( time( 0 ) ); // Random number initialization
}
Generator::Generator( Parameters* ip ) :
parameters( ip )
{}
Generator::~Generator()
{
if ( parameters->generation.enabled && parameters->process() && parameters->process()->numGeneratedEvents()>0 ) {
Information( Form( "Mean generation time / event: %.3f ms", parameters->process()->totalGenerationTime()*1.e3/parameters->process()->numGeneratedEvents() ) );
}
}
size_t
Generator::numDimensions() const
{
if ( !parameters->process() ) return 0;
return parameters->process()->numDimensions( parameters->kinematics.mode );
}
void
Generator::clearRun()
{
integrator_.reset();
parameters->integrator.first_run = true;
has_cross_section_ = false; // force the recreation of the integrator instance
cross_section_ = cross_section_error_ = -1.;
}
void
Generator::setParameters( Parameters& ip )
{
parameters = std::unique_ptr<Parameters>( new Parameters( ip ) ); // copy constructor
}
void
Generator::printHeader()
{
std::string tmp;
- std::ostringstream os; os << std::endl;
+ std::ostringstream os; os << "version " << version() << std::endl;
std::ifstream hf( "README" );
if ( !hf.good() ) throw Exception( __PRETTY_FUNCTION__, "Failed to open README file", JustWarning );
while ( true ) {
if ( !hf.good() ) break;
getline( hf, tmp );
os << "\n " << tmp;
}
hf.close();
Information( os.str().c_str() );
}
double
Generator::computePoint( double* x )
{
prepareFunction();
double res = f( x, numDimensions(), (void*)parameters.get() );
std::ostringstream os;
for ( unsigned int i=0; i<numDimensions(); i++ ) { os << x[i] << " "; }
Debugging( Form( "Result for x[%zu] = ( %s):\n\t%10.6f", numDimensions(), os.str().c_str(), res ) );
return res;
}
void
Generator::computeXsection( double& xsec, double& err )
{
// first destroy and recreate the integrator instance
if ( !integrator_ ) {
integrator_ = std::unique_ptr<Integrator>( new Integrator( numDimensions(), f, parameters.get() ) );
}
else if ( integrator_->dimensions() != numDimensions() ) {
integrator_.reset( new Integrator( numDimensions(), f, parameters.get() ) );
}
if ( Logger::get().level>=Logger::Debug ) {
std::ostringstream topo; topo << parameters->kinematics.mode;
Debugging( Form( "New integrator instance created\n\t"
"Considered topology: %s case\n\t"
"Will proceed with %d-dimensional integration", topo.str().c_str(), numDimensions() ) );
}
Information( "Starting the computation of the process cross-section" );
try { prepareFunction(); } catch ( Exception& e ) { e.dump(); }
has_cross_section_ = ( integrator_->integrate( cross_section_, cross_section_error_ ) == 0 );
xsec = cross_section_;
err = cross_section_error_;
Information( Form( "Total cross section: %f +/- %f pb", xsec, err ) );
}
Event*
Generator::generateOneEvent()
{
bool good = false;
if ( !has_cross_section_ ) {
computeXsection( cross_section_, cross_section_error_ );
}
while ( !good ) { good = integrator_->generateOneEvent(); }
last_event = this->parameters->generation.last_event;
return last_event.get();
}
void
Generator::prepareFunction()
{
if ( !parameters->process() ) {
throw Exception( __PRETTY_FUNCTION__, "No process defined!", FatalError );
}
Kinematics kin = parameters->kinematics;
parameters->process()->addEventContent();
parameters->process()->setKinematics( kin );
Debugging( "Function prepared to be integrated!" );
}
}
diff --git a/CepGen/Core/Integrand.cpp b/CepGen/Core/Integrand.cpp
index d383e32..d03e3a3 100644
--- a/CepGen/Core/Integrand.cpp
+++ b/CepGen/Core/Integrand.cpp
@@ -1,140 +1,140 @@
#include "CepGen/Core/Timer.h"
#include "CepGen/Core/Exception.h"
#include "CepGen/Event/Event.h"
#include "CepGen/Event/Particle.h"
#include "CepGen/Physics/Kinematics.h"
#include "CepGen/Processes/GenericProcess.h"
#include "CepGen/Parameters.h"
#include <sstream>
namespace CepGen
{
double
f( double* x, size_t ndim, void* params )
{
std::ostringstream os;
Parameters* p = static_cast<Parameters*>( params );
std::shared_ptr<Event> ev = p->process()->event();
if ( p->process()->hasEvent() ) {
p->process()->clearEvent();
const Particle::Momentum p1( 0., 0., p->kinematics.inp.first ), p2( 0., 0., -p->kinematics.inp.second );
p->process()->setIncomingKinematics( p1, p2 ); // at some point introduce non head-on colliding beams?
DebuggingInsideLoop( Form( "Function f called -- some parameters:\n\t"
" pz(p1) = %5.2f pz(p2) = %5.2f\n\t"
" remnant mode: %d",
p->kinematics.inp.first, p->kinematics.inp.second, p->kinematics.structure_functions ) );
if ( p->integrator.first_run ) {
if ( Logger::get().level >= Logger::Debug ) {
std::ostringstream oss; oss << p->kinematics.mode;
Debugging( Form( "Process mode considered: %s", oss.str().c_str() ) );
}
Particle& op1 = ev->getOneByRole( Particle::OutgoingBeam1 ),
&op2 = ev->getOneByRole( Particle::OutgoingBeam2 );
//--- add outgoing protons or remnants
switch ( p->kinematics.mode ) {
case Kinematics::ElectronProton: default: { InError( Form( "Process mode %d not yet handled!", (int)p->kinematics.mode ) ); }
case Kinematics::ElasticElastic: break; // nothing to change in the event
case Kinematics::ElasticInelastic:
- op2.setPdgId( Particle::uQuark, 1 ); break;
+ op2.setPdgId( uQuark, 1 ); break;
case Kinematics::InelasticElastic: // set one of the outgoing protons to be fragmented
- op1.setPdgId( Particle::uQuark, 1 ); break;
+ op1.setPdgId( uQuark, 1 ); break;
case Kinematics::InelasticInelastic: // set both the outgoing protons to be fragmented
- op1.setPdgId( Particle::uQuark, 1 );
- op2.setPdgId( Particle::uQuark, 1 );
+ op1.setPdgId( uQuark, 1 );
+ op2.setPdgId( uQuark, 1 );
break;
}
//--- prepare the function to be integrated
p->process()->prepareKinematics();
//--- add central system
Particles& central_system = ev->getByRole( Particle::CentralSystem );
if ( central_system.size() == p->kinematics.central_system.size() ) {
unsigned short i = 0;
for ( Particles::iterator part = central_system.begin(); part != central_system.end(); ++part ) {
- if ( p->kinematics.central_system[i] == Particle::invalidParticle ) continue;
+ if ( p->kinematics.central_system[i] == invalidParticle ) continue;
part->setPdgId( p->kinematics.central_system[i] );
part->computeMass();
i++;
}
}
p->process()->clearRun();
p->integrator.first_run = false;
}
} // event is not empty
p->process()->setPoint( ndim, x );
if ( Logger::get().level >= Logger::DebugInsideLoop ) {
std::ostringstream oss; for ( unsigned int i=0; i<ndim; i++ ) { oss << x[i] << " "; }
DebuggingInsideLoop( Form( "Computing dim-%d point ( %s)", ndim, oss.str().c_str() ) );
}
//--- from this step on, the phase space point is supposed to be set by 'GenericProcess::setPoint()'
p->process()->beforeComputeWeight();
Timer tmr; // start the timer
double integrand = p->process()->computeWeight();
if ( integrand <= 0. ) return 0.;
//--- fill in the process' Event object
p->process()->fillKinematics();
//--- once the kinematics variables have been populated,
// can apply the collection of taming functions
double taming = 1.0;
if ( p->taming_functions.has( "m_central" ) || p->taming_functions.has( "pt_central" ) ) {
const Particle::Momentum central_system( ev->getByRole( Particle::CentralSystem )[0].momentum() + ev->getByRole( Particle::CentralSystem )[1].momentum() );
taming *= p->taming_functions.eval( "m_central", central_system.mass() );
taming *= p->taming_functions.eval( "pt_central", central_system.pt() );
}
if ( p->taming_functions.has( "q2" ) ) {
taming *= p->taming_functions.eval( "q2", ev->getOneByRole( Particle::Parton1 ).momentum().mass() );
taming *= p->taming_functions.eval( "q2", ev->getOneByRole( Particle::Parton2 ).momentum().mass() );
}
integrand *= taming;
//--- full event content (+ hadronisation) if generating events
if ( p->hadroniser() ) {
if ( !p->hadroniser()->hadronise( *ev ) ) return 0.;
}
if ( p->storage() ) {
ev->time_generation = tmr.elapsed();
ev->time_total = tmr.elapsed();
p->process()->addGenerationTime( ev->time_total );
Debugging( Form( "Generation time: %5.6f sec\n\t"
"Total time (gen+hadr): %5.6f sec",
ev->time_generation,
ev->time_total ) );
p->generation.last_event = ev;
} // generating events
if ( Logger::get().level>=Logger::DebugInsideLoop ) {
os.str( "" ); for ( unsigned int i=0; i<ndim; i++ ) { os << Form( "%10.8f ", x[i] ); }
Debugging( Form( "f value for dim-%d point ( %s): %4.4e", ndim, os.str().c_str(), integrand ) );
}
return integrand;
}
}
diff --git a/CepGen/Core/Logger.cpp b/CepGen/Core/Logger.cpp
deleted file mode 100644
index 5267d73..0000000
--- a/CepGen/Core/Logger.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#include "Logger.h"
-
-namespace CepGen
-{
- Logger&
- Logger::get()
- {
- static Logger log;
- return log;
- }
-
- std::ostream&
- operator<<( std::ostream& os, const Logger::LoggingLevel& lvl )
- {
- switch ( lvl ) {
- case Logger::Nothing: os << "None"; break;
- case Logger::Error: os << "Errors"; break;
- case Logger::Warning: os << "Warnings"; break;
- case Logger::Information: os << "Infos"; break;
- case Logger::Debug: os << "Debug"; break;
- case Logger::DebugInsideLoop: os << "Debug (in loops)"; break;
- }
- return os;
- }
-}
diff --git a/CepGen/Core/Logger.h b/CepGen/Core/Logger.h
index cee526b..56b2542 100644
--- a/CepGen/Core/Logger.h
+++ b/CepGen/Core/Logger.h
@@ -1,37 +1,50 @@
#ifndef CepGen_Core_Logger_h
#define CepGen_Core_Logger_h
#include <iostream>
namespace CepGen
{
/**
* \brief General purposes logger
* \author Laurent Forthomme <laurent.forthomme@cern.ch>
* \date 15 Oct 2015
*/
class Logger
{
public:
/// Logging threshold for the output stream
enum LoggingLevel { Nothing=0, Error, Warning, Information, Debug, DebugInsideLoop };
private:
/// Initialize a logging object
Logger() : level( Warning ), outputStream( std::cout ) {}
~Logger() {}
public:
/// Retrieve the running instance of the logger
- static Logger& get();
+ static Logger& get() {
+ static Logger log;
+ return log;
+ }
/// Redirect the logger to a given output stream
- friend std::ostream& operator<<( std::ostream& os, const Logger::LoggingLevel& lvl );
+ friend std::ostream& operator<<( std::ostream& os, const Logger::LoggingLevel& lvl ) {
+ switch ( lvl ) {
+ case Logger::Nothing: os << "None"; break;
+ case Logger::Error: os << "Errors"; break;
+ case Logger::Warning: os << "Warnings"; break;
+ case Logger::Information: os << "Infos"; break;
+ case Logger::Debug: os << "Debug"; break;
+ case Logger::DebugInsideLoop: os << "Debug (in loops)"; break;
+ }
+ return os;
+ }
/// Logging threshold for the output stream
LoggingLevel level;
/// Output stream to use for all logging operations
std::ostream& outputStream;
};
}
#endif
diff --git a/CepGen/Core/Parameters.cpp b/CepGen/Core/Parameters.cpp
index 65ee937..65e39c6 100644
--- a/CepGen/Core/Parameters.cpp
+++ b/CepGen/Core/Parameters.cpp
@@ -1,121 +1,121 @@
#include "CepGen/Parameters.h"
#include "CepGen/Core/Exception.h"
#include "CepGen/Processes/GenericProcess.h"
namespace CepGen
{
Parameters::Parameters() :
store_( false )
{}
Parameters::Parameters( Parameters& param ) :
kinematics( param.kinematics ), integrator( param.integrator ), generation( param.generation ),
taming_functions( param.taming_functions ),
process_( std::move( param.process_ ) ), hadroniser_( std::move( param.hadroniser_ ) ),
store_( param.store_ )
{}
Parameters::Parameters( const Parameters& param ) :
kinematics( param.kinematics ), integrator( param.integrator ), generation( param.generation ),
taming_functions( param.taming_functions ),
store_( param.store_ )
{}
Parameters::~Parameters()
{}
void
Parameters::setThetaRange( float thetamin, float thetamax )
{
kinematics.cuts.central[Cuts::eta_single].in( Particle::thetaToEta( thetamax ), Particle::thetaToEta( thetamin ) );
if ( Logger::get().level >= Logger::Debug ) {
std::ostringstream os; os << kinematics.cuts.central[Cuts::eta_single];
Debugging( Form( "eta in range: %s => theta(min) = %5.2f, theta(max) = %5.2f",
os.str().c_str(), thetamin, thetamax ) );
}
}
std::string
Parameters::processName() const
{
if ( process_ ) return process_->name();
return "no process";
}
void
Parameters::dump( std::ostream& out, bool pretty ) const
{
std::ostringstream os;
const int wb = 75, wt = 32;
os.str( "" );
os
<< "Parameters dump" << std::left
<< std::endl << std::endl
<< std::setfill('_') << std::setw( wb ) << "_/¯ RUN INFORMATION ¯\\_" << std::setfill( ' ' ) << std::endl
<< std::right << std::setw( wb ) << std::left << std::endl
<< std::setw( wt ) << "Process to generate";
if ( process_ ) {
os << ( pretty ? boldify( process_->name().c_str() ) : process_->name() ) << std::endl
<< std::setw( wt ) << "" << process_->description();
}
else
os << ( pretty ? boldify( "no process!" ) : "no process!" );
os
<< std::endl
<< std::setw( wt ) << "Events generation? " << ( pretty ? yesno( generation.enabled ) : std::to_string( generation.enabled ) ) << std::endl
<< std::setw( wt ) << "Number of events to generate" << ( pretty ? boldify( generation.maxgen ) : std::to_string( generation.maxgen ) ) << std::endl
<< std::setw( wt ) << "Verbosity level " << Logger::get().level << std::endl;
if ( hadroniser_ ) {
os
<< std::endl
<< std::setfill( '-' ) << std::setw( wb+6 ) << ( pretty ? boldify( " Hadronisation algorithm " ) : "Hadronisation algorithm" ) << std::setfill( ' ' ) << std::endl
<< std::endl
<< std::setw( wt ) << "Name" << hadroniser_->name() << std::endl;
}
os
<< std::endl
<< std::setfill( '-' ) << std::setw( wb+6 ) << ( pretty ? boldify( " Integration parameters " ) : "Integration parameters" ) << std::setfill( ' ' ) << std::endl
<< std::endl;
std::ostringstream int_algo; int_algo << integrator.type;
os
<< std::setw( wt ) << "Integration algorithm" << ( pretty ? boldify( int_algo.str().c_str() ) : int_algo.str() ) << std::endl
<< std::setw( wt ) << "Maximum number of iterations" << ( pretty ? boldify( integrator.itvg ) : std::to_string( integrator.itvg ) ) << std::endl
<< std::setw( wt ) << "Number of function calls" << integrator.ncvg << std::endl
<< std::setw( wt ) << "Number of points to try per bin" << integrator.npoints << std::endl
<< std::setw( wt ) << "Random number generator seed" << integrator.seed << std::endl
<< std::endl
<< std::setfill('_') << std::setw( wb ) << "_/¯ EVENTS KINEMATICS ¯\\_" << std::setfill( ' ' ) << std::endl
<< std::endl
<< std::setfill( '-' ) << std::setw( wb+6 ) << ( pretty ? boldify( " Incoming particles " ) : "Incoming particles" ) << std::setfill( ' ' ) << std::endl
<< std::endl;
std::ostringstream proc_mode; proc_mode << kinematics.mode;
std::ostringstream ip1, ip2, op; ip1 << kinematics.inpdg.first; ip2 << kinematics.inpdg.second;
- for ( std::vector<Particle::ParticleCode>::const_iterator cp = kinematics.central_system.begin(); cp != kinematics.central_system.end(); ++cp )
+ for ( std::vector<ParticleCode>::const_iterator cp = kinematics.central_system.begin(); cp != kinematics.central_system.end(); ++cp )
op << ( cp != kinematics.central_system.begin() ? ", " : "" ) << *cp;
std::ostringstream q2range; q2range << kinematics.cuts.initial.at( Cuts::q2 );
os
<< std::setw( wt ) << "Subprocess mode" << ( pretty ? boldify( proc_mode.str().c_str() ) : proc_mode.str() ) << std::endl
<< std::setw( wt ) << "Incoming particles" << ( pretty ? boldify( ip1.str().c_str() ) : ip1.str() ) << ", " << ( pretty ? boldify( ip2.str().c_str() ) : ip2.str() ) << std::endl
<< std::setw( wt ) << "Momenta (GeV/c)" << kinematics.inp.first << ", " << kinematics.inp.second << std::endl
<< std::setw( wt ) << "Structure functions" << kinematics.structure_functions << std::endl
<< std::endl
<< std::setfill( '-' ) << std::setw( wb+6 ) << ( pretty ? boldify( " Incoming partons " ) : "Incoming partons" ) << std::setfill( ' ' ) << std::endl
<< std::endl
<< std::setw( wt ) << "Virtuality range" << ( pretty ? boldify( q2range.str().c_str() ) : q2range.str().c_str() ) << " GeV**2" << std::endl
<< std::endl
<< std::setfill( '-' ) << std::setw( wb+6 ) << ( pretty ? boldify( " Outgoing central system " ) : "Outgoing central system" ) << std::setfill( ' ' ) << std::endl
<< std::endl
<< std::setw( wt ) << "Central particles" << ( pretty ? boldify( op.str().c_str() ) : op.str() ) << std::endl;
for ( std::map<Cuts::Central, Kinematics::Limits>::const_iterator lim = kinematics.cuts.central.begin(); lim != kinematics.cuts.central.end(); ++lim ) {
os << std::setw( wt ) << lim->first << lim->second << std::endl;
}
os << std::setfill( '-' ) << std::setw( wb+6 ) << ( pretty ? boldify( " Proton / remnants " ) : "Proton / remnants" ) << std::setfill( ' ' ) << std::endl;
for ( std::map<Cuts::Remnants, Kinematics::Limits>::const_iterator lim = kinematics.cuts.remnants.begin(); lim != kinematics.cuts.remnants.end(); ++lim ) {
os << std::setw( wt ) << lim->first << lim->second << std::endl;
}
if ( pretty ) { Information( os.str() ); }
else out << os.str();
}
}
diff --git a/CepGen/Core/Version.cpp b/CepGen/Core/Version.cpp
new file mode 100644
index 0000000..0622c3a
--- /dev/null
+++ b/CepGen/Core/Version.cpp
@@ -0,0 +1,13 @@
+#include "CepGen/Version.h"
+
+namespace CepGen
+{
+ const char* version()
+ {
+ char* str = new char[9];
+ sprintf( str, "%02u.%02u.%02u", ( cepgen_version >> 16 ) & 0xff,
+ ( cepgen_version >> 8 ) & 0xff,
+ cepgen_version & 0xff );
+ return str;
+ }
+}
diff --git a/CepGen/Core/utils.cpp b/CepGen/Core/utils.cpp
index 95a9aae..3ad3dbd 100644
--- a/CepGen/Core/utils.cpp
+++ b/CepGen/Core/utils.cpp
@@ -1,74 +1,51 @@
#include "CepGen/Core/utils.h"
#include "CepGen/Core/Exception.h"
#include <stdlib.h>
-#include <stdarg.h> // For va_start, etc.
#include <stdio.h>
#include <math.h>
void Map( double expo, double xmin, double xmax, double& out, double& dout, const std::string& var_name_ )
{
const double y = xmax/xmin;
out = xmin*pow( y, expo );
dout = out*log( y );
DebuggingInsideLoop( Form( "Mapping variable \"%s\"\n\t"
"min = %f\n\tmax = %f\n\tmax/min = %f\n\t"
"exponent = %f\n\t"
"output = %f\n\td(output) = %f",
var_name_.c_str(), xmin, xmax, y, expo, out, dout ) );
}
void Mapla( double y, double z, int u, double xm, double xp, double& x, double& d )
{
double xmb, xpb, c, yy, zz, alp, alm, am, ap, ax;
xmb = xm-y-z;
xpb = xp-y-z;
c = -4.*y*z;
alp = sqrt( xpb*xpb + c );
alm = sqrt( xmb*xmb + c );
am = xmb+alm;
ap = xpb+alp;
yy = ap/am;
zz = pow( yy, u );
x = y + z + ( am*zz - c / ( am*zz ) ) / 2.;
ax = sqrt( pow( x-y-z, 2 ) + c );
d = ax*log( yy );
}
double BreitWigner( double er, double gamma, double emin, double emax, double x )
{
if ( x==-1. ) x = drand();
if ( gamma<1.e-3*er ) { return er; }
const double a = atan( 2.*( emax-er ) / gamma ),
b = atan( 2.*( emin-er ) / gamma ),
e = er + gamma*tan( x*( a - b ) + b ) / 2.;
if ( e>emax ) { return emax; }
return e;
}
-std::string
-Form( const std::string fmt, ... )
-{
- int size = ( (int)fmt.size() ) * 2 + 50; // Use a rubric appropriate for your code
- std::string str;
- va_list ap;
- while ( true ) { // Maximum two passes on a POSIX system...
- str.resize( size );
- va_start( ap, fmt );
- int n = vsnprintf( (char*)str.data(), size, fmt.c_str(), ap );
- va_end( ap );
- if ( n>-1 and n<size ) { // Everything worked
- str.resize( n );
- return str;
- }
- if ( n>-1 ) // Needed size returned
- size = n + 1; // For null char
- else size *= 2; // Guess at a larger size (OS specific)
- }
- return str;
-}
-
diff --git a/CepGen/Core/utils.h b/CepGen/Core/utils.h
index c1820f2..558ef8d 100644
--- a/CepGen/Core/utils.h
+++ b/CepGen/Core/utils.h
@@ -1,47 +1,67 @@
#ifndef CepGen_Core_utils_h
#define CepGen_Core_utils_h
#include <string>
+#include <stdarg.h> // For va_start, etc.
/// Provide a random number generated along a uniform distribution between 0 and 1
//inline double drand() { srand (time(nullptr)); return static_cast<double>(rand())/RAND_MAX; }
#define drand() static_cast<double>( rand()/RAND_MAX )
/// Format a string using a printf style format descriptor.
-std::string Form(const std::string fmt, ...);
+inline std::string Form( const std::string fmt, ... ) {
+ int size = ( (int)fmt.size() ) * 2 + 50; // Use a rubric appropriate for your code
+ std::string str;
+ va_list ap;
+ while ( true ) { // Maximum two passes on a POSIX system...
+ str.resize( size );
+ va_start( ap, fmt );
+ int n = vsnprintf( (char*)str.data(), size, fmt.c_str(), ap );
+ va_end( ap );
+ if ( n>-1 and n<size ) { // Everything worked
+ str.resize( n );
+ return str;
+ }
+ if ( n>-1 ) // Needed size returned
+ size = n + 1; // For null char
+ else size *= 2; // Guess at a larger size (OS specific)
+ }
+ return str;
+}
+
inline const char* yesno( const bool& test ) { return ( test ) ? "\033[32;1myes\033[0m" : "\033[31;1mno\033[0m"; }
//inline const char* boldify( const char* str ) { const std::string out = std::string( "\033[33;1m" ) + std::string( str ) + std::string( "\033[0m" ); return out.c_str(); }
inline std::string boldify( const std::string& str ) { return Form( "\033[1m%s\033[0m", str.c_str() ); }
inline std::string boldify( const char* str ) { return boldify( std::string( str ) ); }
inline std::string boldify( const double& dbl ) { return boldify( Form("%.2f", dbl ) ); }
inline std::string boldify( const int& i ) { return boldify( Form("% d", i ) ); }
inline std::string boldify( const unsigned int& ui ) { return boldify( Form("%d", ui ) ); }
namespace Colour{
enum TextColour { Gray=30, Red=31, Green=32, Yellow=33, Blue=34, Purple=35 };
}
inline std::string colourise( const std::string& str, const Colour::TextColour& col ) { return Form( "\033[%d%s\033[0m", col, str.c_str() ); }
/**
* Define modified variables of integration to avoid peaks integrations (see @cite Vermaseren1983347 for details)
* Return a set of two modified variables of integration to maintain the stability of the integrant. These two new variables are :
* - \f$y_{out} = x_{min}\left(\frac{x_{max}}{x_{min}}\right)^{exp}\f$ the new variable
* - \f$\mathrm dy_{out} = x_{min}\left(\frac{x_{max}}{x_{min}}\right)^{exp}\log\frac{x_{min}}{x_{max}}\f$, the new variable's differential form
* @brief Redefine the variables of integration in order to avoid the strong peaking of the integrant.
* @param[in] expo Exponant
* @param[in] xmin Minimal value of the variable
* @param[in] xmax Maximal value of the variable
* @param[out] out The new variable definition
* @param[out] dout The differential variant of the new variable definition
* @param[in] var_name The variable name
* @note This method overrides the set of `mapxx` subroutines in ILPAIR, with a slight difference according to the sign of the
* \f$\mathrm dy_{out}\f$ parameter :
* - left unchanged :
* > `mapw2`, `mapxq`, `mapwx`, `maps2`
* - opposite sign :
* > `mapt1`, `mapt2`
*/
void Map( double expo, double xmin, double xmax, double& out, double& dout, const std::string& var_name="" );
void Mapla( double y, double z, int u, double xm, double xp, double& x, double& d );
#endif
diff --git a/CepGen/Event/Particle.cpp b/CepGen/Event/Particle.cpp
index ea6dcf2..0a6a425 100644
--- a/CepGen/Event/Particle.cpp
+++ b/CepGen/Event/Particle.cpp
@@ -1,396 +1,282 @@
#include "Particle.h"
#include "CepGen/Core/Exception.h"
#include "CepGen/Core/utils.h"
#include "CepGen/Physics/Constants.h"
namespace CepGen
{
Particle::Particle() :
id_( -1 ), charge_sign_( 1 ),
mass_( -1. ), helicity_( 0. ),
role_( UnknownRole ), status_( Undefined ), pdg_id_( invalidParticle )
{}
Particle::Particle( Role role, ParticleCode pdgId, Status st ) :
id_( -1 ), charge_sign_( 1 ),
mass_( -1. ), helicity_( 0. ),
role_( role ), status_( st ), pdg_id_( pdgId )
{
if ( pdg_id_!=invalidParticle ) {
computeMass();
}
}
Particle::Particle( const Particle& part ) :
id_( part.id_ ), charge_sign_( part.charge_sign_ ),
momentum_( part.momentum_ ), mass_( part.mass_ ), helicity_( part.helicity_ ),
role_( part.role_ ), status_( part.status_ ),
mothers_( part.mothers_ ), daughters_( part.daughters_ ),
pdg_id_( part.pdg_id_ )
{}
bool
Particle::operator<( const Particle& rhs ) const
{
return ( id_ < rhs.id_ );
}
double
Particle::thetaToEta( double theta )
{
return -log( tan( 0.5 * theta * M_PI/180. ) );
}
double
Particle::etaToTheta( double eta )
{
return 2.*atan( exp( -eta ) )*180. / M_PI;
}
bool
Particle::valid()
{
if ( pdg_id_ == invalidParticle ) return false;
if ( momentum_.p() == 0. && mass() == 0. ) return false;
return true;
}
void
Particle::computeMass( bool off_shell )
{
if ( !off_shell && pdg_id_ != invalidParticle ) { // retrieve the mass from the on-shell particle's properties
- mass_ = massFromPDGId( pdg_id_ );
+ mass_ = ParticleProperties::mass( pdg_id_ );
}
else if ( momentum_.energy() >= 0. ) {
mass_ = sqrt( energy2() - momentum_.p2() );
}
//--- finish by setting the energy accordingly
if ( momentum_.energy() < 0. ) { // invalid energy
momentum_.setEnergy( sqrt( momentum_.p2() + mass2() ) );
}
}
void
Particle::setMass( double m )
{
if ( m >= 0. ) mass_ = m;
else computeMass();
}
void
Particle::addMother( Particle& part )
{
mothers_.insert( part.id() );
DebuggingInsideLoop( Form( "Particle %2d (pdgId=%4d) is the new mother of %2d (pdgId=%4d)",
part.id(), part.pdgId(), id_, pdg_id_ ) );
part.addDaughter( *this );
}
void
Particle::addDaughter( Particle& part )
{
std::pair<ParticlesIds::iterator,bool> ret = daughters_.insert( part.id() );
if ( Logger::get().level >= Logger::DebugInsideLoop ) {
std::ostringstream os;
for ( ParticlesIds::const_iterator it=daughters_.begin(); it!=daughters_.end(); it++) {
os << Form( "\n\t * id=%d", *it );
}
DebuggingInsideLoop( Form( "Particle %2d (pdgId=%4d) has now %2d daughter(s):"
"%s", role_, pdg_id_, numDaughters(), os.str().c_str() ) );
}
if ( ret.second ) {
DebuggingInsideLoop( Form( "Particle %2d (pdgId=%4d) is a new daughter of %2d (pdgId=%4d)",
part.role(), part.pdgId(), role_, pdg_id_ ) );
if ( part.mothers().find( id_ ) == part.mothers().end() ) part.addMother( *this );
}
}
void
Particle::setMomentum( const Momentum& mom, bool offshell )
{
momentum_ = mom;
if ( !offshell && mom.mass() > 0. ) mass_ = momentum_.mass();
else computeMass();
}
void
Particle::setMomentum( double px, double py, double pz )
{
momentum_.setP( px, py, pz );
setEnergy();
}
void
Particle::setMomentum( double px, double py, double pz, double e )
{
setMomentum( px, py, pz );
if ( fabs( e-momentum_.energy() )>1.e-6 ) { // more than 1 eV difference
InError( Form( "Energy difference: %.5e", e-momentum_.energy() ) );
return;
}
}
double
Particle::energy() const
{
return ( momentum_.energy() < 0. ) ? sqrt( mass2()+momentum_.p2() ) : momentum_.energy();
}
void
Particle::setEnergy( double e )
{
if ( e < 0. && mass_ >= 0. ) e = sqrt( mass2()+momentum_.p2() );
momentum_.setEnergy( e );
}
void
Particle::setPdgId( const ParticleCode& pdg, short ch )
{
pdg_id_ = pdg;
charge_sign_ = ch;
}
int
Particle::integerPdgId() const
{
- const float ch = chargeFromPDGId( pdg_id_ );
+ const float ch = ParticleProperties::charge( pdg_id_ );
if ( ch == 0 ) return static_cast<int>( pdg_id_ );
return static_cast<int>( pdg_id_ ) * charge_sign_ * ( ch/fabs( ch ) );
}
void
Particle::dump() const
{
std::ostringstream osm, osd, os;
if ( !primary() ) {
osm << ": mother(s): ";
for ( ParticlesIds::const_iterator m=mothers_.begin(); m!=mothers_.end(); m++ ) {
if ( m!=mothers_.begin() ) osm << ", ";
osm << ( *m );
}
}
const ParticlesIds daugh = daughters();
if ( daugh.size()!=0 ) {
osd << ": id = ";
for ( ParticlesIds::const_iterator it=daugh.begin(); it!=daugh.end(); it++ ) {
if ( it!=daugh.begin() ) osd << ", ";
osd << ( *it );
}
}
os << " (" << pdg_id_ << ")";
if ( os.str() == " ()" ) os.str("");
Information( Form(
"Dumping a particle with id=%3d, role=%3d, status=% 3d\n\t"
"PDG Id:%4d%s, mass = %5.4f GeV\n\t"
"(E,P) = (%4.2f, %4.2f, %4.2f, %4.2f) GeV\t"
"(|P| = p = %4.2f GeV)\n\t"
" Pt = %5.4f GeV, eta = %4.3f, phi = % 4.3f\n\t"
"Primary? %s%s\n\t"
"%d daughter(s)%s",
id_, role_, status_, pdg_id_, os.str().c_str(),
mass(), energy(), momentum_.px(), momentum_.py(), momentum_.pz(),
momentum_.p(), momentum_.pt(), momentum_.eta(), momentum_.phi(),
yesno( primary() ), osm.str().c_str(), numDaughters(), osd.str().c_str() )
);
}
Particle&
Particle::lorentzBoost( double m, const Particle::Momentum& mom )
{
double pf4, fn;
if ( mom.energy() != m ) {
pf4 = 0.;
for ( unsigned int i=0; i<4; i++ ) {
pf4 += momentum_[i]*mom[i];
}
pf4 /= m;
fn = ( pf4+energy() )/( momentum_.energy()+m );
for ( unsigned int i=0; i<3; i++ ) {
momentum_.setP( i, momentum_[i]+fn*mom[i] );
}
}
return *this;
}
std::vector<double>
Particle::lorentzBoost( const Particle::Momentum& mom )
{
double p2, gamma, bp, gamma2;
std::vector<double> out( 3, 0. );
p2 = mom.p2();
gamma = 1./sqrt( 1.-p2 );
bp = 0.;
for ( unsigned int i=0; i<3; i++ ) bp+= mom[i]*momentum_[i];
if ( p2>0. ) gamma2 = (gamma-1.)/p2;
else gamma2 = 0.;
for ( unsigned int i=0; i<3; i++ ) {
out[i] = momentum_[i] + gamma2*bp*mom[i]+gamma*mom[i]*energy();
}
return out;
}
double
- Particle::massFromPDGId( const Particle::ParticleCode& pdg )
- {
- switch ( pdg ) {
- case dQuark: return 0.33; // mass from PYTHIA6.4
- case uQuark: return 0.33; // mass from PYTHIA6.4
- case Electron: return 0.510998928e-3;
- case ElectronNeutrino: return 0.;
- case Muon: return 0.1056583715;
- case MuonNeutrino: return 0.;
- case Tau: return 1.77682;
- case TauNeutrino: return 0.;
- case Gluon: return 0.;
- case Z: return 91.1876;
- case W: return 80.385;
- case Photon: return 0.;
- case PiPlus: return 0.13957018;
- case PiZero: return Constants::mpi;
- case JPsi: return 20.; //FIXME FIXME FIXME
- case ud0Diquark: return 0.57933;
- case ud1Diquark: return 0.77133;
- case uu1Diquark: return 0.77133;
- case Proton: return Constants::mp;
- case Neutron: return 0.939565346;
- case Upsilon1S: return 9.46030;
- case Upsilon2S: return 10.02326;
- case Upsilon3S: return 10.3552;
- case Rho770_0: return 0.77526;
- case Rho1450_0: return 1.465;
- case Rho1700_0: return 1.720;
- case h1380_1: return 1.38619;
- case Eta: return 0.547862;
- case invalidParticle:
- default: return -1.;
- }
- }
-
- double
- Particle::chargeFromPDGId( const Particle::ParticleCode& pdg )
- {
- switch ( pdg ) {
- case Proton: return +1.;
- case dQuark: return -1./3;
- case uQuark: return +2./3;
- case Electron: case Muon: case Tau: return -1.;
- case ElectronNeutrino: case MuonNeutrino: case TauNeutrino: return 0.;
- case Gluon: case Z: case Photon: return 0.;
- case W: return +1.;
- case PiPlus: return +1.;
- case PiZero: return 0.;
- case Neutron: return 0.;
- case Eta: return 0.;
- default: return 0.;
- }
- }
-
- double
- Particle::widthFromPDGId( const Particle::ParticleCode& pdg )
- {
- switch ( pdg ) {
- case JPsi: return 5.; //FIXME
- case Z: return 2.4952;
- case W: return 2.085;
- case Upsilon1S: return 54.02e-6;
- case Upsilon2S: return 31.98e-6;
- case Upsilon3S: return 20.32e-6;
- case Rho770_0: return 0.150; // PDG
- case Rho1450_0: return 0.400; // PDG
- case Rho1700_0: return 0.250; // PDG
- default: return -1.;
- }
- }
-
- double
Particle::etaToY( double eta_, double m_, double pt_ )
{
const double mt = m_*m_ + pt_*pt_;
return asinh( sqrt( ( ( ( mt*mt-m_*m_ )*cosh( 2.*eta_ ) + m_*m_ )/ mt*mt - 1. ) / 2. ) );
}
std::ostream&
- operator<<( std::ostream& os, const Particle::ParticleCode& pc )
- {
- switch ( pc ) {
- case Particle::dQuark: return os << "d quark";
- case Particle::uQuark: return os << "u quark";
- case Particle::Electron: return os << "electron";
- case Particle::ElectronNeutrino: return os << "nu_e";
- case Particle::Muon: return os << "muon";
- case Particle::MuonNeutrino: return os << "nu_mu";
- case Particle::Tau: return os << "tau";
- case Particle::TauNeutrino: return os << "nu_tau";
- case Particle::Gluon: return os << "gluon";
- case Particle::Photon: return os << "photon";
- case Particle::Z: return os << "Z";
- case Particle::W: return os << "W+-";
- case Particle::PiPlus: return os << "pi+";
- case Particle::PiZero: return os << "pi0";
- case Particle::Rho770_0: return os << "rho(770)0";
- case Particle::Rho1450_0: return os << "rho(1450)0";
- case Particle::Rho1700_0: return os << "rho(1700)0";
- case Particle::h1380_1: return os << "h(1380)1";
- case Particle::Eta: return os << "eta meson";
- case Particle::Omega782: return os << "omega(782)";
- case Particle::JPsi: return os << "J/Psi";
- case Particle::Phi1680: return os << "phi(1680)";
- case Particle::Upsilon1S: return os << "Upsilon(1S)";
- case Particle::Upsilon2S: return os << "Upsilon(2S)";
- case Particle::Upsilon3S: return os << "Upsilon(3S)";;
- case Particle::ud0Diquark: return os << "(ud)0 di-quark";
- case Particle::ud1Diquark: return os << "(ud)1 di-quark";
- case Particle::uu1Diquark: return os << "(uu)1 di-quark";
- case Particle::Proton: return os << "proton";
- case Particle::Neutron: return os << "neutron";
- case Particle::Pomeron: return os << "pomeron";
- case Particle::Reggeon: return os << "reggeon";
- case Particle::invalidParticle: return os << "[...]";
- }
- return os;
- }
-
- std::ostream&
operator<<( std::ostream& os, const Particle::Role& rl )
{
switch ( rl ) {
case Particle::UnknownRole: return os << "unknown";
case Particle::IncomingBeam1: return os << "in.b.1";
case Particle::IncomingBeam2: return os << "in.b.2";
case Particle::OutgoingBeam1: return os << "out.b.1";
case Particle::OutgoingBeam2: return os << "out.b.2";
case Particle::Parton1: return os << "parton1";
case Particle::Parton2: return os << "parton2";
case Particle::Parton3: return os << "parton3";
case Particle::Intermediate: return os << "partons";
case Particle::CentralSystem: return os << "central";
}
return os;
}
double
CMEnergy( const Particle& p1, const Particle& p2 )
{
if ( p1.mass()*p2.mass() < 0. ) return 0.;
if ( p1.energy()*p2.energy() < 0. ) return 0.;
return sqrt( p1.mass2()+p2.mass2() + 2.*p1.energy()*p2.energy() - 2.*( p1.momentum()*p2.momentum() ) );
}
double
CMEnergy( const Particle::Momentum& m1, const Particle::Momentum& m2 )
{
if ( m1.mass()*m2.mass() < 0. ) return 0.;
if ( m1.energy()*m2.energy() < 0. ) return 0.;
return sqrt( m1.mass2()+m2.mass2() + 2.*m1.energy()*m2.energy() - 2.*( m1*m2 ) );
}
}
diff --git a/CepGen/Event/Particle.h b/CepGen/Event/Particle.h
index 724948a..40f4cfa 100644
--- a/CepGen/Event/Particle.h
+++ b/CepGen/Event/Particle.h
@@ -1,404 +1,360 @@
#ifndef CepGen_Event_Particle_h
#define CepGen_Event_Particle_h
+#include "CepGen/Physics/ParticleProperties.h"
+
#include <set>
#include <map>
#include <vector>
namespace CepGen
{
/// A set of integer-type particle identifiers
typedef std::set<int> ParticlesIds;
/// Kinematic information for one particle
class Particle {
public:
- /** Unique identifier for a particle type. From \cite Beringer:1900zz :
- * `The Monte Carlo particle numbering scheme [...] is intended to facilitate interfacing between event generators, detector simulators, and analysis packages used in particle physics.`
- * \brief PDG ids of all known particles
- */
- enum ParticleCode {
- invalidParticle = 0,
- //--- fundamental particles
- dQuark = 1, uQuark = 2,
- Electron = 11, ElectronNeutrino = 12,
- Muon = 13, MuonNeutrino = 14,
- Tau = 15, TauNeutrino = 16,
- Gluon = 21, Photon = 22, Z = 23, W = 24,
- //--- composite particles
- PiPlus = 211, PiZero = 111,
- Rho770_0 = 113, Rho1450_0 = 100113, Rho1700_0 = 30113,
- Eta = 221, Omega782 = 223,
- h1380_1 = 10333,
- JPsi= 443,
- Phi1680 = 100333,
- Upsilon1S = 553, Upsilon2S = 100553, Upsilon3S = 200553,
- ud0Diquark = 2101, ud1Diquark = 2103, uu1Diquark = 2203,
- Proton = 2212, Neutron = 2112,
- Pomeron = 990, Reggeon = 110
- };
/// Internal status code for a particle
enum Status {
PrimordialIncoming = -9,
Unfragmented = -4, Undecayed = -3,
Propagator = -2,
Incoming = -1,
Undefined = 0,
FinalState = 1,
Resonance = 2,
DebugResonance = 3,
PythiaHIncoming = 21
};
/// Role of the particle in the process
enum Role {
UnknownRole = -1,
IncomingBeam1 = 1, IncomingBeam2 = 2,
OutgoingBeam1 = 3, OutgoingBeam2 = 5,
CentralSystem = 6,
Intermediate = 4,
Parton1 = 41, Parton2 = 42, Parton3 = 43
};
/**
* Container for a particle's 4-momentum, along with useful methods to ease the development of any matrix element level generator
* \brief 4-momentum for a particle
* \date Dec 2015
* \author Laurent Forthomme <laurent.forthomme@cern.ch>
*/
class Momentum {
public:
/// Build a 4-momentum at rest with an invalid energy (no mass information known)
Momentum();
/// Build a 4-momentum using its 3-momentum coordinates and its energy
Momentum( double x_, double y_, double z_, double t_=-1. );
- inline ~Momentum() {}
// --- static definitions
/// Build a 3-momentum from its three pseudo-cylindric coordinates
static Momentum fromPtEtaPhi( double pt, double eta, double phi, double e=-1. );
/// Build a 4-momentum from its scalar momentum, and its polar and azimuthal angles
static Momentum fromPThetaPhi( double p, double theta, double phi, double e=-1. );
/// Build a 4-momentum from its four momentum and energy coordinates
static Momentum fromPxPyPzE( double px, double py, double pz, double e );
// --- vector and scalar operators
/// Scalar product of the 3-momentum with another 3-momentum
double threeProduct( const Momentum& ) const;
/// Scalar product of the 4-momentum with another 4-momentum
double fourProduct( const Momentum& ) const;
/// Add a 4-momentum through a 4-vector sum
Momentum& operator+=( const Momentum& );
/// Subtract a 4-momentum through a 4-vector sum
Momentum& operator-=( const Momentum& );
/// Scalar product of the 3-momentum with another 3-momentum
double operator*=( const Momentum& );
/// Multiply all 4-momentum coordinates by a scalar
Momentum& operator*=( double c );
/// Equality operator
bool operator==( const Momentum& ) const;
/// Human-readable format for a particle's momentum
friend std::ostream& operator<<( std::ostream& os, const Particle::Momentum& mom );
Momentum& betaGammaBoost( double gamma, double betagamma );
/// Forward Lorentz boost
Momentum& lorentzBoost( const Particle::Momentum& p );
// --- setters and getters
/// Set all the components of the 4-momentum (in GeV)
void setP( double px, double py, double pz, double e );
/// Set all the components of the 3-momentum (in GeV)
void setP( double px, double py, double pz );
/// Set an individual component of the 4-momentum (in GeV)
void setP( unsigned int i, double p );
/// Set the energy (in GeV)
inline void setEnergy( double e ) { energy_ = e; }
/// Compute the energy from the mass
inline void setMass( double m ) { setMass2( m*m ); }
/// Compute the energy from the mass
void setMass2( double m2 );
/// Get one component of the 4-momentum (in GeV)
double operator[]( const unsigned int i ) const;
/// Momentum along the \f$x\f$-axis (in GeV)
inline double px() const { return px_; }
/// Momentum along the \f$y\f$-axis (in GeV)
inline double py() const { return py_; }
/// Longitudinal momentum (in GeV)
inline double pz() const { return pz_; }
/// Transverse momentum (in GeV)
double pt() const;
/// Squared transverse momentum (in GeV\f$^\textrm{2}\f$)
inline double pt2() const { return ( px()*px()+py()*py() ); }
/// 4-vector of double precision floats (in GeV)
const std::vector<double> pVector() const;
/// 3-momentum norm (in GeV)
inline double p() const { return p_; }
/// Squared 3-momentum norm (in GeV\f$^\textrm{2}\f$)
inline double p2() const { return p_*p_; }
/// Energy (in GeV)
inline double energy() const { return energy_; }
/// Squared energy (in GeV^2)
inline double energy2() const { return energy_*energy_; }
/// Squared mass (in GeV^2) as computed from its energy and momentum
inline double mass2() const { return energy2()-p2(); }
/// Mass (in GeV) as computed from its energy and momentum
/// \note Returns \f$-\sqrt{|E^2-\mathbf{p}^2|}<0\f$ if \f$\mathbf{p}^2>E^2\f$
double mass() const;
/// Polar angle (angle with respect to the longitudinal direction)
double theta() const;
/// Azimutal angle (angle in the transverse plane)
double phi() const;
/// Pseudo-rapidity
double eta() const;
/// Rapidity
double rapidity() const;
/// Rotate the transverse components by an angle phi (and reflect the y coordinate)
Momentum& rotatePhi( double phi, double sign );
/// Rotate the particle's momentum by a polar/azimuthal angle
Momentum& rotateThetaPhi( double theta_, double phi_ );
/// Apply a \f$ z\rightarrow -z\f$ transformation
inline Momentum& mirrorZ() { pz_ = -pz_; return *this; }
private:
/// Compute the 3-momentum's norm
void computeP();
/// Momentum along the \f$x\f$-axis
double px_;
/// Momentum along the \f$y\f$-axis
double py_;
/// Momentum along the \f$z\f$-axis
double pz_;
/// 3-momentum's norm (in GeV/c)
double p_;
/// Energy (in GeV)
double energy_;
};
/// Human-readable format for a particle's PDG code
- friend std::ostream& operator<<( std::ostream& os, const Particle::ParticleCode& pc );
+ friend std::ostream& operator<<( std::ostream& os, const ParticleCode& pc );
/// Human-readable format for a particle's role in the event
friend std::ostream& operator<<( std::ostream& os, const Particle::Role& rl );
/// Compute the 4-vector sum of two 4-momenta
friend Particle::Momentum operator+( const Particle::Momentum& mom1, const Particle::Momentum& mom2 );
/// Compute the 4-vector difference of two 4-momenta
friend Particle::Momentum operator-( const Particle::Momentum& mom1, const Particle::Momentum& mom2 );
/// Scalar product of two 3-momenta
friend double operator*( const Particle::Momentum& mom1, const Particle::Momentum& mom2 );
/// Multiply all components of a 4-momentum by a scalar
friend Particle::Momentum operator*( const Particle::Momentum& mom, double c );
/// Multiply all components of a 4-momentum by a scalar
friend Particle::Momentum operator*( double c, const Particle::Momentum& mom );
//----- static getters
- /**
- * \brief Gets the mass of a particle
- * \param pdgId ParticleCode (PDG ID)
- * \return Mass of the particle in \f$\textrm{GeV}/c^2\f$
- */
- static double massFromPDGId( const Particle::ParticleCode& pdgId );
- /**
- * \brief Gets the electric charge of a particle
- * \param pdgId ParticleCode (PDG ID)
- * \return Charge of the particle in \f$e\f$
- */
- static double chargeFromPDGId( const Particle::ParticleCode& pdgId );
- /**
- * \brief Total decay width of one unstable particle
- * \param[in] pdgId ParticleCode (PDG ID)
- * \return Decay width in GeV
- */
- static double widthFromPDGId( const Particle::ParticleCode& pdgId );
-
/// Convert a polar angle to a pseudo-rapidity
static double thetaToEta( double theta );
/// Convert a pseudo-rapidity to a polar angle
static double etaToTheta( double eta );
/// Convert a pseudo-rapidity to a rapidity
static double etaToY( double eta_, double m_, double pt_ );
-
-
Particle();
/// Build using the role of the particle in the process and its PDG id
/// \param[in] pdgId ParticleCode (PDG ID)
/// \param[in] role Role of the particle in the process
/// \param[in] st Current status
Particle( Role role, ParticleCode pdgId=invalidParticle, Status st=Undefined );
/// Copy constructor
Particle( const Particle& );
inline ~Particle() {}
/// Comparison operator (from unique identifier)
bool operator<( const Particle& rhs ) const;
/// Comparison operator (from their reference's unique identifier)
//bool operator<( Particle *rhs ) const { return ( id < rhs->id ); }
Particle& lorentzBoost( double m_, const Momentum& mom_ );
/// Lorentz boost (shamelessly stolen from ROOT)
std::vector<double> lorentzBoost( const Momentum& mom_ );
// --- general particle properties
/// Unique identifier (in a Event object context)
int id() const { return id_; }
//void setId( int id ) { id_ = id; }
/// Set the particle unique identifier in an event
void setId( int id ) { id_ = id; }
/// Electric charge (given as a float number, for the quarks and bound states)
- float charge() const { return charge_sign_ * chargeFromPDGId( pdg_id_ ); }
+ float charge() const { return charge_sign_ * ParticleProperties::charge( pdg_id_ ); }
/// Set the electric charge sign (+-1 for charged or 0 for neutral particles)
void setChargeSign( int sign ) { charge_sign_ = sign; }
/// Role in the considered process
Role role() const { return role_; }
/// Set the particle role in the process
void setRole( const Role& role ) { role_ = role; }
/**
* Codes 1-10 correspond to currently existing partons/particles, and larger codes contain partons/particles which no longer exist, or other kinds of event information
* \brief Particle status
*/
Status status() const { return status_; }
/// Set the particle decay/stability status
void setStatus( Status status ) { status_ = status; }
/// Set the PDG identifier (along with the particle's electric charge)
/// \param[in] pdg ParticleCode (PDG ID)
/// \param[in] ch Electric charge (0, 1, or -1)
void setPdgId( const ParticleCode& pdg, short ch=0 );
/// Retrieve the objectified PDG identifier
inline ParticleCode pdgId() const { return pdg_id_; }
/// Retrieve the integer value of the PDG identifier
int integerPdgId() const;
/// Particle's helicity
float helicity() const { return helicity_; }
/// Set the helicity of the particle
void setHelicity( float heli ) { helicity_ = heli; }
/**
* Gets the particle's mass in \f$\textrm{GeV}/c^{2}\f$.
* \brief Gets the particle's mass
* \return The particle's mass
*/
inline double mass() const { return mass_; };
/**
* Set the mass of the particle in \f$\textrm{GeV}/c^{2}\f$ while ensuring that the kinematics is properly set (the mass is set according to the energy and the momentum in priority)
* \brief Compute the particle's mass in \f$\textrm{GeV}/c^{2}\f$
*/
void computeMass( bool off_shell=false );
/**
* Set the mass of the particle in \f$\textrm{GeV}/c^{2}\f$ according to a value given as an argument. This method ensures that the kinematics is properly set (the mass is set according to the energy and the momentum in priority)
* \param m The mass in \f$\textrm{GeV}/c^{2}\f$ to set
* \brief Set the particle's mass in \f$\textrm{GeV}/c^{2}\f$
*/
void setMass( double m=-1. );
/// Get the particle's squared mass (in \f$\textrm{GeV}^\textrm{2}\f$)
inline double mass2() const { return mass_*mass_; };
/// Retrieve the momentum object associated with this particle
inline Momentum& momentum() { return momentum_; }
/// Retrieve the momentum object associated with this particle
inline Momentum momentum() const { return momentum_; }
/// Associate a momentum object to this particle
void setMomentum( const Momentum& mom, bool offshell=false );
/**
* \brief Set the 3-momentum associated to the particle
* \param[in] px Momentum along the \f$x\f$-axis, in \f$\textrm{GeV}/c\f$
* \param[in] py Momentum along the \f$y\f$-axis, in \f$\textrm{GeV}/c\f$
* \param[in] pz Momentum along the \f$z\f$-axis, in \f$\textrm{GeV}/c\f$
*/
void setMomentum( double px, double py, double pz );
/**
* \brief Set the 4-momentum associated to the particle
* \param[in] px Momentum along the \f$x\f$-axis, in \f$\textrm{GeV}/c\f$
* \param[in] py Momentum along the \f$y\f$-axis, in \f$\textrm{GeV}/c\f$
* \param[in] pz Momentum along the \f$z\f$-axis, in \f$\textrm{GeV}/c\f$
* \param[in] e Energy, in GeV
*/
void setMomentum( double px, double py, double pz, double e );
/**
* \brief Set the 4-momentum associated to the particle
* \param[in] p 4-momentum
*/
inline void setMomentum( double p[4] ) { setMomentum( p[0], p[1], p[2], p[3] ); }
/**
* \brief Set the particle's energy
* \param[in] e Energy, in GeV
*/
void setEnergy( double e=-1. );
/// Get the particle's energy (in GeV)
double energy() const;
/// Get the particle's squared energy (in \f$\textrm{GeV}^\textrm{2}\f$)
inline double energy2() const { return energy()*energy(); };
/// Is this particle a valid particle which can be used for kinematic computations?
bool valid();
// --- particle relations
/// Is this particle a primary particle?
inline bool primary() const { return mothers_.empty(); }
/**
* \brief Set the mother particle
* \param[in] part A Particle object containing all the information on the mother particle
*/
void addMother( Particle& part );
/**
* \brief Gets the unique identifier to the mother particle from which this particle arises
* \return An integer representing the unique identifier to the mother of this particle in the event
*/
inline ParticlesIds mothers() const { return mothers_; }
/**
* \brief Add a decay product
* \param[in] part The Particle object in which this particle will desintegrate or convert
* \return A boolean stating if the particle has been added to the daughters list or if it was already present before
*/
void addDaughter( Particle& part );
/// Gets the number of daughter particles
inline unsigned int numDaughters() const { return daughters_.size(); };
/**
* \brief Get an identifiers list all daughter particles
* \return An integer vector containing all the daughters' unique identifier in the event
*/
inline ParticlesIds daughters() const { return daughters_; }
// --- global particle information extraction
/// Dump all the information on this particle into the standard output stream
void dump() const;
private:
/// Unique identifier in an event
int id_;
/// Electric charge (+-1 or 0)
short charge_sign_;
/// Momentum properties handler
Momentum momentum_;
/// Mass in \f$\textrm{GeV}/c^2\f$
double mass_;
/// Helicity
float helicity_;
/// Role in the process
Role role_;
/// Decay/stability status
Status status_;
/// List of mother particles
ParticlesIds mothers_;
/// List of daughter particles
ParticlesIds daughters_;
/// PDG id
ParticleCode pdg_id_;
};
/// Compute the centre of mass energy of two particles (incoming or outgoing states)
double CMEnergy( const Particle& p1, const Particle& p2 );
/// Compute the centre of mass energy of two particles (incoming or outgoing states)
double CMEnergy( const Particle::Momentum& m1, const Particle::Momentum& m2 );
//bool operator<( const Particle& a, const Particle& b ) { return a.id<b.id; }
// --- particle containers
/// List of Particle objects
typedef std::vector<Particle> Particles;
/// List of particles' roles
typedef std::vector<Particle::Role> ParticleRoles;
/// Map between a particle's role and its associated Particle object
typedef std::map<Particle::Role,Particles> ParticlesMap;
}
#endif
diff --git a/CepGen/Export/CMakeLists.txt b/CepGen/Export/CMakeLists.txt
index 0f1845b..4d02e25 100644
--- a/CepGen/Export/CMakeLists.txt
+++ b/CepGen/Export/CMakeLists.txt
@@ -1,9 +1,8 @@
file(GLOB sources *.cpp)
-file(GLOB headers *.h)
include_directories(${PROJECT_SOURCE_DIR})
add_library(CepGenExporter SHARED ${sources})
install(TARGETS CepGenExporter DESTINATION lib)
diff --git a/CepGen/Export/HepMCHandler.cpp b/CepGen/Export/HepMCHandler.cpp
index fc2689f..c0bad8c 100644
--- a/CepGen/Export/HepMCHandler.cpp
+++ b/CepGen/Export/HepMCHandler.cpp
@@ -1,127 +1,130 @@
#include "HepMCHandler.h"
#include "CepGen/Parameters.h"
#include "CepGen/Core/Exception.h"
#ifdef LIBHEPMC
+#include "HepMC/GenVertex.h"
+#include "HepMC/GenParticle.h"
+
using namespace CepGen::OutputHandler;
HepMCHandler::HepMCHandler( const char* filename, const ExportHandler::OutputType& type ) :
ExportHandler( type ),
event( new HepMC::GenEvent() )
{
#ifdef HEPMC_VERSION3
output = std::unique_ptr<HepMC::WriterAscii>( new HepMC::WriterAscii( filename ) );
#else
output = std::unique_ptr<HepMC::IO_GenEvent>( new HepMC::IO_GenEvent( filename ) );
#endif
}
HepMCHandler::~HepMCHandler()
{}
void
HepMCHandler::operator<<( const Event* evt )
{
fillEvent( evt );
if ( !event.get() ) {
throw Exception( __PRETTY_FUNCTION__, "Failed to retrieve the HepMC event to be stored!", FatalError );
}
#ifdef HEPMC_VERSION3
output->write_event( *event );
#else
output->write_event( event.get() );
#endif
event->clear();
}
void
HepMCHandler::fillEvent( const Event* evt )
{
event->clear();
// general information
#ifdef HEPMC_VERSION3
HepMC::GenCrossSectionPtr xs = HepMC::make_shared<HepMC::GenCrossSection>();
xs->set_cross_section( cross_sect_, cross_sect_err_ );
event->add_attribute( "AlphaQCD", HepMC::make_shared<HepMC::DoubleAttribute>( Constants::alphaQCD ) );
event->add_attribute( "AlphaEM", HepMC::make_shared<HepMC::DoubleAttribute>( Constants::alphaEM ) );
#else
HepMC::GenCrossSection xs;
xs.set_cross_section( cross_sect_, cross_sect_err_ );
event->set_alphaQCD( Constants::alphaQCD );
event->set_alphaQED( Constants::alphaEM );
#endif
event->set_cross_section( xs );
event->set_event_number( event_num_ );
event->weights().push_back( 1. ); //FIXME we generate unweighted events
// filling the particles content
const HepMC::FourVector origin( 0., 0., 0., 0. );
Particles part_vec = evt->particles();
int cm_id = 0, idx = 1;
#ifdef HEPMC_VERSION3
HepMC::GenVertexPtr v1 = HepMC::make_shared<HepMC::GenVertex>( origin ),
v2 = HepMC::make_shared<HepMC::GenVertex>( origin ),
vcm = HepMC::make_shared<HepMC::GenVertex>( origin );
#else
HepMC::GenVertex* v1 = new HepMC::GenVertex( origin ),
*v2 = new HepMC::GenVertex( origin ),
*vcm = new HepMC::GenVertex( origin );
#endif
- for ( unsigned int i=0; i<part_vec.size(); i++ ) {
+ for ( unsigned int i = 0; i < part_vec.size(); ++i ) {
const Particle part_orig = part_vec.at( i );
HepMC::FourVector pmom( part_orig.momentum().px(),
part_orig.momentum().py(),
part_orig.momentum().pz(),
part_orig.energy() );
#ifdef HEPMC_VERSION3
HepMC::GenParticlePtr part = HepMC::make_shared<HepMC::GenParticle>( pmom, part_orig.integerPdgId(), part_orig.status() );
#else
HepMC::GenParticle* part = new HepMC::GenParticle( pmom, part_orig.integerPdgId(), part_orig.status() );
part->suggest_barcode( idx++ );
#endif
const ParticlesIds moth = part_orig.mothers();
switch ( part_orig.role() ) {
case Particle::IncomingBeam1: { v1->add_particle_in( part ); } break;
case Particle::IncomingBeam2: { v2->add_particle_in( part ); } break;
case Particle::OutgoingBeam1: { v1->add_particle_out( part ); } break;
case Particle::OutgoingBeam2: { v2->add_particle_out( part ); } break;
case Particle::Parton1: { v1->add_particle_out( part ); vcm->add_particle_in( part ); } break;
case Particle::Parton2: { v2->add_particle_out( part ); vcm->add_particle_in( part ); } break;
case Particle::Parton3: { v2->add_particle_out( part ); vcm->add_particle_in( part ); } break;
case Particle::Intermediate: { cm_id = i; continue; } break;
case Particle::CentralSystem:
default: {
if ( moth.size() == 0 ) { continue; }
if ( *moth.begin() == cm_id ) { vcm->add_particle_out( part ); }
else {
std::cout << "other particle!!" << std::endl;
continue;
//FIXME secondary products... to be implemented!
}
} break;
}
idx++;
}
event->add_vertex( v1 );
event->add_vertex( v2 );
event->add_vertex( vcm );
#ifndef HEPMC_VERSION3
event->set_beam_particles( *v1->particles_in_const_begin(), *v2->particles_in_const_begin() );
event->set_signal_process_vertex( *v1->vertices_begin() );
event->set_beam_particles( *v1->particles_in_const_begin(), *v2->particles_in_const_end() );
#endif
event_num_++;
}
#endif
diff --git a/CepGen/Export/HepMCHandler.h b/CepGen/Export/HepMCHandler.h
index 2b5e52c..8c1eb95 100644
--- a/CepGen/Export/HepMCHandler.h
+++ b/CepGen/Export/HepMCHandler.h
@@ -1,68 +1,68 @@
#ifndef CepGen_Export_HepMCHandler_h
#define CepGen_Export_HepMCHandler_h
#include "ExportHandler.h"
#ifdef LIBHEPMC
#include "HepMC/Version.h"
#ifndef HEPMC_VERSION_CODE // HepMC v2
#include "HepMC/IO_GenEvent.h"
#include "HepMC/SimpleVector.h"
#else // HepMC v3+
#define HEPMC_VERSION3
#include "HepMC/WriterAscii.h"
#include "HepMC/FourVector.h"
#endif
#include "HepMC/GenEvent.h"
#include <memory>
namespace CepGen
{
namespace OutputHandler
{
/**
* \brief Handler for the HepMC file output
* \author Laurent Forthomme <laurent.forthomme@cern.ch>
* \date Sep 2016
*/
class HepMCHandler : public ExportHandler
{
public:
/// Class constructor
/// \param[in] filename Output file path
/// \param[in] type Output type
- HepMCHandler( const char* filename, const ExportHandler::OutputType& type=ExportHandler::HepMC );
+ HepMCHandler( const char* filename, const ExportHandler::OutputType& type = ExportHandler::HepMC );
~HepMCHandler();
void initialise( const Parameters& params ) {}
/// Writer operator
void operator<<( const Event* );
protected:
/// Clear the associated HepMC event content
void clearEvent();
/// Populate the associated HepMC event with a Event object
void fillEvent( const Event* );
/// Associated HepMC event
std::shared_ptr<HepMC::GenEvent> event;
private:
#ifdef HEPMC_VERSION3
/// Writer object (from HepMC v3+)
std::unique_ptr<HepMC::WriterAscii> output;
#else
/// Writer object (from HepMC v<3)
std::unique_ptr<HepMC::IO_GenEvent> output;
#endif
};
}
}
#endif
#endif
diff --git a/CepGen/Export/LHEFHandler.cpp b/CepGen/Export/LHEFHandler.cpp
index 64e8d85..7ee7ccf 100644
--- a/CepGen/Export/LHEFHandler.cpp
+++ b/CepGen/Export/LHEFHandler.cpp
@@ -1,69 +1,82 @@
#ifdef LIBHEPMC
-#include "ExportHandler.h"
+#include "HepMCHandler.h"
#ifdef HEPMC_VERSION3
-
#include "LHEFHandler.h"
#include "CepGen/Parameters.h"
+#include "CepGen/Version.h"
-namespace OutputHandler
+namespace CepGen
{
- LHEFHandler::LHEFHandler( const char* filename ) :
- ExportHandler( ExportHandler::LHE ),
- lhe_output_( std::make_unique<LHEF::Writer>( filename ) )
+ namespace OutputHandler
{
- //lhe_output_->headerBlock() << "";
- lhe_output_->initComments() << "Sample created using CepGen.\n";
- }
+ LHEFHandler::LHEFHandler( const char* filename ) :
+ ExportHandler( ExportHandler::LHE ),
+ lhe_output_( new LHEF::Writer( filename ) )
+ {}
- void
- LHEFHandler::initialise( const Parameters& params )
- {
- lhe_output_->initComments() << " Input parameters:\n";
- params.dump( lhe_output_->initComments(), false );
- LHEF::HEPRUP run = lhe_output_->heprup;
- run.IDBMUP = std::pair<int,int>( params.in1pdg, params.in2pdg );
- run.EBMUP = std::pair<double,double>( params.in1p, params.in2p );
- run.NPRUP = 1;
- run.resize();
- run.XSECUP[0] = cross_sect_;
- run.XERRUP[0] = cross_sect_err_;
- run.XMAXUP[0] = 1.;
- run.LPRUP[0] = 1;
- lhe_output_->heprup = run;
- lhe_output_->init();
- }
+ void
+ LHEFHandler::initialise( const Parameters& params )
+ {
+ lhe_output_->headerBlock()
+ << "<!--\n"
+ << "***** Sample generated with CepGen v" << version() << " *****\n"
+ << "* process: " << params.processName() << " (" << params.kinematics.mode << ")\n"
+ << "* structure functions: " << params.kinematics.structure_functions << "\n"
+ << "*--- incoming state\n"
+ << "* Q² range (GeV²): " << params.kinematics.cuts.initial.at( Cuts::q2 ) << "\n"
+ << "* remnants mass range (GeV): " << params.kinematics.cuts.remnants.at( Cuts::mass ) << "\n"
+ << "*--- central system\n"
+ << "* single particle pT (GeV): " << params.kinematics.cuts.central.at( Cuts::pt_single ) << "\n"
+ << "* single particle energy (GeV): " << params.kinematics.cuts.central.at( Cuts::energy_single ) << "\n"
+ << "* single particle eta: " << params.kinematics.cuts.central.at( Cuts::eta_single ) << "\n"
+ << "**************************************************\n"
+ << "-->";
+ //params.dump( lhe_output_->initComments(), false );
+ LHEF::HEPRUP run = lhe_output_->heprup;
+ run.IDBMUP = params.kinematics.inpdg;
+ run.EBMUP = params.kinematics.inp;
+ run.NPRUP = 1;
+ run.resize();
+ run.XSECUP[0] = cross_sect_;
+ run.XERRUP[0] = cross_sect_err_;
+ run.XMAXUP[0] = 1.;
+ run.LPRUP[0] = 1;
+ lhe_output_->heprup = run;
+ lhe_output_->init();
+ }
- void
- LHEFHandler::operator<<( const Event* ev )
- {
- LHEF::HEPEUP out;
- out.heprup = &lhe_output_->heprup;
- out.XWGTUP = 1.;
- out.XPDWUP = std::pair<double,double>( 0., 0. );
- out.SCALUP = 0.;
- out.AQEDUP = Constants::alphaEM;
- out.AQCDUP = Constants::alphaQCD;
- out.NUP = ev->numParticles();
- out.resize();
- for ( unsigned short ip=0; ip<ev->numParticles(); ip++ ) {
- const Particle part = ev->getConstById( ip );
- out.IDUP[ip] = part.integerPdgId(); // PDG id
- out.ISTUP[ip] = part.status; // status code
- out.MOTHUP[ip] = std::pair<int,int>( *part.mothersIds().begin(), ( part.mothersIds().size()>0 ) ? *( part.mothersIds().end()-- ) : 0 ); // mothers
- out.ICOLUP[ip] = std::pair<int,int>( 0, 0 );
- out.PUP[ip] = std::vector<double>( { part.momentum().px(), part.momentum().py(), part.momentum().pz(), part.energy(), part.mass() } ); // momentum
- out.VTIMUP[ip] = 0.; // invariant lifetime
- out.SPINUP[ip] = 0.;
+ void
+ LHEFHandler::operator<<( const Event* ev )
+ {
+ LHEF::HEPEUP out;
+ out.heprup = &lhe_output_->heprup;
+ out.XWGTUP = 1.;
+ out.XPDWUP = std::pair<double,double>( 0., 0. );
+ out.SCALUP = 0.;
+ out.AQEDUP = Constants::alphaEM;
+ out.AQCDUP = Constants::alphaQCD;
+ out.NUP = ev->numParticles();
+ out.resize();
+ for ( unsigned short ip=0; ip<ev->numParticles(); ip++ ) {
+ const Particle part = ev->getConstById( ip );
+ out.IDUP[ip] = part.integerPdgId(); // PDG id
+ out.ISTUP[ip] = part.status(); // status code
+ out.MOTHUP[ip] = std::pair<int,int>( ( part.mothers().size() > 0 ) ? *part.mothers().begin()+1 : 0, ( part.mothers().size() > 1 ) ? *part.mothers().rbegin()+1 : 0 ); // mothers
+ out.ICOLUP[ip] = std::pair<int,int>( 0, 0 );
+ out.PUP[ip] = std::vector<double>( { { part.momentum().px(), part.momentum().py(), part.momentum().pz(), part.energy(), part.mass() } } ); // momentum
+ out.VTIMUP[ip] = 0.; // invariant lifetime
+ out.SPINUP[ip] = 0.;
+ }
+ lhe_output_->eventComments() << "haha";
+ lhe_output_->hepeup = out;
+ lhe_output_->writeEvent();
}
- lhe_output_->eventComments() << "haha";
- lhe_output_->hepeup = out;
- lhe_output_->writeEvent();
}
}
#endif
#endif
diff --git a/CepGen/Export/LHEFHandler.h b/CepGen/Export/LHEFHandler.h
index fb161fb..b8c94bb 100644
--- a/CepGen/Export/LHEFHandler.h
+++ b/CepGen/Export/LHEFHandler.h
@@ -1,42 +1,46 @@
#ifndef CepGen_Export_LHEFHandler_h
#define CepGen_Export_LHEFHandler_h
#ifndef LIBHEPMC
#error "HepMC is not linked to this instance!"
#endif
#include "HepMCHandler.h"
#ifndef HEPMC_VERSION3
#error "HepMC v3 is required for the LHEF export!"
#else
+#include "ExportHandler.h"
#include "HepMC/LHEF.h"
#include "CepGen/Event/Event.h"
-namespace OutputHandler
+namespace CepGen
{
- /**
- * \brief Handler for the LHE file output
- * \author Laurent Forthomme <laurent.forthomme@cern.ch>
- * \date Sep 2016
- */
- class LHEFHandler : public ExportHandler
+ namespace OutputHandler
{
- public:
- /// Class constructor
- /// \param[in] filename Output file path
- LHEFHandler( const char* filename );
- void initialise( const Parameters& params );
- /// Writer operator
- void operator<<( const Event* );
-
- private:
- /// Writer object (from HepMC)
- std::unique_ptr<LHEF::Writer> lhe_output_;
- LHEF::HEPRUP run_;
- };
+ /**
+ * \brief Handler for the LHE file output
+ * \author Laurent Forthomme <laurent.forthomme@cern.ch>
+ * \date Sep 2016
+ */
+ class LHEFHandler : public ExportHandler
+ {
+ public:
+ /// Class constructor
+ /// \param[in] filename Output file path
+ LHEFHandler( const char* filename );
+ void initialise( const Parameters& params );
+ /// Writer operator
+ void operator<<( const Event* );
+
+ private:
+ /// Writer object (from HepMC)
+ std::unique_ptr<LHEF::Writer> lhe_output_;
+ LHEF::HEPRUP run_;
+ };
+ }
}
#endif
#endif
diff --git a/CepGen/Hadronisers/Pythia8Hadroniser.cpp b/CepGen/Hadronisers/Pythia8Hadroniser.cpp
index ff17f6f..6328510 100644
--- a/CepGen/Hadronisers/Pythia8Hadroniser.cpp
+++ b/CepGen/Hadronisers/Pythia8Hadroniser.cpp
@@ -1,124 +1,124 @@
#ifdef PYTHIA8
#include "Pythia8Hadroniser.h"
#include "CepGen/Core/Exception.h"
#include "CepGen/Core/utils.h"
#include "CepGen/Event/Event.h"
#include "CepGen/Event/Particle.h"
namespace CepGen
{
namespace Hadroniser
{
Pythia8Hadroniser::Pythia8Hadroniser() :
#ifdef PYTHIA8
GenericHadroniser( "pythia8" ), pythia_( std::unique_ptr<Pythia8::Pythia>( new Pythia8::Pythia ) )
{
//--- start by disabling some unnecessary output
pythia_->readString( "Next:numberCount = 0" );
}
#else
GenericHadroniser( "pythia8" )
{}
#endif
Pythia8Hadroniser::~Pythia8Hadroniser()
{}
void
Pythia8Hadroniser::setSeed( long long seed )
{
#ifdef PYTHIA8
if ( seed == -1ll ) {
pythia_->readString( "Random:setSeed = off" );
return;
}
pythia_->readString( "Random:setSeed = on" );
pythia_->readString( Form( "Random:seed = %llu", seed ) );
#endif
}
bool
Pythia8Hadroniser::hadronise( const Particle& part, Event& ev )
{
#ifdef PYTHIA8
// check if the particle can be decayed
if ( part.status() != Particle::Undecayed ) return false;
if ( !pythia_->particleData.canDecay( part.pdgId() ) ) return false;
// check if the particle has a valid kinematics
const Particle::Momentum mom = part.momentum();
if ( mom == Particle::Momentum() ) return false; // FIXME probably during warm-up...
pythia_->event.reset();
Pythia8::Particle py8part( part.integerPdgId(), 93, 0, 0, 0, 0, 0, 0, mom.px(), mom.py(), mom.pz(), mom.energy(), part.mass() );
py8part.tau( pythia_->particleData.tau0( part.pdgId() ) );
pythia_->event.append( py8part );
const unsigned short num_before = pythia_->event.size(); // number of particles before the decay
if ( !pythia_->next() ) return false; // launch the decay
// std::cout << pythia_->info.sigmaGen() << std::endl;
// map { "pythia id" -> "cepgen id" }
std::map<unsigned short, unsigned short> py_cg_corresp = { { 1, part.id() } };
const unsigned short num_after = pythia_->event.size(); // number of particles after the decay
if ( num_before == num_after ) return false; // nothing happened... so no decay!
for ( unsigned short i = 2; i < pythia_->event.size(); ++i ) { // skip the initial system
const Pythia8::Particle p = pythia_->event[i];
const std::vector<int> mothers = p.motherList();
if ( mothers.size() == 0 ) continue;
Particle& op = ev.addParticle( Particle::CentralSystem );
py_cg_corresp[i] = op.id();
- op.setPdgId( ( Particle::ParticleCode )abs( p.id() ), p.charge() );
+ op.setPdgId( ( ParticleCode )abs( p.id() ), p.charge() );
if ( p.isFinal() ) op.setStatus( Particle::FinalState );
else op.setStatus( Particle::Propagator );
op.setMomentum( Particle::Momentum( p.px(), p.py(), p.pz(), p.e() ) );
for ( std::vector<int>::const_iterator moth = mothers.begin(); moth != mothers.end(); ++moth ) {
if ( py_cg_corresp.count( *moth ) == 0 ) { FatalError( Form( "Particle with id=%d was not found in the event content!", *moth ) ); }
op.addMother( ev.getById( py_cg_corresp[*moth] ) );
}
}
#else
FatalError( "Pythia8 is not linked to this instance!" );
#endif
return true;
}
bool
Pythia8Hadroniser::hadronise( Event& ev )
{
#ifdef PYTHIA8
//--- first start by cleaning up the previous runs leftovers
pythia_->event.reset();
//--- outgoing proton remnants fragmentation
Particles& op1 = ev.getByRole( Particle::OutgoingBeam1 ), &op2 = ev.getByRole( Particle::OutgoingBeam2 );
for ( Particles::const_iterator p_it = op1.begin(); p_it != op1.end(); ++p_it ) {
// excited proton fragmentation
}
for ( Particles::const_iterator p_it = op2.begin(); p_it != op2.end(); ++p_it ) {
// excited proton fragmentation
}
//--- central system hadronisation/decay/...
const ParticlesIds cs = ev.getIdsByRole( Particle::CentralSystem );
for ( ParticlesIds::iterator p_it = cs.begin(); p_it != cs.end(); ++p_it ) {
const Particle& part = ev.getById( *p_it );
if ( !hadronise( part, ev ) ) continue;
ev.getById( *p_it ).setStatus( Particle::Resonance );
}
#else
FatalError( "Pythia8 is not linked to this instance!" );
#endif
return true;
}
}
}
#endif
diff --git a/CepGen/IO/CMakeLists.txt b/CepGen/IO/CMakeLists.txt
new file mode 100644
index 0000000..4d90ba1
--- /dev/null
+++ b/CepGen/IO/CMakeLists.txt
@@ -0,0 +1,8 @@
+file(GLOB io_sources FortranInterface.cpp)
+
+include_directories(${PROJECT_SOURCE_DIR})
+
+add_library(CepGenIO SHARED ${io_sources})
+
+install(TARGETS CepGenIO DESTINATION lib)
+
diff --git a/CepGen/IO/MSTWGridHandler.cpp b/CepGen/IO/MSTWGridHandler.cpp
new file mode 100644
index 0000000..e7aaf5b
--- /dev/null
+++ b/CepGen/IO/MSTWGridHandler.cpp
@@ -0,0 +1,171 @@
+#include "MSTWGridHandler.h"
+#include "CepGen/Core/Exception.h"
+#include "CepGen/Core/utils.h"
+#include "CepGen/StructureFunctions/StructureFunctions.h"
+
+#include <fstream>
+
+#include <gsl/gsl_errno.h>
+#include <gsl/gsl_math.h>
+
+namespace MSTW
+{
+ GridHandler&
+ GridHandler::get( const char* filename )
+ {
+ static GridHandler instance( filename );
+ return instance;
+ }
+
+ GridHandler::GridHandler( const char* filename )
+#ifdef GOOD_GSL
+ : xacc_( 0 ), yacc_( 0 ), values_( { { 0, 0 } } )
+#endif
+ {
+ std::set<double> q2_vals, xbj_vals;
+
+ { // file readout part
+ std::ifstream file( filename, std::ios::binary | std::ios::in );
+ if ( !file.is_open() )
+ FatalError( Form( "Impossible to load grid file \"%s\"!", filename ) );
+
+ file.read( reinterpret_cast<char*>( &header_ ), sizeof( header_t ) );
+
+ // first checks on the file header
+
+ if ( header_.magic != good_magic )
+ FatalError( Form( "Wrong magic number retrieved: %u, expecting %u!", header_.magic, good_magic ) );
+
+ if ( header_.nucleon != header_t::proton )
+ FatalError( "Only proton structure function grids can be retrieved for this purpose!" );
+
+ // retrieve all points and evaluate grid boundaries
+
+ sfval_t val;
+ while ( file.read( reinterpret_cast<char*>( &val ), sizeof( sfval_t ) ) ) {
+ q2_vals.insert( log10( val.q2 ) );
+ xbj_vals.insert( log10( val.xbj ) );
+ /*val.f2 = std::max( val.f2, 0. );
+ val.fl = std::max( val.fl, 0. );*/
+ values_raw_.emplace_back( val );
+ }
+ file.close();
+ }
+
+ if ( q2_vals.size() < 2 || xbj_vals.size() < 2 )
+ FatalError( "Invalid grid retrieved!" );
+
+ initGSL( q2_vals, xbj_vals );
+
+ {
+ std::ostringstream ss_cl, ss_ord, ss_nucl;
+ ss_cl << header_.cl;
+ ss_ord << header_.order;
+ ss_nucl << header_.nucleon;
+ Information( Form( "MSTW@%s grid evaluator built for %s structure functions (%s)\n\t"
+ " Q² in range [%.3e:%.3e]\n\t"
+ "xBj in range [%.3e:%.3e]",
+ ss_ord.str().c_str(), ss_nucl.str().c_str(), ss_cl.str().c_str(),
+ pow( 10., *q2_vals.begin() ), pow( 10., *q2_vals.rbegin() ),
+ pow( 10., *xbj_vals.begin() ), pow( 10., *xbj_vals.rbegin() ) ) );
+ }
+ }
+
+ GridHandler::~GridHandler()
+ {
+#ifdef GOOD_GSL
+ for ( unsigned short i = 0; i < num_functions_; ++i ) {
+ gsl_spline2d_free( splines_[i] );
+ if ( values_[i] ) delete[] values_[i];
+ }
+ if ( xacc_ ) gsl_interp_accel_free( xacc_ );
+ if ( yacc_ ) gsl_interp_accel_free( yacc_ );
+#endif
+ }
+
+ void
+ GridHandler::initGSL( const std::set<double>& q2_vals, const std::set<double>& xbj_vals )
+ {
+#ifdef GOOD_GSL
+ gsl_set_error_handler_off();
+ const gsl_interp2d_type* T = gsl_interp2d_bilinear;
+
+ for ( unsigned short i = 0; i < num_functions_; ++i ) {
+ values_[i] = new double[q2_vals.size() * xbj_vals.size()];
+ splines_[i] = gsl_spline2d_alloc( T, q2_vals.size(), xbj_vals.size() );
+ }
+ xacc_ = gsl_interp_accel_alloc();
+ yacc_ = gsl_interp_accel_alloc();
+
+ // second loop over all points to populate the grid
+ for ( const auto& val : values_raw_ ) {
+ // retrieve the index of the Q2/xbj bin in the set
+ const unsigned short id_q2 = std::distance( q2_vals.begin(), q2_vals.lower_bound( log10( val.q2 ) ) ),
+ id_xbj = std::distance( xbj_vals.begin(), xbj_vals.lower_bound( log10( val.xbj ) ) );
+ gsl_spline2d_set( splines_[F2], values_[F2], id_q2, id_xbj, val.f2 );
+ gsl_spline2d_set( splines_[FL], values_[FL], id_q2, id_xbj, val.fl );
+ }
+
+ // initialise splines objects
+ std::vector<double> q2_vec( q2_vals.begin(), q2_vals.end() ), xbj_vec( xbj_vals.begin(), xbj_vals.end() );
+ for ( unsigned short i = 0; i < num_functions_; ++i ) {
+ gsl_spline2d_init( splines_[i], &q2_vec[0], &xbj_vec[0], values_[i], q2_vals.size(), xbj_vals.size() );
+ }
+#else
+ FatalError( Form( "GSL version ≥ 2.1 is required for bilinear interpolation.\n\tVersion %s is installed on this system!", GSL_VERSION ) );
+#endif
+ }
+
+ CepGen::StructureFunctions
+ GridHandler::eval( double q2, double xbj ) const
+ {
+ CepGen::StructureFunctions ev;
+#ifdef GOOD_GSL
+ if ( gsl_spline2d_eval_e( splines_[F2], log10( q2 ), log10( xbj ), xacc_, yacc_, &ev.F2 ) != GSL_SUCCESS
+ || gsl_spline2d_eval_e( splines_[FL], log10( q2 ), log10( xbj ), xacc_, yacc_, &ev.FL ) != GSL_SUCCESS ) {
+ InWarning( Form( "Failed to evaluate the structure functions for Q² = %.5e GeV² / xbj = %.5e", q2, xbj ) );
+ return ev;
+ }
+#else
+ FatalError( Form( "GSL version ≥ 2.1 is required for bilinear interpolation.\n\tVersion %s is installed on this system!", GSL_VERSION ) );
+#endif
+ return ev;
+ }
+
+ std::ostream&
+ operator<<( std::ostream& os, const GridHandler::sfval_t& val )
+ {
+ return os << Form( "Q² = %.5e GeV²\txbj = %.4f\tF₂ = % .6e\tFL = % .6e", val.q2, val.xbj, val.f2, val.fl );
+ }
+
+ std::ostream&
+ operator<<( std::ostream& os, const GridHandler::header_t::order_t& order )
+ {
+ switch ( order ) {
+ case GridHandler::header_t::lo: return os << "LO";
+ case GridHandler::header_t::nlo: return os << "nLO";
+ case GridHandler::header_t::nnlo: return os << "nnLO";
+ }
+ return os;
+ }
+
+ std::ostream&
+ operator<<( std::ostream& os, const GridHandler::header_t::cl_t& cl )
+ {
+ switch ( cl ) {
+ case GridHandler::header_t::cl68: return os << "68% C.L.";
+ case GridHandler::header_t::cl95: return os << "95% C.L.";
+ }
+ return os;
+ }
+
+ std::ostream&
+ operator<<( std::ostream& os, const GridHandler::header_t::nucleon_t& nucl )
+ {
+ switch ( nucl ) {
+ case GridHandler::header_t::proton: return os << "proton";
+ case GridHandler::header_t::neutron: return os << "neutron";
+ }
+ return os;
+ }
+}
diff --git a/CepGen/IO/MSTWGridHandler.h b/CepGen/IO/MSTWGridHandler.h
new file mode 100644
index 0000000..db20967
--- /dev/null
+++ b/CepGen/IO/MSTWGridHandler.h
@@ -0,0 +1,74 @@
+#ifndef CepGen_IO_MSTWGridHandler_h
+#define CepGen_IO_MSTWGridHandler_h
+
+#include <gsl/gsl_version.h>
+
+#if GSL_MAJOR_VERSION > 2 || ( GSL_MAJOR_VERSION == 2 && GSL_MINOR_VERSION >= 1 )
+#define GOOD_GSL 1
+#endif
+
+#ifdef GOOD_GSL
+#include <gsl/gsl_interp2d.h>
+#include <gsl/gsl_spline2d.h>
+#endif
+
+#include <array>
+#include <vector>
+#include <set>
+
+namespace CepGen { class StructureFunctions; }
+namespace MSTW
+{
+ class GridHandler
+ {
+ public:
+ struct sfval_t {
+ float q2, xbj;
+ double f2, fl;
+ };
+ struct header_t {
+ enum order_t : unsigned short { lo = 0, nlo = 1, nnlo = 2 };
+ enum cl_t : unsigned short { cl68 = 0, cl95 = 1 };
+ enum nucleon_t : unsigned short { proton = 1, neutron = 2 };
+ unsigned int magic;
+ order_t order;
+ cl_t cl;
+ nucleon_t nucleon;
+ };
+
+ public:
+ static GridHandler& get( const char* filename = "External/F2_Luxlike_fit/mstw_f2_scan_nnlo.dat" );
+ ~GridHandler();
+
+ CepGen::StructureFunctions eval( double q2, double xbj ) const;
+
+ header_t header() const { return header_; }
+ std::vector<sfval_t> values() const { return values_raw_; }
+
+ private:
+ GridHandler( const char* );
+ void initGSL( const std::set<double>& q2_vals, const std::set<double>& xbj_vals );
+
+ enum spline_type { F2 = 0, FL = 1, num_functions_ };
+ static constexpr unsigned int good_magic = 0x5754534d; // MSTW in ASCII
+
+ header_t header_;
+ std::vector<sfval_t> values_raw_;
+#ifdef GOOD_GSL
+ std::array<gsl_spline2d*,2> splines_;
+ gsl_interp_accel* xacc_, *yacc_;
+ std::array<double*,2> values_;
+#endif
+
+ public:
+ GridHandler( const GridHandler& ) = delete;
+ void operator=( const GridHandler& ) = delete;
+ };
+ std::ostream& operator<<( std::ostream&, const GridHandler::sfval_t& );
+ std::ostream& operator<<( std::ostream&, const GridHandler::header_t::order_t& );
+ std::ostream& operator<<( std::ostream&, const GridHandler::header_t::cl_t& );
+ std::ostream& operator<<( std::ostream&, const GridHandler::header_t::nucleon_t& );
+}
+
+#endif
+
diff --git a/CepGen/Parameters.h b/CepGen/Parameters.h
index 2afa1ee..d619fb9 100644
--- a/CepGen/Parameters.h
+++ b/CepGen/Parameters.h
@@ -1,115 +1,119 @@
#ifndef CepGen_Parameters_h
#define CepGen_Parameters_h
#include "CepGen/Core/TamingFunction.h"
#include "CepGen/Core/Integrator.h"
#include "CepGen/Physics/Kinematics.h"
#include "CepGen/Processes/GenericProcess.h"
#include "CepGen/Hadronisers/GenericHadroniser.h"
#include <memory>
namespace CepGen
{
class Event;
/// List of parameters used to start and run the simulation job
class Parameters
{
public:
Parameters();
/// Copy constructor (transfers ownership to the process/hadroniser!)
Parameters( Parameters& );
/// Const copy constructor (all but the process and the hadroniser)
Parameters( const Parameters& );
~Parameters();
/// Set the polar angle range for the produced leptons
/// \param[in] thetamin The minimal value of \f$\theta\f$ for the outgoing leptons
/// \param[in] thetamax The maximal value of \f$\theta\f$ for the outgoing leptons
void setThetaRange( float thetamin, float thetamax );
/// Dump the input parameters in the console
- void dump( std::ostream& os=Logger::get().outputStream, bool pretty=true ) const;
+ void dump( std::ostream& os = Logger::get().outputStream, bool pretty = true ) const;
//----- process to compute
/// Process for which the cross-section will be computed and the events will be generated
Process::GenericProcess* process() { return process_.get(); }
/// Name of the process considered
std::string processName() const;
/// Set the process to study
void setProcess( Process::GenericProcess* proc ) { process_.reset( proc ); }
//----- events kinematics
/// Events kinematics for phase space definition
Kinematics kinematics;
//----- VEGAS
/// Collection of integrator parameters
struct IntegratorParameters
{
- IntegratorParameters() : type( Integrator::Vegas ), ncvg( 100000 ), itvg( 10 ), npoints( 100 ), first_run( true ), seed( 0 ) {}
+ IntegratorParameters() :
+ type( Integrator::Vegas ), ncvg( 100000 ), itvg( 10 ),
+ npoints( 100 ), first_run( true ), seed( 0 ) {}
Integrator::Type type;
/// Number of function calls to be computed for each point
unsigned int ncvg; // ??
/// Number of iterations for the integration
unsigned int itvg;
/// Number of points to "shoot" in each integration bin by the algorithm
unsigned int npoints;
/// Is it the first time the integrator is run?
bool first_run;
/// Random number generator seed
unsigned long seed;
};
/// Integrator parameters
IntegratorParameters integrator;
//----- events generation
/// Collection of events generation parameters
struct Generation
{
- Generation() : enabled( false ), maxgen( 0 ), symmetrise( false ), ngen( 0 ), gen_print_every( 1 ) {}
+ Generation() :
+ enabled( false ), maxgen( 0 ),
+ symmetrise( false ), ngen( 0 ), gen_print_every( 1 ) {}
/// Are we generating events ? (true) or are we only computing the cross-section ? (false)
bool enabled;
/// Maximal number of events to generate in this run
unsigned int maxgen;
/// Pointer to the last event produced in this run
std::shared_ptr<Event> last_event;
/// Do we want the events to be symmetrised with respect to the \f$z\f$-axis ?
bool symmetrise;
/// Number of events already generated in this run
unsigned int ngen;
/// Frequency at which the events are displayed to the end-user
unsigned int gen_print_every;
};
/// Events generation parameters
Generation generation;
/// Specify if the generated events are to be stored
void setStorage( bool store ) { store_ = store; }
/// Are the events generated in this run to be stored in the output file ?
bool storage() const { return store_; }
//----- hadronisation algorithm
/// Hadronisation algorithm to use for the proton(s) fragmentation
Hadroniser::GenericHadroniser* hadroniser() { return hadroniser_.get(); }
/// Set the hadronisation algorithm
void setHadroniser( Hadroniser::GenericHadroniser* hadr ) { hadroniser_.reset( hadr ); }
/// Maximal number of trials for the hadronisation of the proton(s) remnants
unsigned int hadroniser_max_trials;
//----- taming functions
/// Functionals to be used to account for rescattering corrections (implemented within the process)
TamingFunctionsCollection taming_functions;
private:
std::unique_ptr<Process::GenericProcess> process_;
std::unique_ptr<Hadroniser::GenericHadroniser> hadroniser_;
bool store_;
};
}
#endif
diff --git a/CepGen/Physics/Constants.h b/CepGen/Physics/Constants.h
index 53d77b8..1c31a30 100644
--- a/CepGen/Physics/Constants.h
+++ b/CepGen/Physics/Constants.h
@@ -1,24 +1,23 @@
#ifndef CepGen_Physics_Constants_h
#define CepGen_Physics_Constants_h
#include <math.h>
namespace CepGen
{
/// List of physical constants useful that may be used for the matrix element definition
namespace Constants
{
/// Electromagnetic coupling constant \f$\alpha_\textrm{em}=\frac{e^2}{4\pi\epsilon_0\hbar c}\f$
const double alphaEM = 1./137.035;
/// Strong coupling constant \f$\alpha_\textrm{QCD}\f$
const double alphaQCD = 0.1184; // at the Z pole
/// Conversion factor between GeV^2 and barn
- const double GeV2toBarn = 3.89351824e8; // 1.e4*pow(197.3271, 2);
+ const double GeV2toBarn = 3.89351824e8; // 1.e4*(197.3271**2);
const double sconstb = 2.1868465e10; // 1.1868465e10;
const double alphaReduced = 0.5 * alphaEM / M_PI;
- const double mp = 0.938272046, mpi = 0.1349766;
}
}
#endif
diff --git a/CepGen/Physics/FormFactors.cpp b/CepGen/Physics/FormFactors.cpp
index c92f0bd..9cee183 100644
--- a/CepGen/Physics/FormFactors.cpp
+++ b/CepGen/Physics/FormFactors.cpp
@@ -1,78 +1,87 @@
#include "FormFactors.h"
#include "CepGen/Core/Exception.h"
+#include "CepGen/Physics/ParticleProperties.h"
+
#include "CepGen/StructureFunctions/ALLM.h"
#include "CepGen/StructureFunctions/BlockDurandHa.h"
#include "CepGen/StructureFunctions/FioreBrasse.h"
#include "CepGen/StructureFunctions/GenericLHAPDF.h"
#include "CepGen/StructureFunctions/SuriYennie.h"
#include "CepGen/StructureFunctions/SzczurekUleshchenko.h"
namespace CepGen
{
FormFactors
FormFactors::Trivial()
{
return FormFactors( 1.0, 1.0 );
}
FormFactors
FormFactors::ProtonElastic( double q2 )
{
- const double mp2 = Constants::mp*Constants::mp;
+ const double mp2 = ParticleProperties::mass( Proton )*ParticleProperties::mass( Proton );
const double GE = pow( 1.+q2/0.71, -2. ), GE2 = GE*GE;
const double GM = 2.79*GE, GM2 = GM*GM;
return FormFactors( ( 4.*mp2*GE2 + q2*GM2 ) / ( 4.*mp2 + q2 ), GM2 );
}
FormFactors
FormFactors::ProtonInelastic( const StructureFunctions::Type& sf, double q2, double mi2, double mf2 )
{
switch ( sf ) {
case StructureFunctions::ElasticProton:
InWarning( "Elastic proton form factors requested! Check your process definition!" );
return FormFactors::ProtonElastic( q2 );
case StructureFunctions::SuriYennie:
return FormFactors::SuriYennie( q2, mi2, mf2 );
case StructureFunctions::SzczurekUleshchenko:
return FormFactors::SzczurekUleshchenko( q2, mi2, mf2 );
case StructureFunctions::FioreBrasse:
return FormFactors::FioreBrasse( q2, mi2, mf2 );
default: throw Exception( __PRETTY_FUNCTION__, "Invalid structure functions required!", FatalError );
}
}
FormFactors
FormFactors::SuriYennie( double q2, double mi2, double mf2 )
{
const double x = q2 / ( q2 + mf2 - mi2 );
const SF::SuriYennie suriyennie, sy = suriyennie( q2, x );
//std::cout << "---> " << sy.FM << "\t" << sy.F2*x/q2 << "\t" << sy.F2*x*sqrt(mi2)/q2 << std::endl;
return FormFactors( sy.F2 * x * sqrt( mi2 ) / q2, sy.FM ); //FIXME
}
FormFactors
FormFactors::FioreBrasse( double q2, double mi2, double mf2 )
{
const double x = q2 / ( q2 + mf2 - mi2 );
SF::FioreBrasse fb, sf = fb( q2, x );
return FormFactors( sf.F2 * x / q2, -2.*sf.W1 / q2 );
}
FormFactors
FormFactors::SzczurekUleshchenko( double q2, double mi2, double mf2 )
{
const double x = q2 / ( q2 + mf2 - mi2 );
SF::SzczurekUleshchenko su, sf = su( q2, x );
return FormFactors( sf.F2 * x / q2, -2.*sf.F1 / q2 );
}
+ double
+ FormFactors::x( double q2, double w2, double m2 ) const
+ {
+ const double mp2 = ParticleProperties::mass( Proton )*ParticleProperties::mass( Proton );
+ return 1./( 1.+( w2-mp2 ) / q2+m2 );
+ }
+
std::ostream&
operator<<( std::ostream& os, const FormFactors& ff )
{
os << Form( "Form factors: electric: Fe = %.3e ; magnetic: Fm = %.3e", ff.FE, ff.FM ).c_str();
return os;
}
}
diff --git a/CepGen/Physics/FormFactors.h b/CepGen/Physics/FormFactors.h
index 39c2456..fb0d903 100644
--- a/CepGen/Physics/FormFactors.h
+++ b/CepGen/Physics/FormFactors.h
@@ -1,47 +1,44 @@
#ifndef CepGen_Physics_FormFactors_h
#define CepGen_Physics_FormFactors_h
#include <math.h>
#include <array>
#include "CepGen/Core/utils.h"
#include "CepGen/StructureFunctions/StructureFunctions.h"
#include "CepGen/Physics/Constants.h"
namespace CepGen
{
/// Form factors collection (electric and magnetic parts)
class FormFactors
{
public:
/// Initialise a collection of electric/magnetic form factors
FormFactors( double fe=0.0, double fm=0.0 ) : FE( fe ), FM( fm ) {}
// compute x from w2/m2
- double x( double q2, double w2, double m2=0.0 ) const {
- const double mp2 = Constants::mp*Constants::mp;
- return 1./( 1.+( w2-mp2 ) / q2+m2 );
- }
+ double x( double q2, double w2, double m2=0.0 ) const;
/// Trivial, spin-0 form factors (e.g. pion)
static FormFactors Trivial();
/// Elastic proton form factors
static FormFactors ProtonElastic( double q2 );
/// Suri-Yennie inelastic form factors
static FormFactors SuriYennie( double q2, double mi2, double mf2 );
/// Brasse et al. inelastic form factors
/// \cite Brasse1976413
static FormFactors FioreBrasse( double q2, double mi2, double mf2 );
/// Szczurek-Uleschenko inelastic form factors
static FormFactors SzczurekUleshchenko( double q2, double mi2, double mf2 );
/// Generate the form factors according to the proton structure functions set
static FormFactors ProtonInelastic( const StructureFunctions::Type& sf, double q2, double mi2, double mf2 );
/// Electric form factor
double FE;
/// Magnetic form factor
double FM;
/// Dumping operator for standard output streams
friend std::ostream& operator<<( std::ostream&, const FormFactors& );
};
}
#endif
diff --git a/CepGen/Physics/Kinematics.cpp b/CepGen/Physics/Kinematics.cpp
index 8603c2a..e90f8ef 100644
--- a/CepGen/Physics/Kinematics.cpp
+++ b/CepGen/Physics/Kinematics.cpp
@@ -1,83 +1,83 @@
#include "Kinematics.h"
#include "CepGen/Core/Exception.h"
#include "CepGen/Core/utils.h"
namespace CepGen
{
Kinematics::Kinematics() :
- inp( { 6500., 6500. } ), inpdg( { Particle::Proton, Particle::Proton } ),
+ inp( { 6500., 6500. } ), inpdg( { Proton, Proton } ),
central_system( {} ),
mode( ElasticElastic ), structure_functions( StructureFunctions::SuriYennie )
{}
Kinematics::Kinematics( const Kinematics& kin ) :
inp( kin.inp ), inpdg( kin.inpdg ),
central_system( kin.central_system ),
mode( kin.mode ), structure_functions( kin.structure_functions ),
cuts( kin.cuts )
{}
Kinematics::~Kinematics()
{}
void
Kinematics::dump( std::ostream& os ) const
{
os << std::setfill(' ');
os << "===== Central system\n";
for ( std::map<Cuts::Central,Limits>::const_iterator lim = cuts.central.begin(); lim != cuts.central.end(); ++lim ) {
os << std::setw(30) << lim->first << ": " << lim->second;
}
os << "===== Initial state\n";
for ( std::map<Cuts::InitialState,Limits>::const_iterator lim = cuts.initial.begin(); lim != cuts.initial.end(); ++lim ) {
os << std::setw(30) << lim->first << ": " << lim->second;
}
os << "===== Remnants\n";
for ( std::map<Cuts::Remnants,Limits>::const_iterator lim = cuts.remnants.begin(); lim != cuts.remnants.end(); ++lim ) {
os << std::setw(30) << lim->first << ": " << lim->second;
}
}
std::ostream&
operator<<( std::ostream& os, const Kinematics::ProcessMode& pm )
{
switch ( pm ) {
case Kinematics::ElectronElectron: return os << "electron/electron";
case Kinematics::ElectronProton: return os << "electron/proton";
case Kinematics::ProtonElectron: return os << "proton/electron";
case Kinematics::ElasticElastic: return os << "elastic/elastic";
case Kinematics::InelasticElastic: return os << "inelastic/elastic";
case Kinematics::ElasticInelastic: return os << "elastic/inelastic";
case Kinematics::InelasticInelastic: return os << "inelastic/inelastic";
}
return os;
}
std::ostream&
operator<<( std::ostream& os, const Kinematics::Limits& lim )
{
if ( !lim.hasMin() && !lim.hasMax() ) return os << "no cuts";
if ( !lim.hasMin() ) return os << Form( "≤ %.3f", lim.max() );
if ( !lim.hasMax() ) return os << Form( "≥ %.3f", lim.min() );
return os << Form( "%.3f → %.3f", lim.min(), lim.max() );
}
double
Kinematics::Limits::x( double v ) const
{
if ( v < 0. || v > 1. ) { InError( Form( "x must be comprised between 0 and 1 ; x value = %.5e", v ) ); }
if ( !hasMin() || !hasMax() ) return invalid_;
return first + ( second-first ) * v;
}
Kinematics::CutsList::CutsList() :
initial( { { Cuts::q2, { 0.0, 1.0e5 } }, { Cuts::qt, { 0.0, 500.0 } } } ),
central( { { Cuts::pt_single, 3.0 }, { Cuts::pt_diff, { 0., 400.0 } } } ),
remnants( { { Cuts::mass, { 1.07, 320.0 } } } )
{}
Kinematics::CutsList::CutsList( const CutsList& cuts ) :
initial( cuts.initial ), central( cuts.central ), remnants( cuts.remnants )
{}
}
diff --git a/CepGen/Physics/Kinematics.h b/CepGen/Physics/Kinematics.h
index 275410f..8488630 100644
--- a/CepGen/Physics/Kinematics.h
+++ b/CepGen/Physics/Kinematics.h
@@ -1,108 +1,108 @@
#ifndef CepGen_Physics_Kinematics_h
#define CepGen_Physics_Kinematics_h
#include <iomanip>
#include <algorithm>
#include "CepGen/Core/Logger.h"
#include "CepGen/Event/Particle.h"
#include "CepGen/StructureFunctions/StructureFunctions.h"
#include "Cuts.h"
#include <vector>
#include <map>
using std::cout;
using std::string;
namespace CepGen
{
/// List of kinematic constraints to apply on the process phase space.
class Kinematics
{
public:
/// Validity interval for a variable
class Limits : private std::pair<double,double>
{
public:
/// Define lower and upper limits on a quantity
Limits( double min=invalid_, double max=invalid_ ) : std::pair<double,double>( min, max ) {}
/// Lower limit to apply on the variable
double min() const { return first; }
/// Lower limit to apply on the variable
double& min() { return first; }
/// Upper limit to apply on the variable
double max() const { return second; }
/// Upper limit to apply on the variable
double& max() { return second; }
double x( double v ) const;
/// Specify the lower and upper limits on the variable
void in( double low, double up ) { first = low; second = up; }
/// Full variable range allowed
double range() const { return ( !hasMin() || !hasMax() ) ? 0. : second-first; }
/// Have a lower limit?
bool hasMin() const { return first != invalid_; }
/// Have an upper limit?
bool hasMax() const { return second != invalid_; }
/// Human-readable expression of the limits
friend std::ostream& operator<<( std::ostream&, const Limits& );
private:
static constexpr double invalid_ = -999.999;
};
public:
Kinematics();
Kinematics( const Kinematics& kin );
~Kinematics();
/// Type of kinematics to consider for the process
enum ProcessMode {
ElectronProton = 0, ///< electron-proton elastic case
ElasticElastic = 1, ///< proton-proton elastic case
ElasticInelastic = 2, ///< proton-proton single-dissociative (or inelastic-elastic) case
InelasticElastic = 3, ///< proton-proton single-dissociative (or elastic-inelastic) case
InelasticInelastic = 4, ///< proton-proton double-dissociative case
ProtonElectron,
ElectronElectron
};
/// Human-readable format of a process mode (elastic/dissociative parts)
friend std::ostream& operator<<( std::ostream&, const ProcessMode& );
/// Dump all the parameters used in this process cross-section computation
/// or events generation
void dump( std::ostream& os = Logger::get().outputStream ) const;
/// Incoming particles' momentum (in \f$\text{GeV}/c\f$)
std::pair<double,double> inp;
/// Set the incoming particles' momenta (if the collision is symmetric)
inline void setSqrtS( double sqrts ) { inp = { sqrts*0.5, sqrts*0.5 }; }
/// Process centre of mass energy
inline double sqrtS() const { return ( inp.first+inp.second ); }
/// Beam/primary particle's PDG identifier
- std::pair<Particle::ParticleCode,Particle::ParticleCode> inpdg;
+ std::pair<ParticleCode,ParticleCode> inpdg;
/// PDG id of the outgoing central particles
- std::vector<Particle::ParticleCode> central_system;
+ std::vector<ParticleCode> central_system;
/// Type of kinematics to consider for the phase space
ProcessMode mode;
/// Type of structure functions to consider
StructureFunctions::Type structure_functions;
struct CutsList {
CutsList();
CutsList( const CutsList& cuts );
/// Cuts on the initial particles kinematics
std::map<Cuts::InitialState, Limits> initial;
/// Cuts on the central system produced
std::map<Cuts::Central, Limits> central;
/// Cuts on the beam remnants system
std::map<Cuts::Remnants, Limits> remnants;
};
CutsList cuts;
};
}
#endif
diff --git a/CepGen/Physics/ParticleProperties.h b/CepGen/Physics/ParticleProperties.h
new file mode 100644
index 0000000..5f140ca
--- /dev/null
+++ b/CepGen/Physics/ParticleProperties.h
@@ -0,0 +1,152 @@
+#ifndef CepGen_Physics_ParticleProperties_h
+#define CepGen_Physics_ParticleProperties_h
+
+#include <iostream>
+
+namespace CepGen
+{
+ /** Unique identifier for a particle type. From \cite Beringer:1900zz :
+ * `The Monte Carlo particle numbering scheme [...] is intended to facilitate interfacing between event generators, detector simulators, and analysis packages used in particle physics.`
+ * \brief PDG ids of all known particles
+ */
+ enum ParticleCode {
+ invalidParticle = 0,
+ //--- fundamental particles
+ dQuark = 1, uQuark = 2,
+ Electron = 11, ElectronNeutrino = 12,
+ Muon = 13, MuonNeutrino = 14,
+ Tau = 15, TauNeutrino = 16,
+ Gluon = 21, Photon = 22, Z = 23, W = 24,
+ //--- composite particles
+ PiPlus = 211, PiZero = 111,
+ Rho770_0 = 113, Rho1450_0 = 100113, Rho1700_0 = 30113,
+ Eta = 221, Omega782 = 223,
+ h1380_1 = 10333,
+ JPsi= 443,
+ Phi1680 = 100333,
+ Upsilon1S = 553, Upsilon2S = 100553, Upsilon3S = 200553,
+ ud0Diquark = 2101, ud1Diquark = 2103, uu1Diquark = 2203,
+ Proton = 2212, Neutron = 2112,
+ Pomeron = 990, Reggeon = 110
+ };
+ namespace ParticleProperties
+ {
+ /**
+ * \brief Gets the mass of a particle
+ * \param pdgId ParticleCode (PDG ID)
+ * \return Mass of the particle in \f$\textrm{GeV}/c^2\f$
+ */
+ inline double mass( const ParticleCode& pdgId ) {
+ switch ( pdgId ) {
+ case dQuark: return 0.33; // mass from PYTHIA6.4
+ case uQuark: return 0.33; // mass from PYTHIA6.4
+ case Electron: return 0.510998928e-3;
+ case Muon: return 0.1056583715;
+ case Tau: return 1.77682;
+ case ElectronNeutrino: case MuonNeutrino: case TauNeutrino: return 0.;
+ case Gluon: case Photon: return 0.;
+ case Z: return 91.1876;
+ case W: return 80.385;
+ case PiPlus: return 0.13957018;
+ case PiZero: return 0.1349766;
+ case JPsi: return 20.; //FIXME FIXME FIXME
+ case ud0Diquark: return 0.57933;
+ case ud1Diquark: return 0.77133;
+ case uu1Diquark: return 0.77133;
+ case Proton: return 0.938272046;
+ case Neutron: return 0.939565346;
+ case Upsilon1S: return 9.46030;
+ case Upsilon2S: return 10.02326;
+ case Upsilon3S: return 10.3552;
+ case Rho770_0: return 0.77526;
+ case Rho1450_0: return 1.465;
+ case Rho1700_0: return 1.720;
+ case h1380_1: return 1.38619;
+ case Eta: return 0.547862;
+ case invalidParticle:
+ default: return -1.;
+ }
+ }
+ /**
+ * \brief Gets the electric charge of a particle
+ * \param pdgId ParticleCode (PDG ID)
+ * \return Charge of the particle in \f$e\f$
+ */
+ inline double charge( const ParticleCode& pdgId ) {
+ switch ( pdgId ) {
+ case Proton: return +1.;
+ case dQuark: return -1./3;
+ case uQuark: return +2./3;
+ case Electron: case Muon: case Tau: return -1.;
+ case ElectronNeutrino: case MuonNeutrino: case TauNeutrino: return 0.;
+ case Gluon: case Z: case Photon: return 0.;
+ case W: return +1.;
+ case PiPlus: return +1.;
+ case PiZero: return 0.;
+ case Neutron: return 0.;
+ case Eta: return 0.;
+ default: return 0.;
+ }
+ }
+ /**
+ * \brief Total decay width of one unstable particle
+ * \param[in] pdgId ParticleCode (PDG ID)
+ * \return Decay width in GeV
+ */
+ inline double width( const ParticleCode& pdgId ) {
+ switch ( pdgId ) {
+ case JPsi: return 5.; //FIXME
+ case Z: return 2.4952;
+ case W: return 2.085;
+ case Upsilon1S: return 54.02e-6;
+ case Upsilon2S: return 31.98e-6;
+ case Upsilon3S: return 20.32e-6;
+ case Rho770_0: return 0.150; // PDG
+ case Rho1450_0: return 0.400; // PDG
+ case Rho1700_0: return 0.250; // PDG
+ default: return -1.;
+ }
+ }
+ }
+
+ inline std::ostream& operator<<( std::ostream& os, const ParticleCode& pc ) {
+ switch ( pc ) {
+ case dQuark: return os << "d quark";
+ case uQuark: return os << "u quark";
+ case Electron: return os << "electron";
+ case ElectronNeutrino: return os << "nu_e";
+ case Muon: return os << "muon";
+ case MuonNeutrino: return os << "nu_mu";
+ case Tau: return os << "tau";
+ case TauNeutrino: return os << "nu_tau";
+ case Gluon: return os << "gluon";
+ case Photon: return os << "photon";
+ case Z: return os << "Z";
+ case W: return os << "W+-";
+ case PiPlus: return os << "pi+";
+ case PiZero: return os << "pi0";
+ case Rho770_0: return os << "rho(770)0";
+ case Rho1450_0: return os << "rho(1450)0";
+ case Rho1700_0: return os << "rho(1700)0";
+ case h1380_1: return os << "h(1380)1";
+ case Eta: return os << "eta meson";
+ case Omega782: return os << "omega(782)";
+ case JPsi: return os << "J/Psi";
+ case Phi1680: return os << "phi(1680)";
+ case Upsilon1S: return os << "Upsilon(1S)";
+ case Upsilon2S: return os << "Upsilon(2S)";
+ case Upsilon3S: return os << "Upsilon(3S)";;
+ case ud0Diquark: return os << "(ud)0 di-quark";
+ case ud1Diquark: return os << "(ud)1 di-quark";
+ case uu1Diquark: return os << "(uu)1 di-quark";
+ case Proton: return os << "proton";
+ case Neutron: return os << "neutron";
+ case Pomeron: return os << "pomeron";
+ case Reggeon: return os << "reggeon";
+ case invalidParticle: return os << "[...]";
+ }
+ return os;
+ }
+}
+
+#endif
diff --git a/CepGen/Processes/GamGamLL.cpp b/CepGen/Processes/GamGamLL.cpp
index 4d1fc92..b58494a 100644
--- a/CepGen/Processes/GamGamLL.cpp
+++ b/CepGen/Processes/GamGamLL.cpp
@@ -1,877 +1,877 @@
#include "GamGamLL.h"
#include "CepGen/Core/Exception.h"
using namespace CepGen::Process;
GamGamLL::GamGamLL( int nopt ) :
GenericProcess( "lpair", "pp -> p(*) (gamma gamma -> l+ l-) p(*)" ),
n_opt_( nopt ),
MX2_( 0. ), MY2_( 0. ), Ml2_( 0. ),
ep1_( 0. ), ep2_( 0. ), p_cm_( 0. ),
w12_( 0. ), w31_( 0. ), dw31_( 0. ), w52_( 0. ), dw52_( 0. ),
ec4_( 0. ), pc4_( 0. ), mc4_( 0. ), w4_( 0. ),
p12_( 0. ), p1k2_( 0. ), p2k1_( 0. ),
p13_( 0. ), p14_( 0. ), p25_( 0. ),
q1dq_( 0. ), q1dq2_( 0. ),
s1_( 0. ), s2_( 0. ),
epsi_( 0. ),
g5_( 0. ), g6_( 0. ), a5_( 0. ), a6_( 0. ), bb_( 0. ),
gram_( 0. ),
dd1_( 0. ), dd2_( 0. ), dd3_( 0. ), dd4_( 0. ), dd5_( 0. ),
delta_( 0. ),
g4_( 0. ), sa1_( 0. ), sa2_( 0. ),
sl1_( 0. ),
cos_theta4_( 0. ), sin_theta4_( 0. ),
al4_( 0. ), be4_( 0. ), de3_( 0. ), de5_( 0. ),
pt4_( 0. ),
jacobian_( 0. )
{}
void
GamGamLL::addEventContent()
{
GenericProcess::setEventContent( {
- { Particle::IncomingBeam1, Particle::Proton },
- { Particle::IncomingBeam2, Particle::Proton },
- { Particle::Parton1, Particle::Photon },
- { Particle::Parton2, Particle::Photon }
+ { Particle::IncomingBeam1, Proton },
+ { Particle::IncomingBeam2, Proton },
+ { Particle::Parton1, Photon },
+ { Particle::Parton2, Photon }
}, {
- { Particle::OutgoingBeam1, { Particle::Proton } },
- { Particle::OutgoingBeam2, { Particle::Proton } },
- { Particle::CentralSystem, { Particle::Muon, Particle::Muon } }
+ { Particle::OutgoingBeam1, { Proton } },
+ { Particle::OutgoingBeam2, { Proton } },
+ { Particle::CentralSystem, { Muon, Muon } }
} );
}
unsigned int
GamGamLL::numDimensions( const Kinematics::ProcessMode& process_mode ) const
{
switch ( process_mode ) {
case Kinematics::ElectronProton: { InError( "Not supported yet!" ); }
case Kinematics::ElasticElastic:
default: return 7;
case Kinematics::ElasticInelastic:
case Kinematics::InelasticElastic: return 8;
case Kinematics::InelasticInelastic: return 9;
}
}
bool
GamGamLL::pickin()
{
DebuggingInsideLoop( Form( "Optimised mode? %i", n_opt_ ) );
jacobian_ = 0.;
w4_ = mc4_*mc4_;
// sig1 = sigma and sig2 = sigma' in [1]
const double sig = mc4_+MY_;
double sig1 = sig*sig,
sig2 = sig1;
DebuggingInsideLoop( Form( "mc4 = %f\n\t"
"sig1 = %f\n\t"
"sig2 = %f", mc4_, sig1, sig2 ) );
// Mass difference between the first outgoing particle and the first incoming
// particle
w31_ = MX2_-w1_;
// Mass difference between the second outgoing particle and the second
// incoming particle
w52_ = MY2_-w2_;
// Mass difference between the two incoming particles
w12_ = w1_-w2_;
// Mass difference between the central two-photons system and the second
// outgoing particle
const double d6 = w4_-MY2_;
DebuggingInsideLoop( Form( "w1 = %f\n\t"
"w2 = %f\n\t"
"w3 = %f\n\t"
"w4 = %f\n\t"
"w5 = %f",
w1_, w2_, MX2_, w4_, MY2_ ) );
DebuggingInsideLoop( Form( "w31 = %f\n\tw52 = %f\n\tw12 = %f", w31_, w52_, w12_ ) );
const double ss = s_+w12_;
const double rl1 = ss*ss-4.*w1_*s_; // lambda(s, m1**2, m2**2)
if ( rl1 <= 0. ) { InWarning( Form( "rl1 = %f <= 0", rl1 ) ); return false; }
sl1_ = sqrt( rl1 );
s2_ = 0.;
double ds2 = 0.;
if ( n_opt_ == 0 ) {
const double smax = s_+MX2_-2.*MX_*sqs_;
Map( x(2), sig1, smax, s2_, ds2, "s2" );
sig1 = s2_; //FIXME!!!!!!!!!!!!!!!!!!!!
}
DebuggingInsideLoop( Form( "s2 = %f", s2_ ) );
//std::cout << "s=" << _s << ", w3=" << MX2_ << ", sig1=" << sig1 << std::endl;
const double sp = s_+MX2_-sig1,
d3 = sig1-w2_;
const double rl2 = sp*sp-4.*s_*MX2_; // lambda(s, m3**2, sigma)
if ( rl2 <= 0. ) { InWarning( Form( "rl2 = %f <= 0", rl2 ) ); return false; }
const double sl2 = sqrt( rl2 );
//std::cout << "ss=" << ss << ", sp=" << sp << ", sl1=" << sl1_ << ", sl2=" << sl2 << std::endl;
double t1_max = w1_+MX2_-( ss*sp+sl1_*sl2 )/( 2.*s_ ), // definition from eq. (A.4) in [1]
t1_min = ( w31_*d3+( d3-w31_ )*( d3*w1_-w31_*w2_ )/s_ )/t1_max; // definition from eq. (A.5) in [1]
// FIXME dropped in CDF version
const Kinematics::Limits q2_limits = cuts_.cuts.initial[Cuts::q2];
if ( t1_max > -q2_limits.min() ) { InWarning( Form( "t1max = %f > -q2min = %f", t1_max, -q2_limits.min() ) ); return false; }
if ( t1_min < -q2_limits.max() && q2_limits.hasMax() ) { Debugging( Form( "t1min = %f < -q2max = %f", t1_min, -q2_limits.max() ) ); return false; }
if ( t1_max < -q2_limits.max() && q2_limits.hasMax() ) t1_max = -q2_limits.max();
if ( t1_min > -q2_limits.min() ) t1_min = -q2_limits.min();
/////
// t1, the first photon propagator, is defined here
t1_ = 0.;
double dt1 = 0.;
Map( x(0), t1_min, t1_max, t1_, dt1, "t1" );
// changes wrt mapt1 : dx->-dx
dt1 = -dt1;
DebuggingInsideLoop( Form( "Definition of t1 = %f according to\n\t"
"(t1min, t1max) = (%f, %f)", t1_, t1_min, t1_max ) );
dd4_ = w4_-t1_;
const double d8 = t1_-w2_,
t13 = t1_-w1_-MX2_;
sa1_ = -pow( t1_-w31_, 2 )/4.+w1_*t1_;
if ( sa1_ >= 0. ) { InWarning( Form( "sa1_ = %f >= 0", sa1_ ) ); return false; }
const double sl3 = sqrt( -sa1_ );
// one computes splus and (s2x=s2max)
double splus, s2max;
if ( w1_ != 0. ) {
const double sb =( s_*( t1_-w31_ )+w12_*t13 )/( 2.*w1_ )+MX2_,
sd = sl1_*sl3/w1_,
se =( s_*( t1_*( s_+t13-w2_ )-w2_*w31_ )+MX2_*( w12_*d8+w2_*MX2_ ) )/w1_;
if ( fabs( ( sb-sd )/sd )>=1. ) { splus = sb-sd; s2max = se/splus; }
else { s2max = sb+sd; splus = se/s2max; }
}
else { // 3
s2max = ( s_*(t1_*(s_+d8-MX2_)-w2_*MX2_ )+w2_*MX2_*( w2_+MX2_-t1_ ) )/( ss*t13 );
splus = sig2;
}
// 4
double s2x = s2max;
DebuggingInsideLoop( Form( "s2x = s2max = %f", s2x ) );
if ( n_opt_ < 0 ) { // 5
if ( splus > sig2 ) {
sig2 = splus;
DebuggingInsideLoop( Form( "sig2 truncated to splus = %f", splus ) );
}
if ( n_opt_ < -1 ) { Map( x(2), sig2, s2max, s2_, ds2, "s2" ); }
else { Mapla( t1_, w2_, x(2), sig2, s2max, s2_, ds2 ); } // n_opt_==-1
s2x = s2_;
}
else if ( n_opt_ == 0 ) { s2x = s2_; } // 6
DebuggingInsideLoop( Form( "s2x = %f", s2x ) );
// 7
const double r1 = s2x-d8,
r2 = s2x-d6;
const double rl4 = ( r1*r1-4.*w2_*s2x )*( r2*r2-4.*MY2_*s2x );
if ( rl4 <= 0. ) {
DebuggingInsideLoop( Form( "rl4 = %f <= 0", rl4 ) );
return false;
}
const double sl4 = sqrt( rl4 );
// t2max, t2min definitions from eq. (A.12) and (A.13) in [1]
const double t2_max = w2_+MY2_-( r1*r2+sl4 )/s2x * 0.5,
t2_min = ( w52_*dd4_+( dd4_-w52_ )*( dd4_*w2_-w52_*t1_ )/s2x )/t2_max;
// t2, the second photon propagator, is defined here
t2_ = 0.;
double dt2 = 0.;
Map( x(1), t2_min, t2_max, t2_, dt2, "t2" );
// changes wrt mapt2 : dx->-dx
dt2 = -dt2;
// \f$\delta_6=m_4^2-m_5^2\f$ as defined in Vermaseren's paper
const double tau = t1_-t2_,
r3 = dd4_-t2_,
r4 = w52_-t2_;
DebuggingInsideLoop( Form( "r1 = %f\n\tr2 = %f\n\tr3 = %f\n\tr4 = %f", r1, r2, r3, r4 ) );
const double b = r3*r4-2.*( t1_+w2_ )*t2_,
c = t2_*d6*d8+( d6-d8 )*( d6*w2_-d8*MY2_ );
const double t25 = t2_-w2_-MY2_;
sa2_ = -r4*r4/4.+w2_*t2_;
if ( sa2_ >= 0. ) { InWarning( Form( "sa2_ = %f >= 0", sa2_ ) ); return false; }
const double sl6 = 2.*sqrt( -sa2_ );
g4_ = -r3*r3/4.+t1_*t2_;
if ( g4_ >= 0. ) { InWarning( Form( "g4_ = %f >= 0", g4_ ) ); return false; }
const double sl7 = 2.*sqrt( -g4_ ),
sl5 = sl6*sl7;
double s2p, s2min;
if ( fabs( ( sl5-b )/sl5 ) >= 1. ) {
s2p = ( sl5-b )/t2_ * 0.5;
s2min = c/( t2_*s2p );
}
else { // 8
s2min = ( -sl5-b )/t2_ * 0.5;
s2p = c/( t2_*s2min );
}
// 9
if ( n_opt_ > 1 ) Map( x( 2 ), s2min, s2max, s2_, ds2, "s2" );
else if ( n_opt_ == 1 ) Mapla( t1_, w2_, x( 2 ), s2min, s2max, s2_, ds2 );
const double ap = -0.25*pow( s2_+d8, 2 )+s2_*t1_;
DebuggingInsideLoop( Form( "s2 = %f, s2max = %f, splus = %f", s2_, s2max, splus ) );
if ( w1_!=0. ) dd1_ = -0.25 * ( s2_-s2max ) * ( s2_-splus ) * w1_; // 10
else dd1_ = 0.25 * ( s2_-s2max ) * ss * t13;
// 11
dd2_ = -t2_*( s2_-s2p )*( s2_-s2min ) * 0.25;
DebuggingInsideLoop( Form( "t2 =%f\n\ts2 =%f\n\ts2p=%f\n\ts2min=%f\n\tdd2=%f", t2_, s2_, s2p, s2min, dd2_ ) );
const double yy4 = cos( M_PI*x( 3 ) );
const double dd = dd1_*dd2_;
p12_ = ( s_-w1_-w2_ )*0.5;
const double st = s2_-t1_-w2_;
const double delb = ( 2.*w2_*r3+r4*st )*( 4.*p12_*t1_-( t1_-w31_ )*st )/( 16.*ap );
if ( dd <= 0. ) {
DebuggingInsideLoop( Form( "dd = %e <= 0\n\tdd1 = %e\tdd2 = %e", dd, dd1_, dd2_ ) );
return false;
}
delta_ = delb - yy4*st*sqrt( dd )/ ap * 0.5;
s1_ = t2_+w1_+( 2.*p12_*r3-4.*delta_ )/st;
if ( ap >= 0. ) {
DebuggingInsideLoop( Form( "ap = %f >= 0", ap ) );
return false;
}
jacobian_ = ds2
* dt1
* dt2
* M_PI*M_PI/( 8.*sl1_*sqrt( -ap ) );
DebuggingInsideLoop( Form( "Jacobian = %e", jacobian_ ) );
gram_ = ( 1.-yy4*yy4 )*dd/ap;
p13_ = -t13 * 0.5;
p14_ = (tau+s1_-MX2_) * 0.5;
p25_ = -t25 * 0.5;
/*const double //p15 = (s_+t2_-s1_-w2_)/2.,
//p23 = (s_+t1_-s2_-w1_)/2.,
//p24 = (s2_-tau-MY2_)/2.,
//p34 = (s1_-MX2_-w4_)/2.,
//p35 = (s_+w4_-s1_-s2_)/2.,
//p45 = (s2_-w4_-MY2_)/2.;*/
p1k2_ = ( s1_-t2_-w1_ ) * 0.5;
p2k1_ = st * 0.5;
double s1p, s1m;
if ( w2_ != 0. ) {
const double sbb = ( s_*( t2_-w52_ )-w12_*t25 )/w2_ * 0.5 + MY2_,
sdd = sl1_*sl6/w2_ * 0.5,
see = ( s_*( t2_*( s_+t25-w1_ )-w1_*w52_ )+MY2_*( w1_*MY2_-w12_*( t2_-w1_ ) ) )/w2_;
if ( sbb/sdd >= 0. ) { s1p = sbb+sdd; s1m = see/s1p; }
else { s1m = sbb-sdd; s1p = see/s1m; } // 12
dd3_ = -w2_*( s1p-s1_ )*( s1m-s1_ ) * 0.25; // 13
}
else { // 14
s1p = ( s_*( t2_*( s_-MY2_+t2_-w1_ )-w1_*MY2_ )+w1_*MY2_*( w1_+MY2_-t2_ ) )/( t25*( s_-w12_ ) );
dd3_ = -t25*( s_-w12_ )*( s1p-s1_ ) * 0.25;
}
// 15
//const double acc3 = (s1p-s1_)/(s1p+s1_);
const double ssb = t2_+w1_-r3*( w31_-t1_ )/t1_ * 0.5,
ssd = sl3*sl7/t1_,
sse = ( t2_-w1_ )*( w4_-MX2_ )+( t2_-w4_+w31_ )*( ( t2_-w1_)*MX2_-(w4_-MX2_)*w1_)/t1_;
double s1pp, s1pm;
if (ssb/ssd>=0.) { s1pp = ssb+ssd; s1pm = sse/s1pp; }
else { s1pm = ssb-ssd; s1pp = sse/s1pm; } // 16
// 17
dd4_ = -t1_*( s1_-s1pp )*( s1_-s1pm ) * 0.25;
//const double acc4 = ( s1_-s1pm )/( s1_+s1pm );
dd5_ = dd1_+dd3_+( ( p12_*( t1_-w31_ )*0.5-w1_*p2k1_ )*( p2k1_*( t2_-w52_ )-w2_*r3 )-delta_*( 2.*p12_*p2k1_-w2_*( t1_-w31_ ) ) ) / p2k1_;
return true;
}
bool
GamGamLL::orient()
{
if ( !pickin() or jacobian_ == 0. ) { DebuggingInsideLoop( Form( "Pickin failed! Jacobian = %f", jacobian_ ) ); return false; }
const double re = 0.5 / sqs_;
ep1_ = re*( s_+w12_ );
ep2_ = re*( s_-w12_ );
DebuggingInsideLoop( Form( " re = %e\n\tw12_ = %e", re, w12_ ) );
DebuggingInsideLoop( Form( "Incoming particles' energy = %f, %f", ep1_, ep2_ ) );
p_cm_ = re*sl1_;
de3_ = re*(s2_-MX2_+w12_);
de5_ = re*(s1_-MY2_-w12_);
// Final state energies
const double ep3 = ep1_-de3_,
ep5 = ep2_-de5_;
ec4_ = de3_+de5_;
if ( ec4_ < mc4_ ) { InWarning( Form( "ec4_ = %f < mc4_ = %f\n\t==> de3 = %f, de5 = %f", ec4_, mc4_, de3_, de5_ ) ); return false; }
// What if the protons' momenta are not along the z-axis?
pc4_ = sqrt( ec4_*ec4_-mc4_*mc4_ );
if ( pc4_==0. ) {
InWarning( "pzc4==0" );
return false;
}
const double pp3 = sqrt( ep3*ep3-MX2_ ), pt3 = sqrt( dd1_/s_ )/p_cm_,
pp5 = sqrt( ep5*ep5-MY2_ ), pt5 = sqrt( dd3_/s_ )/p_cm_;
DebuggingInsideLoop( Form( "Central system's energy: E4 = %f\n\t"
" momentum: p4 = %f\n\t"
" invariant mass: m4 = %f\n\t"
"Outgoing particles' energy: E3 = %f\n\t"
" E5 = %f",
ec4_, pc4_, mc4_, ep3, ep5 ) );
const double sin_theta3 = pt3/pp3,
sin_theta5 = pt5/pp5;
DebuggingInsideLoop( Form( "sin_theta3 = %e\n\tsin_theta5 = %e", sin_theta3, sin_theta5 ) );
if (sin_theta3>1.) { InWarning( Form( "sin_theta3 = %e > 1", sin_theta3 ) ); return false; }
if (sin_theta5>1.) { InWarning( Form( "sin_theta5 = %e > 1", sin_theta5 ) ); return false; }
double ct3 = sqrt( 1.-sin_theta3*sin_theta3 ),
ct5 = sqrt( 1.-sin_theta5*sin_theta5 );
if ( ep1_*ep3 < p13_ ) ct3 *= -1.;
if ( ep2_*ep5 > p25_ ) ct5 *= -1.;
DebuggingInsideLoop( Form( "ct3 = %e\n\tct5 = %e", ct3, ct5 ) );
if ( dd5_ < 0. ) { InWarning( Form( "dd5 = %f < 0", dd5_ ) ); return false; }
// Centre of mass system kinematics (theta4 and phi4)
pt4_ = sqrt( dd5_/s_ )/p_cm_;
sin_theta4_ = pt4_/pc4_;
if ( sin_theta4_ > 1. ) { InWarning( Form( "st4 = %f > 1", sin_theta4_ ) ); return false; }
cos_theta4_ = sqrt( 1.-sin_theta4_*sin_theta4_ );
if ( ep1_*ec4_ < p14_ ) cos_theta4_ *= -1.;
al4_ = 1.-cos_theta4_;
be4_ = 1.+cos_theta4_;
if (cos_theta4_<0.) be4_ = sin_theta4_*sin_theta4_/al4_;
else al4_ = sin_theta4_*sin_theta4_/be4_;
DebuggingInsideLoop( Form( "ct4 = %f\n\tal4 = %f, be4 = %f", cos_theta4_, al4_, be4_ ) );
const double rr = sqrt( -gram_/s_ )/( p_cm_*pt4_ );
const double sin_phi3 = rr / pt3,
sin_phi5 = -rr / pt5;
if ( fabs( sin_phi3 ) > 1. ) { InWarning( Form( "sin(phi_3) = %e while it must be in [-1 ; 1]", sin_phi3 ) ); return false; }
if ( fabs( sin_phi5 ) > 1. ) { InWarning( Form( "sin(phi_5) = %e while it must be in [-1 ; 1]", sin_phi5 ) ); return false; }
const double cos_phi3 = -sqrt( 1.-sin_phi3*sin_phi3 ),
cos_phi5 = -sqrt( 1.-sin_phi5*sin_phi5 );
p3_lab_ = Particle::Momentum( pp3*sin_theta3*cos_phi3, pp3*sin_theta3*sin_phi3, pp3*ct3, ep3 );
p5_lab_ = Particle::Momentum( pp5*sin_theta5*cos_phi5, pp5*sin_theta5*sin_phi5, pp5*ct5, ep5 );
const double a1 = p3_lab_.px()-p5_lab_.px();
DebuggingInsideLoop( Form( "Kinematic quantities\n\t"
"cos(theta3) = %1.4f\tsin(theta3) = %1.4f\tcos( phi3 ) = %1.4f\tsin( phi3 ) = %1.4f\n\t"
"cos(theta4) = %1.4f\tsin(theta4) = %1.4f\n\t"
"cos(theta5) = %1.4f\tsin(theta5) = %1.4f\tcos( phi5 ) = %1.4f\tsin( phi5 ) = %1.4f\n\t"
"a1 = %f",
ct3, sin_theta3, cos_phi3, sin_phi3,
cos_theta4_, sin_theta4_,
ct5, sin_theta5, cos_phi5, sin_phi5, a1 ) );
if ( fabs( pt4_+p3_lab_.px()+p5_lab_.px() ) < fabs( fabs( a1 )-pt4_ ) ) {
DebuggingInsideLoop( Form( "|pp4+pp3*cos(phi3)+pp5*cos(phi5)| < | |a1|-pp4 |\n\t"
"pp4 = %f\tpp5 = %f\n\t"
"cos(phi3) = %f\tcos(phi5) = %f"
"a1 = %f",
pt4_, pt5, cos_phi3, cos_phi5, a1 ) );
return true;
}
if ( a1 < 0. ) p5_lab_.setP( 0, -p5_lab_.px() );
else p3_lab_.setP( 0, -p3_lab_.px() );
return true;
}
double
GamGamLL::computeOutgoingPrimaryParticlesMasses( double x, double outmass, double lepmass, double& dw )
{
- const double mx0 = Particle::massFromPDGId( Particle::Proton )+Particle::massFromPDGId( Particle::PiPlus ); // 1.07
+ const double mx0 = ParticleProperties::mass( Proton )+ParticleProperties::mass( PiPlus ); // 1.07
const Kinematics::Limits mx_limits = cuts_.cuts.remnants[Cuts::mass];
const double wx2min = pow( std::max( mx0, mx_limits.min() ), 2 ),
wx2max = pow( std::min( sqs_-outmass-2.*lepmass, mx_limits.max() ), 2 );
double mx2 = 0., dmx2 = 0.;
Map( x, wx2min, wx2max, mx2, dmx2, "mx2" );
DebuggingInsideLoop( Form( "mX^2 in range (%f, %f), x = %f\n\t"
"mX^2 = %f, d(mX^2) = %f\n\t"
"mX = %f, d(mX) = %f", wx2min, wx2max, x, mx2, dmx2, sqrt( mx2 ), sqrt( dmx2 ) ) );
dw = sqrt( dmx2 );
return sqrt( mx2 );
}
void
GamGamLL::beforeComputeWeight()
{
if ( !GenericProcess::is_point_set_ ) return;
const Particle& p1 = event_->getOneByRole( Particle::IncomingBeam1 ),
&p2 = event_->getOneByRole( Particle::IncomingBeam2 );
ep1_ = p1.energy();
ep2_ = p2.energy();
Ml2_ = event_->getByRole( Particle::CentralSystem )[0].mass2();
switch ( cuts_.mode ) {
case Kinematics::ElectronProton: default:
{ InError( "Case not yet supported!" ); } break;
case Kinematics::ElasticElastic:
dw31_ = dw52_ = 0.; break;
case Kinematics::InelasticElastic: {
const double m = computeOutgoingPrimaryParticlesMasses( x( 7 ), p1.mass(), sqrt( Ml2_ ), dw31_ );
event_->getOneByRole( Particle::OutgoingBeam1 ).setMass( m );
- event_->getOneByRole( Particle::OutgoingBeam2 ).setMass( Particle::massFromPDGId( p2.pdgId() ) );
+ event_->getOneByRole( Particle::OutgoingBeam2 ).setMass( ParticleProperties::mass( p2.pdgId() ) );
} break;
case Kinematics::ElasticInelastic: {
const double m = computeOutgoingPrimaryParticlesMasses( x( 7 ), p2.mass(), sqrt( Ml2_ ), dw52_ );
- event_->getOneByRole( Particle::OutgoingBeam1 ).setMass( Particle::massFromPDGId( p1.pdgId() ) );
+ event_->getOneByRole( Particle::OutgoingBeam1 ).setMass( ParticleProperties::mass( p1.pdgId() ) );
event_->getOneByRole( Particle::OutgoingBeam2 ).setMass( m );
} break;
case Kinematics::InelasticInelastic: {
const double mx = computeOutgoingPrimaryParticlesMasses( x( 7 ), p2.mass(), sqrt( Ml2_ ), dw31_ );
event_->getOneByRole( Particle::OutgoingBeam1 ).setMass( mx );
const double my = computeOutgoingPrimaryParticlesMasses( x( 8 ), p1.mass(), sqrt( Ml2_ ), dw52_ );
event_->getOneByRole( Particle::OutgoingBeam2 ).setMass( my );
} break;
}
MX_ = event_->getOneByRole( Particle::OutgoingBeam1 ).mass();
MY_ = event_->getOneByRole( Particle::OutgoingBeam2 ).mass();
MX2_ = MX_*MX_;
MY2_ = MY_*MY_;
}
double
GamGamLL::computeWeight()
{
if ( !is_outgoing_state_set_ ) { InWarning( "Output state not set!" ); return 0.; }
DebuggingInsideLoop( Form( "sqrt(s)=%f\n\tm(X1)=%f\tm(X2)=%f", sqs_, MX_, MY_ ) );
Kinematics::Limits& w_limits = cuts_.cuts.initial[Cuts::w];
if ( !w_limits.hasMax() ) w_limits.max() = s_;
// The minimal energy for the central system is its outgoing leptons' mass energy (or wmin_ if specified)
const double wmin = std::max( 4.*Ml2_, w_limits.min() );
// The maximal energy for the central system is its CM energy with the outgoing particles' mass energy substracted (or _wmax if specified)
const double wmax = std::min( pow( sqs_-MX_-MY_, 2 ), w_limits.max() );
DebuggingInsideLoop( Form( "wmin = %f\n\twmax = %f\n\twmax/wmin = %f", wmin, wmax, wmax/wmin ) );
// compute the two-photon energy for this point
w4_ = 0.;
double dw4 = 0.;
Map( x( 4 ), wmin, wmax, w4_, dw4, "w4" );
Map( x( 4 ), wmin, wmax, w4_, dw4, "w4" );
mc4_ = sqrt( w4_ );
DebuggingInsideLoop( Form( "Computed value for w4 = %f -> mc4 = %f", w4_, mc4_ ) );
if ( !orient() ) return 0.;
if ( jacobian_ == 0. ) { InWarning( Form( "dj = %f", jacobian_ ) ); return 0.; }
if ( t1_>0. ) { InWarning( Form( "t1 = %f > 0", t1_ ) ); return 0.; }
if ( t2_>0. ) { InWarning( Form( "t2 = %f > 0", t2_ ) ); return 0.; }
const double ecm6 = w4_ / ( 2.*mc4_ ),
pp6cm = sqrt( ecm6*ecm6-Ml2_ );
jacobian_ *= dw4*pp6cm/( mc4_*Constants::sconstb*s_ );
// Let the most obscure part of this code begin...
const double e1mp1 = w1_ / ( ep1_+p_cm_ ),
e3mp3 = MX2_ / ( p3_lab_.energy()+p3_lab_.p() );
const double al3 = pow( sin( p3_lab_.theta() ), 2 )/( 1.+( p3_lab_.theta() ) );
// 2-photon system kinematics ?!
const double eg = ( w4_+t1_-t2_ )/( 2.*mc4_ );
double pg = sqrt( eg*eg-t1_ );
const double pgx = -p3_lab_.px()*cos_theta4_-sin_theta4_*( de3_-e1mp1 + e3mp3 + p3_lab_.p()*al3 ),
pgy = -p3_lab_.py(),
pgz = mc4_*de3_/( ec4_+pc4_ )-ec4_*de3_*al4_/mc4_-p3_lab_.px()*ec4_*sin_theta4_/mc4_+ec4_*cos_theta4_/mc4_*( p3_lab_.p()*al3+e3mp3-e1mp1 );
DebuggingInsideLoop( Form( "pg3 = (%f, %f, %f)\n\t"
"pg3^2 = %f",
pgx, pgy, pgz,
sqrt( pgx*pgx+pgy*pgy+pgz*pgz ) ) );
const double pgp = sqrt( pgx*pgx + pgy*pgy ), // outgoing proton (3)'s transverse momentum
pgg = sqrt( pgp*pgp + pgz*pgz ); // outgoing proton (3)'s momentum
if ( pgg > pgp*0.9 && pgg > pg ) { pg = pgg; } //FIXME ???
// Phi angle for the 2-photon system ?!
const double cpg = pgx/pgp,
spg = pgy/pgp;
// Theta angle for the 2-photon system ?!
const double stg = pgp/pg;
const int theta_sign = ( pgz>0. ) ? 1 : -1;
const double ctg = theta_sign*sqrt( 1.-stg*stg );
double xx6 = x( 5 );
const double amap = 0.5 * (w4_-t1_-t2_),
bmap = 0.5 * sqrt( ( pow( w4_-t1_-t2_, 2 )-4.*t1_*t2_ )*( 1.-4.*Ml2_/w4_ ) ),
ymap = ( amap+bmap )/( amap-bmap ),
beta = pow( ymap, 2.*xx6-1. );
xx6 = 0.5 * ( 1. + amap/bmap*( beta-1. )/( beta+1. ) );
xx6 = std::max( 0., std::min( xx6, 1. ) ); // xx6 in [0., 1.]
DebuggingInsideLoop( Form( "amap = %f\n\tbmap = %f\n\tymap = %f\n\tbeta = %f", amap, bmap, ymap, beta ) );
// 3D rotation of the first outgoing lepton wrt the CM system
const double theta6cm = acos( 1.-2.*xx6 );
// match the Jacobian
jacobian_ *= ( amap+bmap*cos( theta6cm ) );
jacobian_ *= ( amap-bmap*cos( theta6cm ) );
jacobian_ /= amap;
jacobian_ /= bmap;
jacobian_ *= log( ymap );
jacobian_ *= 0.5;
DebuggingInsideLoop( Form( "Jacobian = %e", jacobian_ ) );
DebuggingInsideLoop( Form( "ctcm6 = %f\n\tstcm6 = %f", cos( theta6cm ), sin( theta6cm ) ) );
const double phi6cm = 2.*M_PI*x( 6 );
// First outgoing lepton's 3-momentum in the centre of mass system
Particle::Momentum p6cm = Particle::Momentum::fromPThetaPhi( pp6cm, theta6cm, phi6cm );
DebuggingInsideLoop( Form( "p3cm6 = (%f, %f, %f)", p6cm.px(), p6cm.py(), p6cm.pz() ) );
const double h1 = stg*p6cm.pz()+ctg*p6cm.px();
const double pc6z = ctg*p6cm.pz()-stg*p6cm.px(), pc6x = cpg*h1-spg*p6cm.py();
const double qcx = 2.*pc6x, qcz = 2.*pc6z;
// qcy == QCY is never defined
const double el6 = ( ec4_*ecm6+pc4_*pc6z ) / mc4_,
h2 = ( ec4_*pc6z+pc4_*ecm6 ) / mc4_;
DebuggingInsideLoop( Form( "h1 = %f\n\th2 = %f", h1, h2 ) );
// first outgoing lepton's 3-momentum
const double p6x = cos_theta4_*pc6x+sin_theta4_*h2,
p6y = cpg*p6cm.py()+spg*h1,
p6z = cos_theta4_*h2-sin_theta4_*pc6x;
// first outgoing lepton's kinematics
p6_cm_ = Particle::Momentum( p6x, p6y, p6z, el6 );
DebuggingInsideLoop( Form( "E6(cm) = %f\n\tP6(cm) = (%f, %f, %f)", el6, p6x, p6y, p6z ) );
const double hq = ec4_*qcz/mc4_;
const Particle::Momentum qve(
cos_theta4_*qcx+sin_theta4_*hq,
2.*p6y,
cos_theta4_*hq-sin_theta4_*qcx,
pc4_*qcz/mc4_ // energy
);
// Available energy for the second lepton is the 2-photon system's energy with the first lepton's energy removed
const double el7 = ec4_-el6;
DebuggingInsideLoop( Form( "Outgoing kinematics\n\t"
" first outgoing lepton: p = %f, E = %f\n\t"
"second outgoing lepton: p = %f, E = %f",
p6_cm_.p(), p6_cm_.energy(), p7_cm_.p(), p6_cm_.energy() ) );
// Second outgoing lepton's 3-momentum
const double p7x = -p6x + pt4_,
p7y = -p6y,
p7z = -p6z + pc4_*cos_theta4_;
// second outgoing lepton's kinematics
p7_cm_ = Particle::Momentum( p7x, p7y, p7z, el7 );
//p6_cm_ = Particle::Momentum(pl6*st6*cp6, pl6*st6*sp6, pl6*ct6, el6);
//p7_cm_ = Particle::Momentum(pl7*st7*cp7, pl7*st7*sp7, pl7*ct7, el7);
q1dq_ = eg*( 2.*ecm6-mc4_ )-2.*pg*p6cm.pz();
q1dq2_ = ( w4_-t1_-t2_ ) * 0.5;
const double phi3 = p3_lab_.phi(), cos_phi3 = cos( phi3 ), sin_phi3 = sin( phi3 ),
phi5 = p5_lab_.phi(), cos_phi5 = cos( phi5 ), sin_phi5 = sin( phi5 );
bb_ = t1_*t2_+( w4_*pow( sin( theta6cm ), 2 ) + 4.*Ml2_*pow( cos( theta6cm ), 2 ) )*pg*pg;
const double c1 = p3_lab_.pt() * ( qve.px()*sin_phi3 - qve.py()*cos_phi3 ),
c2 = p3_lab_.pt() * ( qve.pz()*ep1_ - qve.energy() *p_cm_ ),
c3 = ( w31_*ep1_*ep1_ + 2.*w1_*de3_*ep1_ - w1_*de3_*de3_ + p3_lab_.pt2()*ep1_*ep1_ ) / ( p3_lab_.energy()*p_cm_ + p3_lab_.pz()*ep1_ );
const double b1 = p5_lab_.pt() * ( qve.px()*sin_phi5 - qve.py()*cos_phi5 ),
b2 = p5_lab_.pt() * ( qve.pz()*ep2_ + qve.energy() *p_cm_ ),
b3 = ( w52_*ep2_*ep2_ + 2.*w2_*de5_*ep2_ - w2_*de5_*de5_ + p5_lab_.pt2()*ep2_*ep2_ ) / ( ep2_*p5_lab_.pz() - p5_lab_.energy()*p_cm_ );
const double r12 = c2*sin_phi3 + qve.py()*c3,
r13 = -c2*cos_phi3 - qve.px()*c3;
const double r22 = b2*sin_phi5 + qve.py()*b3,
r23 = -b2*cos_phi5 - qve.px()*b3;
epsi_ = p12_*c1*b1 + r12*r22 + r13*r23;
g5_ = w1_*c1*c1 + r12*r12 + r13*r13;
g6_ = w2_*b1*b1 + r22*r22 + r23*r23;
a5_ = -( qve.px()*cos_phi3 + qve.py()*sin_phi3 )*p3_lab_.pt()*p1k2_-( ep1_*qve.energy()-p_cm_*qve.pz() )*( cos_phi3*cos_phi5 + sin_phi3*sin_phi5 )*p3_lab_.pt()*p5_lab_.pt() + ( de5_*qve.pz()+qve.energy()*( p_cm_+p5_lab_.pz() ) )*c3;
a6_ = -( qve.px()*cos_phi5 + qve.py()*sin_phi5 )*p5_lab_.pt()*p2k1_-( ep2_*qve.energy()+p_cm_*qve.pz() )*( cos_phi3*cos_phi5 + sin_phi3*sin_phi5 )*p3_lab_.pt()*p5_lab_.pt() + ( de3_*qve.pz()-qve.energy()*( p_cm_-p3_lab_.pz() ) )*b3;
DebuggingInsideLoop( Form( "a5 = %f\n\ta6 = %f", a5_, a6_ ) );
////////////////////////////////////////////////////////////////
// END of GAMGAMLL subroutine in the FORTRAN version
////////////////////////////////////////////////////////////////
const Particle::Momentum cm = event_->getOneByRole( Particle::IncomingBeam1 ).momentum() + event_->getOneByRole( Particle::IncomingBeam2 ).momentum();
////////////////////////////////////////////////////////////////
// INFO from f.f
////////////////////////////////////////////////////////////////
const double gamma = cm.energy() / sqs_, betgam = cm.pz() / sqs_;
//--- kinematics computation for both leptons
p6_cm_.betaGammaBoost( gamma, betgam );
p7_cm_.betaGammaBoost( gamma, betgam );
//--- cut on mass of final hadronic system (MX/Y)
const Kinematics::Limits mx_limits = cuts_.cuts.remnants[Cuts::mass];
if ( cuts_.mode == Kinematics::InelasticElastic || cuts_.mode == Kinematics::InelasticInelastic ) {
if ( mx_limits.hasMin() && MX_ < mx_limits.min() ) return 0.;
if ( mx_limits.hasMax() && MX_ > mx_limits.max() ) return 0.;
}
if ( cuts_.mode == Kinematics::ElasticInelastic || cuts_.mode == Kinematics::InelasticInelastic ) {
if ( mx_limits.hasMin() && MY_ < mx_limits.min() ) return 0.;
if ( mx_limits.hasMax() && MY_ > mx_limits.max() ) return 0.;
}
//--- cut on the proton's Q2 (first photon propagator T1)
const Kinematics::Limits q2_limits = cuts_.cuts.initial[Cuts::q2];
if ( q2_limits.hasMax() && t1_<-q2_limits.max() ) return 0;
if ( q2_limits.hasMin() && t1_>-q2_limits.min() ) return 0.;
//--- cuts on outgoing leptons' kinematics
const Kinematics::Limits m_limits = cuts_.cuts.central[Cuts::mass_sum];
if ( m_limits.hasMin() && ( p6_cm_+p7_cm_ ).mass() < m_limits.min() ) return 0.;
if ( m_limits.hasMax() && ( p6_cm_+p7_cm_ ).mass() > m_limits.max() ) return 0.;
//----- cuts on the individual leptons
const Kinematics::Limits pt_limits = cuts_.cuts.central[Cuts::pt_single];
if ( pt_limits.hasMin() && ( p6_cm_.pt() < pt_limits.min() || p7_cm_.pt() < pt_limits.min() ) ) return 0.;
if ( pt_limits.hasMax() && ( p6_cm_.pt() > pt_limits.max() || p7_cm_.pt() > pt_limits.max() ) ) return 0.;
const Kinematics::Limits energy_limits = cuts_.cuts.central[Cuts::energy_single];
if ( energy_limits.hasMin() && ( p6_cm_.energy() < energy_limits.min() || p7_cm_.energy() < energy_limits.min() ) ) return 0.;
if ( energy_limits.hasMax() && ( p6_cm_.energy() > energy_limits.max() || p7_cm_.energy() > energy_limits.max() ) ) return 0.;
const Kinematics::Limits eta_limits = cuts_.cuts.central[Cuts::eta_single];
if ( eta_limits.hasMin() && ( p6_cm_.eta() < eta_limits.min() || p7_cm_.eta() < eta_limits.min() ) ) return 0.;
if ( eta_limits.hasMax() && ( p6_cm_.eta() > eta_limits.max() || p7_cm_.eta() > eta_limits.max() ) ) return 0.;
//--- compute the structure functions factors
switch ( cuts_.mode ) { // inherited from CDF version
case Kinematics::ElectronProton: default: jacobian_ *= periPP( 1, 2 ); break; // ep case
case Kinematics::ElasticElastic: jacobian_ *= periPP( 2, 2 ); break; // elastic case
case Kinematics::InelasticElastic: jacobian_ *= periPP( 3, 2 )*( dw31_*dw31_ ); break;
case Kinematics::ElasticInelastic: jacobian_ *= periPP( 3, 2 )*( dw52_*dw52_ ); break; // single-dissociative case
case Kinematics::InelasticInelastic: jacobian_ *= periPP( 3, 3 )*( dw31_*dw31_ )*( dw52_*dw52_ ); break; // double-dissociative case
}
//--- compute the event weight using the Jacobian
return Constants::GeV2toBarn*jacobian_;
}
void
GamGamLL::fillKinematics( bool )
{
const Particle::Momentum cm = event_->getOneByRole( Particle::IncomingBeam1 ).momentum() + event_->getOneByRole( Particle::IncomingBeam2 ).momentum();
const double gamma = cm.energy()/sqs_, betgam = cm.pz()/sqs_;
Particle::Momentum plab_ip1 = Particle::Momentum( 0., 0., p_cm_, ep1_ ).betaGammaBoost( gamma, betgam );
Particle::Momentum plab_ip2 = Particle::Momentum( 0., 0., -p_cm_, ep2_ ).betaGammaBoost( gamma, betgam );
p3_lab_.betaGammaBoost( gamma, betgam );
p5_lab_.betaGammaBoost( gamma, betgam );
//----- needed to parametrise a random rotation around z-axis
const int rany = ( rand() >= RAND_MAX*0.5 ) ? 1 : -1,
ransign = ( rand() >= RAND_MAX*0.5 ) ? 1 : -1;
const double ranphi = ( rand()/RAND_MAX*0.5 )*2.*M_PI;
Particle::Momentum plab_ph1 = ( plab_ip1-p3_lab_ ).rotatePhi( ranphi, rany );
Particle::Momentum plab_ph2 = ( plab_ip2-p5_lab_ ).rotatePhi( ranphi, rany );
p3_lab_.rotatePhi( ranphi, rany );
p5_lab_.rotatePhi( ranphi, rany );
p6_cm_.rotatePhi( ranphi, rany );
p7_cm_.rotatePhi( ranphi, rany );
/*if ( symmetrise_ && rand() >= .5*RAND_MAX ) {
p6_cm_.mirrorZ();
p7_cm_.mirrorZ();
}*/
//----- incoming protons
event_->getOneByRole( Particle::IncomingBeam1 ).setMomentum( plab_ip1 );
event_->getOneByRole( Particle::IncomingBeam2 ).setMomentum( plab_ip2 );
//----- first outgoing proton
Particle& op1 = event_->getOneByRole( Particle::OutgoingBeam1 );
op1.setMomentum( p3_lab_ );
switch ( cuts_.mode ) {
case Kinematics::ElasticElastic:
case Kinematics::ElasticInelastic:
default:
op1.setStatus( Particle::FinalState ); // stable proton
break;
case Kinematics::InelasticElastic:
case Kinematics::InelasticInelastic:
op1.setStatus( Particle::Unfragmented ); // fragmenting remnants
op1.setMass( MX_ );
break;
}
//----- second outgoing proton
Particle& op2 = event_->getOneByRole( Particle::OutgoingBeam2 );
op2.setMomentum( p5_lab_ );
switch ( cuts_.mode ) {
case Kinematics::ElasticElastic:
case Kinematics::InelasticElastic:
default:
op2.setStatus( Particle::FinalState ); // stable proton
break;
case Kinematics::ElasticInelastic:
case Kinematics::InelasticInelastic:
op2.setStatus( Particle::Unfragmented ); // fragmenting remnants
op2.setMass( MY_ );
break;
}
//----- first incoming photon
Particle& ph1 = event_->getOneByRole( Particle::Parton1 );
ph1.setMomentum( plab_ph1 );
ph1.setStatus( Particle::Incoming );
//----- second incoming photon
Particle& ph2 = event_->getOneByRole( Particle::Parton2 );
ph2.setMomentum( plab_ph2 );
ph2.setStatus( Particle::Incoming );
Particles& central_system = event_->getByRole( Particle::CentralSystem );
//----- first outgoing lepton
Particle& ol1 = central_system[0];
ol1.setPdgId( ol1.pdgId(), ransign );
ol1.setMomentum( p6_cm_ );
ol1.setStatus( Particle::FinalState );
//----- second outgoing lepton
Particle& ol2 = central_system[1];
ol2.setPdgId( ol2.pdgId(), -ransign );
ol2.setMomentum( p7_cm_ );
ol2.setStatus( Particle::FinalState );
//----- intermediate two-lepton system
event_->getOneByRole( Particle::Intermediate ).setMomentum( p6_cm_+p7_cm_ );
}
double
GamGamLL::periPP( int nup_, int ndown_ )
{
DebuggingInsideLoop( Form( " Nup = %d\n\tNdown = %d", nup_, ndown_ ) );
FormFactors fp1, fp2;
GenericProcess::formFactors( -t1_, -t2_, fp1, fp2 );
DebuggingInsideLoop( Form( "u1 = %f\n\tu2 = %f\n\tv1 = %f\n\tv2 = %f", fp1.FM, fp1.FE, fp2.FM, fp2.FE ) );
const double qqq = q1dq_*q1dq_,
qdq = 4.*Ml2_-w4_;
const double t11 = 64. *( bb_*( qqq-g4_-qdq*( t1_+t2_+2.*Ml2_ ) )-2.*( t1_+2.*Ml2_ )*( t2_+2.*Ml2_ )*qqq ) * t1_*t2_, // magnetic-magnetic
t12 = 128.*( -bb_*( dd2_+g6_ )-2.*( t1_+2.*Ml2_ )*( sa2_*qqq+a6_*a6_ ) ) * t1_, // electric-magnetic
t21 = 128.*( -bb_*( dd4_+g5_ )-2.*( t2_+2.*Ml2_ )*( sa1_*qqq+a5_*a5_ ) ) * t2_, // magnetic-electric
t22 = 512.*( bb_*( delta_*delta_-gram_ )-pow( epsi_-delta_*( qdq+q1dq2_ ), 2 )-sa1_*a6_*a6_-sa2_*a5_*a5_-sa1_*sa2_*qqq ); // electric-electric
const double peripp = ( fp1.FM*fp2.FM*t11 + fp1.FE*fp2.FM*t21 + fp1.FM*fp2.FE*t12 + fp1.FE*fp2.FE*t22 ) / pow( 2.*t1_*t2_*bb_, 2 );
DebuggingInsideLoop( Form( "t11 = %5.2f\tt12 = %5.2f\n\t"
"t21 = %5.2f\tt22 = %5.2f\n\t"
"=> PeriPP = %e", t11, t12, t21, t22, peripp ) );
return peripp;
}
diff --git a/CepGen/Processes/GenericKTProcess.cpp b/CepGen/Processes/GenericKTProcess.cpp
index 82e35a2..01c72f1 100644
--- a/CepGen/Processes/GenericKTProcess.cpp
+++ b/CepGen/Processes/GenericKTProcess.cpp
@@ -1,269 +1,269 @@
#include "GenericKTProcess.h"
#include "CepGen/StructureFunctions/StructureFunctionsBuilder.h"
#include "CepGen/Core/Exception.h"
namespace CepGen
{
namespace Process
{
GenericKTProcess::GenericKTProcess( const std::string& name,
const std::string& description,
const unsigned int& num_user_dimensions,
- const std::array<Particle::ParticleCode,2>& partons,
- const std::vector<Particle::ParticleCode>& central ) :
+ const std::array<ParticleCode,2>& partons,
+ const std::vector<ParticleCode>& central ) :
GenericProcess( name, description+" (kT-factorisation approach)" ),
kNumUserDimensions( num_user_dimensions ),
kIntermediateParts( partons ), kProducedParts( central )
{}
GenericKTProcess::~GenericKTProcess()
{}
void
GenericKTProcess::prepareKTKinematics()
{
DebuggingInsideLoop("Dummy kinematics prepared!");
}
void
GenericKTProcess::addEventContent()
{
GenericProcess::setEventContent(
{ // incoming state
- { Particle::IncomingBeam1, Particle::Proton },
- { Particle::IncomingBeam2, Particle::Proton },
+ { Particle::IncomingBeam1, Proton },
+ { Particle::IncomingBeam2, Proton },
{ Particle::Parton1, kIntermediateParts[0] },
{ Particle::Parton2, kIntermediateParts[1] }
},
{ // outgoing state
- { Particle::OutgoingBeam1, { Particle::Proton } },
- { Particle::OutgoingBeam2, { Particle::Proton } },
+ { Particle::OutgoingBeam1, { Proton } },
+ { Particle::OutgoingBeam2, { Proton } },
{ Particle::CentralSystem, kProducedParts }
}
);
setExtraContent();
}
unsigned int
GenericKTProcess::numDimensions( const Kinematics::ProcessMode& process_mode ) const
{
switch ( process_mode ) {
default:
case Kinematics::ElasticElastic: return kNumRequiredDimensions+kNumUserDimensions;
case Kinematics::ElasticInelastic:
case Kinematics::InelasticElastic: return kNumRequiredDimensions+kNumUserDimensions+1;
case Kinematics::InelasticInelastic: return kNumRequiredDimensions+kNumUserDimensions+2;
}
}
void
GenericKTProcess::addPartonContent()
{
// Incoming partons
qt1_ = exp( log_qmin_+( log_qmax_-log_qmin_ )*x( 0 ) );
qt2_ = exp( log_qmin_+( log_qmax_-log_qmin_ )*x( 1 ) );
phi_qt1_ = 2.*M_PI*x( 2 );
phi_qt2_ = 2.*M_PI*x( 3 );
DebuggingInsideLoop( Form( "photons transverse virtualities (qt):\n\t"
" mag = %f / %f (%.2f < log(qt) < %.2f)\n\t"
" phi = %f / %f",
qt1_, qt2_, log_qmin_, log_qmax_, phi_qt1_, phi_qt2_ ) );
}
void
GenericKTProcess::setKinematics( const Kinematics& kin )
{
cuts_ = kin;
log_qmin_ = -10.; // FIXME //log_qmin_ = std::log( std::sqrt( cuts_.q2min ) );
log_qmax_ = log( cuts_.cuts.initial[Cuts::qt].max() );
}
double
GenericKTProcess::computeWeight()
{
addPartonContent();
prepareKTKinematics();
computeOutgoingPrimaryParticlesMasses();
const double jac = computeJacobian(),
integrand = computeKTFactorisedMatrixElement(),
weight = jac*integrand;
DebuggingInsideLoop( Form( "Jacobian = %f\n\tIntegrand = %f\n\tdW = %f", jac, integrand, weight ) );
return weight;
}
void
GenericKTProcess::computeOutgoingPrimaryParticlesMasses()
{
const unsigned int op_index = kNumRequiredDimensions+kNumUserDimensions;
const Kinematics::Limits remn_mx_cuts = cuts_.cuts.remnants[Cuts::mass];
switch ( cuts_.mode ) {
case Kinematics::ElectronProton: default: {
InError( "This kT factorisation process is intended for p-on-p collisions! Aborting!" );
exit( 0 ); } break;
case Kinematics::ElasticElastic: {
MX_ = event_->getOneByRole( Particle::IncomingBeam1 ).mass();
MY_ = event_->getOneByRole( Particle::IncomingBeam2 ).mass();
} break;
case Kinematics::ElasticInelastic: {
const double mx_min = remn_mx_cuts.min(), mx_range = remn_mx_cuts.range();
MX_ = event_->getOneByRole( Particle::IncomingBeam1 ).mass();
MY_ = mx_min + mx_range*x( op_index );
} break;
case Kinematics::InelasticElastic: {
const double mx_min = remn_mx_cuts.min(), mx_range = remn_mx_cuts.range();
MX_ = mx_min + mx_range*x( op_index );
MY_ = event_->getOneByRole( Particle::IncomingBeam2 ).mass();
} break;
case Kinematics::InelasticInelastic: {
const double mx_min = remn_mx_cuts.min(), mx_range = remn_mx_cuts.range();
MX_ = mx_min + mx_range*x( op_index );
MY_ = mx_min + mx_range*x( op_index+1 );
} break;
}
DebuggingInsideLoop( Form( "outgoing remnants invariant mass: %f / %f (%.2f < M(X/Y) < %.2f)", MX_, MY_, remn_mx_cuts.min(), remn_mx_cuts.max() ) );
}
void
GenericKTProcess::computeIncomingFluxes( double x1, double q1t2, double x2, double q2t2 )
{
flux1_ = flux2_ = 0.;
switch ( cuts_.mode ) {
case Kinematics::ElasticElastic:
flux1_ = elasticFlux( x1, q1t2 );
flux2_ = elasticFlux( x2, q2t2 );
break;
case Kinematics::ElasticInelastic:
flux1_ = elasticFlux( x1, q1t2 );
flux2_ = inelasticFlux( x2, q2t2, MY_ );
break;
case Kinematics::InelasticElastic:
flux1_ = inelasticFlux( x1, q1t2, MX_ );
flux2_ = elasticFlux( x2, q2t2 );
break;
case Kinematics::InelasticInelastic:
flux1_ = inelasticFlux( x1, q1t2, MX_ );
flux2_ = inelasticFlux( x2, q2t2, MY_ );
break;
default: return;
}
flux1_ = std::max( flux1_, 1.e-20 );
flux2_ = std::max( flux2_, 1.e-20 );
DebuggingInsideLoop( Form( "Form factors: %e / %e", flux1_, flux2_ ) );
}
void
GenericKTProcess::fillKinematics( bool )
{
fillPrimaryParticlesKinematics();
fillCentralParticlesKinematics();
}
void
GenericKTProcess::fillPrimaryParticlesKinematics()
{
//=================================================================
// outgoing protons
//=================================================================
Particle& op1 = event_->getOneByRole( Particle::OutgoingBeam1 ),
&op2 = event_->getOneByRole( Particle::OutgoingBeam2 );
op1.setMomentum( PX_ );
op2.setMomentum( PY_ );
switch ( cuts_.mode ) {
case Kinematics::ElasticElastic:
op1.setStatus( Particle::FinalState );
op2.setStatus( Particle::FinalState );
break;
case Kinematics::ElasticInelastic:
op1.setStatus( Particle::FinalState );
op2.setStatus( Particle::Unfragmented ); op2.setMass( MY_ );
break;
case Kinematics::InelasticElastic:
op1.setStatus( Particle::Unfragmented ); op1.setMass( MX_ );
op2.setStatus( Particle::FinalState );
break;
case Kinematics::InelasticInelastic:
op1.setStatus( Particle::Unfragmented ); op1.setMass( MX_ );
op2.setStatus( Particle::Unfragmented ); op2.setMass( MY_ );
break;
default: { FatalError( "This kT factorisation process is intended for p-on-p collisions! Aborting!" ); } break;
}
//=================================================================
// incoming partons (photons, pomerons, ...)
//=================================================================
//FIXME ensure the validity of this approach
Particle& g1 = event_->getOneByRole( Particle::Parton1 ),
&g2 = event_->getOneByRole( Particle::Parton2 );
g1.setMomentum( event_->getOneByRole( Particle::IncomingBeam1 ).momentum()-PX_, true );
g1.setStatus( Particle::Incoming );
g2.setMomentum( event_->getOneByRole( Particle::IncomingBeam2 ).momentum()-PY_, true );
g2.setStatus( Particle::Incoming );
}
double
GenericKTProcess::minimalJacobian() const
{
double jac = 1.;
jac *= ( log_qmax_-log_qmin_ )*qt1_; // d(q1t) . q1t
jac *= ( log_qmax_-log_qmin_ )*qt2_; // d(q2t) . q2t
jac *= 2.*M_PI; // d(phi1)
jac *= 2.*M_PI; // d(phi2)
const double mx_range = cuts_.cuts.remnants.at( Cuts::mass ).range();
switch ( cuts_.mode ) {
case Kinematics::ElasticElastic: default: break;
case Kinematics::ElasticInelastic: jac *= 2.* mx_range * MY_; break;
case Kinematics::InelasticElastic: jac *= 2.* mx_range * MX_; break;
case Kinematics::InelasticInelastic: jac *= 2.* mx_range * MX_;
jac *= 2.* mx_range * MY_; break;
} // d(mx/y**2)
return jac;
}
double
GenericKTProcess::elasticFlux( double x, double kt2 )
{
- const double mp = Particle::massFromPDGId( Particle::Proton ), mp2 = mp*mp;
+ const double mp = ParticleProperties::mass( Proton ), mp2 = mp*mp;
const double Q2_min = x*x*mp2/( 1.-x ), Q2_ela = Q2_min + kt2/( 1.-x );
const FormFactors ela = FormFactors::ProtonElastic( Q2_ela );
const double ela1 = ( 1.-x )*( 1.-Q2_min/Q2_ela );
const double ela2 = ela.FE;
//const double ela3 = 1.-( Q2_ela-kt2 )/Q2_ela;
const double f_ela = Constants::alphaEM/M_PI/kt2*( ela1*ela2 + 0.5*x*x*ela.FM );
return f_ela * ( 1.-x ) * kt2 / Q2_ela;
}
double
GenericKTProcess::inelasticFlux( double x, double kt2, double mx )
{
- const double mx2 = mx*mx, mp = Particle::massFromPDGId( Particle::Proton ), mp2 = mp*mp;
+ const double mx2 = mx*mx, mp = ParticleProperties::mass( Proton ), mp2 = mp*mp;
// F2 structure function
const double Q2min = 1. / ( 1.-x )*( x*( mx2-mp2 ) + x*x*mp2 ),
Q2 = Q2min + kt2 / ( 1.-x );
float xbj = Q2 / ( Q2 + mx2 - mp2 );
const StructureFunctions sf = StructureFunctionsBuilder::get( cuts_.structure_functions, Q2, xbj );
// Longitudinal/transverse virtual photon cross section R
// from Sibirtsev and Blunden (Phys Rev C 88,065202 (2013))
const double R = 0.014 * Q2 * ( exp( -0.07*Q2 ) + 41.*exp( -0.8*Q2 ) );
const double F1 = sf.F2 * ( 1.+4*xbj*xbj*mp2/Q2 )/( 1.+R )/( 2.*xbj );
const double ine1 = ( 1.-x )*( 1.-Q2min / Q2 );
const double f_D = sf.F2/( Q2 + mx2 - mp2 ) * ine1, f_C= 2.*F1/Q2;
const double f_ine = Constants::alphaEM/M_PI/kt2*( f_D + 0.5*x*x*f_C );
return f_ine * ( 1.-x ) * kt2 / Q2;
}
}
}
diff --git a/CepGen/Processes/GenericKTProcess.h b/CepGen/Processes/GenericKTProcess.h
index 87f1d1b..b32275a 100644
--- a/CepGen/Processes/GenericKTProcess.h
+++ b/CepGen/Processes/GenericKTProcess.h
@@ -1,118 +1,118 @@
#ifndef CepGen_Processes_GenericKTProcess_h
#define CepGen_Processes_GenericKTProcess_h
#include "GenericProcess.h"
namespace CepGen
{
namespace Process
{
/**
* A generic kT-factorisation process.
* First 4 dimensions of the phase space are required for the incoming partons' virtualities (radial and azimuthal coordinates)
* \brief Class template to define any kT-factorisation process
* \author Laurent Forthomme <laurent.forthomme@cern.ch>
* \date Apr 2016
*/
class GenericKTProcess : public GenericProcess
{
public:
/**
* \brief Class constructor
* \param[in] name Generic process name
* \param[in] description Human-readable kT-factorised process name
* \param[in] num_user_dimensions Number of additional dimensions required for the user process
* \param[in] partons First and second incoming parton
* \param[in] output Produced final state particles
*/
GenericKTProcess( const std::string& name,
const std::string& description,
const unsigned int& num_user_dimensions,
- const std::array<Particle::ParticleCode,2>& partons,
- const std::vector<Particle::ParticleCode>& output );
+ const std::array<ParticleCode,2>& partons,
+ const std::vector<ParticleCode>& output );
~GenericKTProcess();
/// Populate the event content with the generated process' topology
void addEventContent() override;
/// Retrieve the total number of dimensions on which the integration is being performet
/// \param[in] proc_mode_ Kinematics case considered
unsigned int numDimensions( const Kinematics::ProcessMode& proc_mode_ ) const override;
/// Retrieve the event weight in the phase space
double computeWeight() override;
/// Populate the event content with the generated process' kinematics
void fillKinematics( bool ) override;
protected:
/// Set the kinematics associated to the phase space definition
void setKinematics( const Kinematics& kin ) override;
/// Set the kinematics of the central system before any point computation
virtual void setExtraContent() {}
virtual void prepareKTKinematics();
/// Minimal Jacobian weight of the point considering a kT factorisation
double minimalJacobian() const;
/// Jacobian weight of the point in the phase space for integration
virtual double computeJacobian() = 0;
/// kT-factorised matrix element (event weight)
/// \return Weight of the point in the phase space to the integral
virtual double computeKTFactorisedMatrixElement() = 0;
/// Compute the invariant masses of the outgoing protons (or remnants)
void computeOutgoingPrimaryParticlesMasses();
/// Compute the unintegrated photon fluxes (for inelastic distributions, interpolation on double logarithmic grid)
void computeIncomingFluxes( double, double, double, double );
/// Set the kinematics of the incoming and outgoing protons (or remnants)
void fillPrimaryParticlesKinematics();
/// Set the kinematics of the outgoing central system
virtual void fillCentralParticlesKinematics() = 0;
/// Get the elastic flux to be expected at a given x_bjorken / kT
/// \param[in] x Bjorken x
/// \param[in] kt2 Transverse 2-momentum \f$\mathbf{q}_{\mathrm{T}}^2\f$ of the incoming photon
double elasticFlux( double x, double kt2 );
/// Get the inelastic flux to be expected at a given x_bjorken / kT
/// \param[in] x Bjorken x
/// \param[in] kt2 Transverse 2-momentum \f$\mathbf{q}_{\mathrm{T}}^2\f$ of the incoming photon
/// \param[in] mx Outgoing diffractive proton mass
double inelasticFlux( double x, double kt2, double mx );
/// Retrieve a component of the phase space point for the kT-factorised process
inline double xkt( const unsigned int i ) const { return x( kNumRequiredDimensions + i ); }
/// Minimal log-virtuality of the intermediate parton
double log_qmin_;
/// Maximal log-virtuality of the intermediate parton
double log_qmax_;
/// Virtuality of the first intermediate parton (photon, pomeron, ...)
double qt1_;
/// Azimuthal rotation of the first intermediate parton's transverse virtuality
double phi_qt1_;
/// Virtuality of the second intermediate parton (photon, pomeron, ...)
double qt2_;
/// Azimuthal rotation of the second intermediate parton's transverse virtuality
double phi_qt2_;
/// First outgoing proton
Particle::Momentum PX_;
/// Second outgoing proton
Particle::Momentum PY_;
/// First incoming parton's flux
double flux1_;
/// Second incoming parton's flux
double flux2_;
private:
void addPartonContent();
static constexpr unsigned int kNumRequiredDimensions = 4;
/// Number of additional dimensions required for the user process
/// (in addition to the 4 required for the two partons' transverse momenta)
unsigned int kNumUserDimensions;
/// First and second intermediate parton (photon, pomeron, ...)
- std::array<Particle::ParticleCode,2> kIntermediateParts;
+ std::array<ParticleCode,2> kIntermediateParts;
/// Type of particles produced in the final state
- std::vector<Particle::ParticleCode> kProducedParts;
+ std::vector<ParticleCode> kProducedParts;
};
}
}
#endif
diff --git a/CepGen/Processes/GenericProcess.cpp b/CepGen/Processes/GenericProcess.cpp
index 66973c8..e977088 100644
--- a/CepGen/Processes/GenericProcess.cpp
+++ b/CepGen/Processes/GenericProcess.cpp
@@ -1,185 +1,186 @@
#include "GenericProcess.h"
#include "CepGen/Core/Exception.h"
+#include "CepGen/Physics/ParticleProperties.h"
namespace CepGen
{
namespace Process
{
GenericProcess::GenericProcess( const std::string& name, const std::string& description, bool has_event ) :
event_( std::shared_ptr<Event>( new Event ) ),
is_point_set_( false ), is_incoming_state_set_( false ), is_outgoing_state_set_( false ), is_kinematics_set_( false ),
name_( name ), description_( description ),
total_gen_time_( 0. ), num_gen_events_( 0 ), has_event_( has_event )
{}
GenericProcess::~GenericProcess()
{}
void
GenericProcess::setPoint( const unsigned int ndim, double* x )
{
if ( ndim != x_.size() ) x_.resize( ndim );
x_ = std::vector<double>( x, x+ndim );
is_point_set_ = true;
if ( Logger::get().level>=Logger::DebugInsideLoop ) { dumpPoint(); }
}
void
GenericProcess::prepareKinematics()
{
if ( !isKinematicsDefined() ) return; // FIXME dump some information...
const Particle ib1 = event_->getOneByRole( Particle::IncomingBeam1 ),
ib2 = event_->getOneByRole( Particle::IncomingBeam2 );
sqs_ = CMEnergy( ib1, ib2 );
s_ = sqs_*sqs_;
w1_ = ib1.mass2();
w2_ = ib2.mass2();
Debugging( Form( "Kinematics successfully prepared! sqrt(s) = %.2f", sqs_ ) );
}
void
GenericProcess::dumpPoint()
{
std::ostringstream os;
for ( unsigned int i=0; i<x_.size(); i++ ) {
os << Form( " x(%2d) = %8.6f\n\t", i, x_[i] );
}
Information( Form( "Number of integration parameters: %d\n\t"
"%s", x_.size(), os.str().c_str() ) );
}
void
GenericProcess::setEventContent( const IncomingState& is, const OutgoingState& os )
{
event_->clear();
//----- add the particles in the event
//--- incoming state
for ( IncomingState::const_iterator ip=is.begin(); ip!=is.end(); ip++ ) {
Particle& p = event_->addParticle( ip->first );
p.setPdgId( ip->second );
}
//--- central system (if not already there)
IncomingState::const_iterator central_system = is.find( Particle::CentralSystem );
if ( central_system == is.end() ) {
Particle& p = event_->addParticle( Particle::Intermediate );
- p.setPdgId( Particle::invalidParticle );
+ p.setPdgId( invalidParticle );
p.setStatus( Particle::Propagator );
}
//--- outgoing state
for ( OutgoingState::const_iterator op = os.begin(); op != os.end(); ++op ) {
- for ( std::vector<Particle::ParticleCode>::const_iterator it = op->second.begin(); it != op->second.end(); ++it ) {
+ for ( std::vector<ParticleCode>::const_iterator it = op->second.begin(); it != op->second.end(); ++it ) {
Particle& p = event_->addParticle( op->first );
p.setPdgId( *it );
}
}
//----- define the particles parentage
const Particles parts = event_->particles();
for ( Particles::const_iterator p = parts.begin(); p != parts.end(); ++p ) {
Particle& part = event_->getById( p->id() );
switch ( part.role() ) {
case Particle::OutgoingBeam1:
case Particle::Parton1:
part.addMother( event_->getOneByRole( Particle::IncomingBeam1 ) );
break;
case Particle::OutgoingBeam2:
case Particle::Parton2:
part.addMother( event_->getOneByRole( Particle::IncomingBeam2 ) );
break;
case Particle::Intermediate:
part.addMother( event_->getOneByRole( Particle::Parton1 ) );
part.addMother( event_->getOneByRole( Particle::Parton2 ) );
break;
case Particle::CentralSystem:
part.addMother( event_->getOneByRole( Particle::Intermediate ) );
break;
default: break;
}
}
//----- freeze the event as it is
event_->freeze();
}
void
GenericProcess::setIncomingKinematics( const Particle::Momentum& p1, const Particle::Momentum& p2 )
{
event_->getOneByRole( Particle::IncomingBeam1 ).setMomentum( p1 );
event_->getOneByRole( Particle::IncomingBeam2 ).setMomentum( p2 );
}
void
GenericProcess::formFactors( double q1, double q2, FormFactors& fp1, FormFactors& fp2 ) const
{
const double mx2 = MX_*MX_, my2 = MY_*MY_;
switch ( cuts_.mode ) {
case Kinematics::ElectronElectron: {
fp1 = FormFactors::Trivial(); // electron (trivial) form factor
fp2 = FormFactors::Trivial(); // electron (trivial) form factor
} break;
case Kinematics::ProtonElectron: {
fp1 = FormFactors::ProtonElastic( -t1_ ); // proton elastic form factor
fp2 = FormFactors::Trivial(); // electron (trivial) form factor
} break;
case Kinematics::ElectronProton: {
fp1 = FormFactors::Trivial(); // electron (trivial) form factor
fp2 = FormFactors::ProtonElastic( -t2_ ); // proton elastic form factor
} break;
case Kinematics::ElasticElastic: {
fp1 = FormFactors::ProtonElastic( -t1_ ); // proton elastic form factor
fp2 = FormFactors::ProtonElastic( -t2_ ); // proton elastic form factor
} break;
case Kinematics::ElasticInelastic: {
fp1 = FormFactors::ProtonElastic( -t1_ );
fp2 = FormFactors::ProtonInelastic( cuts_.structure_functions, -t2_, w2_, my2 );
} break;
case Kinematics::InelasticElastic: {
fp1 = FormFactors::ProtonInelastic( cuts_.structure_functions, -t1_, w1_, mx2 );
fp2 = FormFactors::ProtonElastic( -t2_ );
} break;
case Kinematics::InelasticInelastic: {
fp1 = FormFactors::ProtonInelastic( cuts_.structure_functions, -t1_, w1_, mx2 );
fp2 = FormFactors::ProtonInelastic( cuts_.structure_functions, -t2_, w2_, my2 );
} break;
}
}
inline bool
GenericProcess::isKinematicsDefined()
{
// check the incoming state
if ( !particles( Particle::IncomingBeam1 ).empty() && !particles( Particle::IncomingBeam2 ).empty() ) {
is_incoming_state_set_ = true;
}
// check the outgoing state
if ( !particles( Particle::OutgoingBeam1 ).empty()
&& !particles( Particle::OutgoingBeam2 ).empty()
&& !particles( Particle::CentralSystem ).empty() ) {
is_outgoing_state_set_ = true;
}
// combine both states
is_kinematics_set_ = is_incoming_state_set_ && is_outgoing_state_set_;
return is_kinematics_set_;
}
std::ostream&
operator<<( std::ostream& os, const GenericProcess& proc )
{
return os << proc.name().c_str();
}
std::ostream&
operator<<( std::ostream& os, const GenericProcess* proc )
{
return os << proc->name().c_str();
}
}
}
diff --git a/CepGen/Processes/GenericProcess.h b/CepGen/Processes/GenericProcess.h
index d60ff1e..2554aed 100644
--- a/CepGen/Processes/GenericProcess.h
+++ b/CepGen/Processes/GenericProcess.h
@@ -1,182 +1,182 @@
#ifndef CepGen_Processes_GenericProcess_h
#define CepGen_Processes_GenericProcess_h
#include "CepGen/Event/Event.h"
#include "CepGen/Physics/Kinematics.h"
#include "CepGen/Physics/FormFactors.h"
#include <vector>
#include <memory>
namespace CepGen
{
/// Location for all physics processes to be generated
namespace Process
{
/// Class template to define any process to compute using this MC integrator/events generator
/// \author Laurent Forthomme <laurent.forthomme@cern.ch>
/// \date Jan 2014
class GenericProcess
{
public:
/// Human-readable format dump of a GenericProcess object
friend std::ostream& operator<<( std::ostream& os, const GenericProcess& proc );
/// Human-readable format dump of a pointer to a GenericProcess object
friend std::ostream& operator<<( std::ostream& os, const GenericProcess* proc );
/// Generic map of particles with their role in the process
- typedef std::map<Particle::Role,Particle::ParticleCode> ParticlesRoleMap;
+ typedef std::map<Particle::Role,ParticleCode> ParticlesRoleMap;
/// Pair of particle with their associated role in the process
- typedef std::pair<Particle::Role,Particle::ParticleCode> ParticleWithRole;
+ typedef std::pair<Particle::Role,ParticleCode> ParticleWithRole;
/// Map of all incoming state particles in the process
typedef ParticlesRoleMap IncomingState;
/// Map of all outgoing particles in the process
- typedef std::map<Particle::Role,std::vector<Particle::ParticleCode> > OutgoingState;
+ typedef std::map<Particle::Role,std::vector<ParticleCode> > OutgoingState;
/// Default constructor for an undefined process
/// \param[in] name Process name
/// \param[in] description Human-readable description of the process
/// \param[in] has_event Do we generate the associated event structure?
GenericProcess( const std::string& name, const std::string& description="<invalid process>", bool has_event=true );
virtual ~GenericProcess();
/// Restore the Event object to its initial state
inline void clearEvent() { event_->restore(); }
/// Set the kinematics of the incoming state particles
void setIncomingKinematics( const Particle::Momentum& p1, const Particle::Momentum& p2 );
/// Compute the incoming state kinematics
void prepareKinematics();
public:
/// Set the incoming and outgoing state to be expected in the process
inline virtual void addEventContent() {}
/// Prepare the process for its integration over the whole phase space
inline virtual void beforeComputeWeight() {}
/// Compute the weight for this point in the phase-space
virtual double computeWeight() = 0;
/// Fill the Event object with the particles' kinematics
/// \param[in] symmetrise Symmetrise the event? (randomise the production of positively- and negatively-charged outgoing central particles)
virtual void fillKinematics( bool symmetrise=false ) = 0;
/// Return the number of dimensions on which the integration has to be performed
/// \return Number of dimensions on which to integrate
virtual unsigned int numDimensions( const Kinematics::ProcessMode& ) const = 0;
/// Set the list of kinematic cuts to apply on the outgoing particles' final state
/// \param[in] cuts The Cuts object containing the kinematic parameters
inline virtual void setKinematics( const Kinematics& cuts ) { cuts_ = cuts; }
public:
/**
* Sets the phase space point to compute the weight associated to it.
* \brief Sets the phase space point to compute
* \param[in] ndim The number of dimensions of the point in the phase space
* \param[in] x[] The (\a ndim_)-dimensional point in the phase space on which the kinematics and the cross-section are computed
*/
void setPoint( const unsigned int ndim, double* x );
/// Dump the evaluated point's coordinates in the standard output stream
void dumpPoint();
/// Complete list of Particle with their role in the process for the point considered in the phase space, returned as an Event object.
/// \return Event object containing all the generated Particle objects
inline std::shared_ptr<Event> event() { return event_; }
///Get the number of dimensions on which the integration is performed
inline const unsigned int ndim() const { return x_.size(); }
/// Get the value of a component of the d-dimensional point considered
inline const double x( const unsigned int idx ) const {
return ( idx >= x_.size() ) ? -1. : x_[idx];
}
/// Name of the process considered
inline const std::string& name() const { return name_; }
/// Human-readable description of the process
inline const std::string& description() const { return description_; }
/// Does the process contain (and hold) an event?
bool hasEvent() const { return has_event_; }
/// Reset the total generation time and the number of events generated for this run
inline void clearRun() {
total_gen_time_ = 0.;
num_gen_events_ = 0;
}
/// Add a new timing into the total generation time
/// \param[in] gen_time Time to add (in seconds)
inline void addGenerationTime( const float& gen_time ) {
total_gen_time_ += gen_time;
num_gen_events_++;
}
/// Return the total generation time for this run (in seconds)
inline float totalGenerationTime() const { return total_gen_time_; }
/// Total number of events already generated in this run
inline unsigned int numGeneratedEvents() const { return num_gen_events_; }
protected:
/// Set the incoming and outgoing states to be defined in this process (and prepare the Event object accordingly)
void setEventContent( const IncomingState& is, const OutgoingState& os );
/// Compute the electric/magnetic form factors for the two considered \f$Q^{2}\f$ momenta transfers
void formFactors( double q1, double q2, FormFactors& fp1, FormFactors& fp2 ) const;
/// Get a list of references to the particles with a given role in the process
/// \param[in] role role in the process for the particle to retrieve
/// \return A vector of references to Particle objects associated to the role
inline Particles particles( const Particle::Role& role ) { return event_->getByRole( role ); }
// ---
/// Array of double precision floats representing the point on which the weight in the cross-section is computed
std::vector<double> x_;
/// List of incoming state particles (including intermediate partons)
IncomingState incoming_state_;
/// List of outgoing state particles
OutgoingState outgoing_state_;
/// \f$s\f$, squared centre of mass energy of the incoming particles' system, in \f$\mathrm{GeV}^2\f$
double s_;
/// \f$\sqrt s\f$, centre of mass energy of the incoming particles' system (in GeV)
double sqs_;
/// \f$m_1^2\f$, squared mass of the first proton-like incoming particle
double w1_;
/// \f$m_2^2\f$, squared mass of the second proton-like incoming particle
double w2_;
/// Virtuality of the first incoming photon
double t1_;
/// Virtuality of the second incoming photon
double t2_;
/// Invariant mass of the first proton-like outgoing particle (or remnant)
double MX_;
/// Invariant mass of the second proton-like outgoing particle (or remnant)
double MY_;
/// Set of cuts to apply on the final phase space
Kinematics cuts_;
/// Event object containing all the information on the in- and outgoing particles
std::shared_ptr<Event> event_;
/// Is the phase space point set?
bool is_point_set_;
/// Are the event's incoming particles set?
bool is_incoming_state_set_;
/// Are the event's outgoing particles set?
bool is_outgoing_state_set_;
/// Is the full event's kinematic set?
bool is_kinematics_set_;
/// Name of the process
std::string name_;
/// Process human-readable description
std::string description_;
/// Total generation time (in seconds)
float total_gen_time_;
/// Number of events already generated
unsigned int num_gen_events_;
/// Does the process contain (and hold) an event?
bool has_event_;
private:
/**
* Is the system's kinematics well defined and compatible with the process ?
* This check is mandatory to perform the d-dimensional point's cross-section computation.
* \brief Is the system's kinematics well defined?
* \return A boolean stating if the input kinematics and the final states are well-defined
*/
bool isKinematicsDefined();
};
}
}
#endif
diff --git a/CepGen/Processes/PPtoLL.cpp b/CepGen/Processes/PPtoLL.cpp
index f6fb608..8137194 100644
--- a/CepGen/Processes/PPtoLL.cpp
+++ b/CepGen/Processes/PPtoLL.cpp
@@ -1,411 +1,411 @@
#include "PPtoLL.h"
#include "CepGen/Core/Exception.h"
#include <assert.h>
using namespace CepGen::Process;
PPtoLL::PPtoLL() :
- GenericKTProcess( "pptoll", "gamma,gamma->l+,l-", 4, { { Particle::Photon, Particle::Proton } }, { Particle::Muon, Particle::Muon } )
+ GenericKTProcess( "pptoll", "gamma,gamma->l+,l-", 4, { { Photon, Photon } }, { Muon, Muon } )
{}
void
PPtoLL::prepareKTKinematics()
{
////////////////////////////////////
const Kinematics::Limits rap_limits = cuts_.cuts.central[Cuts::rapidity_single];
///////////// FIXME ////////////////
// Outgoing leptons
y1_ = rap_limits.x( xkt( 0 ) );
y2_ = rap_limits.x( xkt( 1 ) );
DebuggingInsideLoop( Form( "leptons rapidities (%.2f < y < %.2f): %f / %f", rap_limits.min(), rap_limits.max(), y1_, y2_ ) );
Kinematics::Limits ptdiff_limits = cuts_.cuts.central[Cuts::pt_diff];
if ( !ptdiff_limits.hasMax() ) ptdiff_limits.max() = 500.; //FIXME
pt_diff_ = ptdiff_limits.x( xkt( 2 ) );
phi_pt_diff_ = 2.*M_PI*xkt( 3 );
DebuggingInsideLoop( Form( "leptons pt difference:\n\t"
" mag = %f (%.2f < Dpt < %.2f)\n\t"
" phi = %f",
pt_diff_, ptdiff_limits.min(), ptdiff_limits.max(), phi_pt_diff_ ) );
}
double
PPtoLL::computeJacobian()
{
double jac = GenericKTProcess::minimalJacobian();
jac *= cuts_.cuts.central[Cuts::rapidity_single].range(); // d(y1)
jac *= cuts_.cuts.central[Cuts::rapidity_single].range(); // d(y2)
jac *= cuts_.cuts.central[Cuts::pt_diff].range(); // d(Dpt)
jac *= 2.*M_PI; // d(phiDpt)
return jac;
}
double
PPtoLL::computeKTFactorisedMatrixElement()
{
- const double mp = Particle::massFromPDGId( Particle::Proton ), mp2 = mp*mp;
+ const double mp = ParticleProperties::mass( Proton ), mp2 = mp*mp;
const double ml = event_->getByRole( Particle::CentralSystem )[0].mass(), ml2 = ml*ml;
const unsigned int iterm11 = 1, // Long-long
iterm22 = 1, // Trans-trans
iterm12 = 1, // Long-trans
itermtt = 1; // Trans-trans(')
//=================================================================
// How matrix element is calculated
//=================================================================
const bool off_shell = true;
//=================================================================
// two terms in Wolfgang's formula for
// off-shell gamma gamma --> l^+ l^-
//=================================================================
const unsigned int imat1 = 2, imat2 = 0;
//=================================================================
// matrix element computation
//=================================================================
//const double stild = s_/2.*(1+sqrt(1.-(4*pow(mp2, 2))/s_*s_));
// Inner photons
const double q1tx = qt1_*cos( phi_qt1_ ), q1ty = qt1_*sin( phi_qt1_ ),
q2tx = qt2_*cos( phi_qt2_ ), q2ty = qt2_*sin( phi_qt2_ );
DebuggingInsideLoop( Form( "q1t(x/y) = %e / %e\n\t"
"q2t(x/y) = %e / %e", q1tx, q1ty, q2tx, q2ty ) );
// Two-photon system
const double ptsumx = q1tx+q2tx,
ptsumy = q1ty+q2ty,
ptsum = sqrt( ptsumx*ptsumx+ptsumy*ptsumy );
const double ptdiffx = pt_diff_*cos( phi_pt_diff_ ),
ptdiffy = pt_diff_*sin( phi_pt_diff_ );
// Outgoing leptons
const double pt1x = ( ptsumx+ptdiffx )*0.5, pt1y = ( ptsumy+ptdiffy )*0.5, pt1 = sqrt( pt1x*pt1x+pt1y*pt1y ),
pt2x = ( ptsumx-ptdiffx )*0.5, pt2y = ( ptsumy-ptdiffy )*0.5, pt2 = sqrt( pt2x*pt2x+pt2y*pt2y );
const Kinematics::Limits pt_limits = cuts_.cuts.central[Cuts::pt_single];
if ( pt_limits.hasMin() && ( pt1 < pt_limits.min() || pt2 < pt_limits.min() ) ) return 0.;
if ( pt_limits.hasMax() && ( pt1 > pt_limits.max() || pt2 > pt_limits.max() ) ) return 0.;
// transverse mass for the two leptons
const double amt1 = sqrt( pt1*pt1+ml2 ),
amt2 = sqrt( pt2*pt2+ml2 );
//=================================================================
// a window in transverse momentum difference
//=================================================================
const Kinematics::Limits ptdiff_limits = cuts_.cuts.central[Cuts::pt_diff];
if ( ptdiff_limits.hasMax() && fabs( pt1-pt2 ) > ptdiff_limits.max() ) return 0.;
//=================================================================
// a window in rapidity distance
//=================================================================
const double dely = fabs( y1_-y2_ );
const Kinematics::Limits dely_limits = cuts_.cuts.central[Cuts::rapidity_diff];
if ( dely_limits.hasMin() && dely < dely_limits.min() ) return 0.;
if ( dely_limits.hasMax() && dely > dely_limits.max() ) return 0.;
//=================================================================
// auxiliary quantities
//=================================================================
const double alpha1 = amt1/sqs_*exp( y1_ ),
alpha2 = amt2/sqs_*exp( y2_ ),
beta1 = amt1/sqs_*exp( -y1_ ),
beta2 = amt2/sqs_*exp( -y2_ );
DebuggingInsideLoop( Form( "Sudakov parameters:\n\t"
" alpha1/2 = %f / %f\n\t"
" beta1/2 = %f / %f", alpha1, alpha2, beta1, beta2 ) );
const double q1t2 = q1tx*q1tx+q1ty*q1ty,
q2t2 = q2tx*q2tx+q2ty*q2ty;
//const double old_x2 = 0.; //FIXME figure out where this comes from
//const double delta_x1 = (MX_*MX_+q2t2)/((1.-old_x2)*s_);
//x1 = alpha1+alpha2+delta_x1;
const double x1 = alpha1+alpha2,
x2 = beta1 +beta2;
/*const double xi_x1 = log10(x1);
const double xi_x2 = log10(x2);*/
const double z1p = alpha1/x1, z1m = alpha2/x1,
z2p = beta1 /x2, z2m = beta2 /x2;
DebuggingInsideLoop( Form( "z(1/2)p = %f / %f\n\t"
"z(1/2)m = %f / %f", z1p, z2p, z1m, z2m ) );
if ( x1 > 1. || x2 > 1. ) return 0.; // sanity check
// FIXME FIXME FIXME
const double ak10 = event_->getOneByRole( Particle::IncomingBeam1 ).energy(),
ak1z = event_->getOneByRole( Particle::IncomingBeam1 ).momentum().pz(),
ak20 = event_->getOneByRole( Particle::IncomingBeam2 ).energy(),
ak2z = event_->getOneByRole( Particle::IncomingBeam2 ).momentum().pz();
DebuggingInsideLoop( Form( "incoming particles: p1: %f / %f\n\t"
" p2: %f / %f", ak1z, ak10, ak2z, ak20 ) );
//=================================================================
// additional conditions for energy-momentum conservation
//=================================================================
const double s1_eff = x1*s_-qt1_*qt1_, s2_eff = x2*s_-qt2_*qt2_;
const double invm = sqrt( amt1*amt1 + amt2*amt2 + 2.*amt1*amt2*cosh(y1_-y2_) - ptsum*ptsum );
DebuggingInsideLoop( Form( "s(1/2)_eff = %f / %f GeV^2\n\t"
"dilepton invariant mass = %f GeV", s1_eff, s2_eff, invm ) );
switch ( cuts_.mode ) {
case Kinematics::ElasticInelastic: if ( sqrt( s1_eff ) <= ( MY_+invm ) ) return 0.;
case Kinematics::InelasticElastic: if ( sqrt( s2_eff ) <= ( MX_+invm ) ) return 0.;
case Kinematics::InelasticInelastic: if ( sqrt( s1_eff ) <= ( MY_+invm ) ) return 0.;
if ( sqrt( s2_eff ) <= ( MX_+invm ) ) return 0.;
default: break;
}
//const double qcaptx = pcaptx, qcapty = pcapty;
//=================================================================
// four-momenta of the outgoing protons (or remnants)
//=================================================================
const double px_plus = ( 1.-x1 )*fabs( ak1z )*sqrt( 2. ),
px_minus = ( MX_*MX_ + q1tx*q1tx + q1ty*q1ty )*0.5/px_plus;
const double py_minus = ( 1.-x2 )*fabs( ak2z )*sqrt( 2. ), // warning! sign of pz??
py_plus = ( MY_*MY_ + q2tx*q2tx + q2ty*q2ty )*0.5/py_minus;
DebuggingInsideLoop( Form( "px_(+/-) = %f / %f\n\t"
"py_(+/-) = %f / %f", px_plus, px_minus, py_plus, py_minus ) );
PX_ = Particle::Momentum( -q1tx, -q1ty, ( px_plus-px_minus )*0.5*sqrt( 2. ), (px_plus+px_minus)*0.5*sqrt( 2. ) );
PY_ = Particle::Momentum( -q2tx, -q2ty, ( py_plus-py_minus )*0.5*sqrt( 2. ), (py_plus+py_minus)*0.5*sqrt( 2. ) );
DebuggingInsideLoop( Form( "First remnant: (E,p) = (%f, %f, %f, %f)\n\t"
"Second remnant: (E,p) = (%f, %f, %f, %f)",
PX_.px(), PX_.py(), PX_.pz(), PX_.energy(),
PY_.px(), PY_.py(), PY_.pz(), PY_.energy() ) );
assert( fabs( PX_.mass()-MX_ ) < 1.e-6 );
assert( fabs( PY_.mass()-MY_ ) < 1.e-6 );
//=================================================================
// four-momenta of the outgoing l^+ and l^-
//=================================================================
Particle::Momentum p1( pt1x, pt1y, alpha1*ak1z + beta1*ak2z, alpha1*ak10 + beta1*ak20 ),
p2( pt2x, pt2y, alpha2*ak1z + beta2*ak2z, alpha2*ak10 + beta2*ak20 );
DebuggingInsideLoop( Form( "unboosted first lepton: (E,p), m = (%f, %f, %f, %f), %f\n\t"
" second lepton: (E,p), m = (%f, %f, %f, %f), %f",
p1.px(), p1.py(), p1.pz(), p1.energy(), p1.mass(),
p2.px(), p2.py(), p2.pz(), p2.energy(), p2.mass() ) );
Pl1_ = Particle::Momentum( pt1x, pt1y, sqrt( pt1*pt1 + ml2 )*sinh( y1_ ), sqrt( pt1*pt1 + ml2 )*cosh( y1_ ) );
Pl2_ = Particle::Momentum( pt2x, pt2y, sqrt( pt2*pt2 + ml2 )*sinh( y2_ ), sqrt( pt2*pt2 + ml2 )*cosh( y2_ ) );
DebuggingInsideLoop( Form( "First lepton: (E,p), m = (%f, %f, %f, %f), %f\n\t"
"Second lepton: (E,p), m = (%f, %f, %f, %f), %f",
Pl1_.px(), Pl1_.py(), Pl1_.pz(), Pl1_.energy(), Pl1_.mass(),
Pl2_.px(), Pl2_.py(), Pl2_.pz(), Pl2_.energy(), Pl2_.mass() ) );
assert( fabs( Pl1_.mass()-event_->getByRole( Particle::CentralSystem )[0].mass() ) < 1.e-6 );
assert( fabs( Pl2_.mass()-event_->getByRole( Particle::CentralSystem )[1].mass() ) < 1.e-6 );
//=================================================================
// four-momenta squared of the virtual photons
//=================================================================
// FIXME FIXME FIXME /////////////////////
Particle::Momentum q1( q1tx, q1ty, 0., 0. ),
q2( q2tx, q2ty, 0., 0. );
//////////////////////////////////////////
DebuggingInsideLoop( Form( "First photon*: (E,p), m2 = (%f, %f, %f, %f), %e\n\t"
"Second photon*: (E,p), m2 = (%f, %f, %f, %f), %e",
q1.px(), q1.py(), q1.pz(), q1.energy(), q1.mass2(),
q2.px(), q2.py(), q2.pz(), q2.energy(), q2.mass2() ) );
//const double q12 = q1.mass2(), q22 = q2.mass2();
//=================================================================
// Mendelstam variables
//=================================================================
//const double shat = s_*x1*x2; // ishat = 1 (approximation)
//const double shat = ( q1+q2 ).mass2(); // ishat = 2 (exact formula)
const double that1 = ( q1-p1 ).mass2(), that2 = ( q2-p2 ).mass2(),
uhat1 = ( q1-p2 ).mass2(), uhat2 = ( q2-p1 ).mass2();
DebuggingInsideLoop( Form( "that(1/2) = %f / %f\n\t"
"uhat(1/2) = %f / %f",
that1, that2, uhat1, uhat2 ) );
//const double mll = sqrt( shat );
const double that = 0.5*( that1+that2 ), uhat = 0.5*( uhat1+uhat2 );
//=================================================================
// matrix elements
//=================================================================
double amat2 = 0.;
if ( !off_shell ) {
//=================================================================
// on-shell formula for M^2
//=================================================================
const double ml4 = ml2*ml2, ml8 = ml4*ml4;
const double term1 = 6. *ml8,
term2 = -3. *ml4*that*that,
term3 = -14.*ml4*that*uhat,
term4 = -3. *ml4*uhat*uhat,
term5 = ml2*that*that*that,
term6 = 7.* ml2*that*that*uhat,
term7 = 7.* ml2*that*uhat*uhat,
term8 = ml2*uhat*uhat*uhat,
term9 = -that*that*that*uhat,
term10 = -that*uhat*uhat*uhat;
const double auxil_gamgam = -2.*( term1+term2+term3+term4+term5+term6+term7+term8+term9+term10 )/( pow( ( ml2-that )*( ml2-uhat ), 2) );
const double g_em_sq = 4.*M_PI*Constants::alphaEM;
amat2 = g_em_sq*g_em_sq*auxil_gamgam;
}
else if ( off_shell ) {
//=================================================================
// Wolfgang's formulae
//=================================================================
double aux2_1, aux2_2;
const double ak1_x = z1m*pt1x - z1p*pt2x, ak1_y = z1m*pt1y - z1p*pt2y,
ak2_x = z2m*pt1x - z2p*pt2x, ak2_y = z2m*pt1y - z2p*pt2y;
const double t1abs = ( q1t2 + x1*( MX_*MX_-mp2 )+x1*x1*mp2 )/( 1.-x1 ),
t2abs = ( q2t2 + x2*( MY_*MY_-mp2 )+x2*x2*mp2 )/( 1.-x2 );
const double eps12 = ml2 + z1p*z1m*t1abs,
eps22 = ml2 + z2p*z2m*t2abs;
const double Phi10 = 1./( pow( ak1_x + z1p*q2tx, 2 ) + pow( ak1_y + z1p*q2ty, 2 ) + eps12 )
-1./( pow( ak1_x - z1m*q2tx, 2 ) + pow( ak1_y - z1m*q2ty, 2 ) + eps12 ),
Phi11_x = ( ak1_x + z1p*q2tx )/( pow( ak1_x + z1p*q2tx, 2 ) + pow( ak1_y + z1p*q2ty, 2 ) + eps12 )
-( ak1_x - z1m*q2tx )/( pow( ak1_x - z1m*q2tx, 2 ) + pow( ak1_y - z1m*q2ty, 2 ) + eps12 ),
Phi11_y = ( ak1_y + z1p*q2ty )/( pow( ak1_x + z1p*q2tx, 2 ) + pow( ak1_y + z1p*q2ty, 2 ) + eps12 )
-( ak1_y - z1m*q2ty )/( pow( ak1_x - z1m*q2tx, 2 ) + pow( ak1_y - z1m*q2ty, 2 ) + eps12 ),
Phi102 = Phi10*Phi10;
//const double Phi112 = Phi11_x*Phi11_x + Phi11_y*Phu11_y;
const double Phi20 = 1./( pow( ak2_x + z2p*q1tx, 2 )+pow( ak2_y + z2p*q1ty, 2 ) + eps22 )
-1./( pow( ak2_x - z2m*q1tx, 2 )+pow( ak2_y - z2m*q1ty, 2 ) + eps22 ),
Phi21_x = ( ak2_x + z2p*q1tx )/( pow( ak2_x + z2p*q1tx, 2 ) + pow( ak2_y + z2p*q1ty, 2 ) + eps22 )
-( ak2_x - z2m*q1tx )/( pow( ak2_x - z2m*q1tx ,2 ) + pow( ak2_y - z2m*q1ty, 2 ) + eps22 ),
Phi21_y = ( ak2_y + z2p*q1ty )/( pow( ak2_x + z2p*q1tx, 2 ) + pow( ak2_y + z2p*q1ty, 2 ) + eps22 )
-( ak2_y - z2m*q1ty )/( pow( ak2_x - z2m*q1tx, 2 ) + pow( ak2_y - z2m*q1ty, 2 ) + eps22 ),
Phi202 = Phi20*Phi20;
//const double Phi212 = Phi21_x*Phi21_x + Phi21_y*Phi21_y;
/*aux2_1 = iterm11*( ml2 + 4.*z1p*z1m*t1abs )*Phi102
+iterm22*( z1p*z1p + z1m*z1m )*Phi112
-iterm12*4.*z1p*z1m*( z1p-z1m )*Phi10*( q1tx*Phi11_x + q1ty*Phi11_y );
aux2_2 = iterm11*( ml2+4.*z2p*z2m*t2abs)*Phi202
+iterm22*( z2p*z2p + z2m*z2m )*Phi212
-iterm12*4.*z2p*z2m*( z2p-z2m )*Phi20*( q2tx*Phi21_x + q2ty*Phi21_y );*/
const double Phi11_dot_e = ( Phi11_x*q1tx + Phi11_y*q1ty )/qt1_, Phi11_cross_e = ( Phi11_x*q1ty-Phi11_y*q1tx )/qt1_;
const double Phi21_dot_e = ( Phi21_x*q2tx + Phi21_y*q2ty )/qt2_, Phi21_cross_e = ( Phi21_x*q2ty-Phi21_y*q2tx )/qt2_;
DebuggingInsideLoop( Form( "Phi1: E, px, py = %e, %e, %e\n\t"
"Phi2: E, px, py = %e, %e, %e\n\t"
"(dot): %e / %e\n\t"
"(cross): %e / %e",
Phi10, Phi11_x, Phi11_y, Phi20, Phi21_x, Phi21_y,
Phi11_dot_e, Phi21_dot_e, Phi11_cross_e, Phi21_cross_e ) );
aux2_1 = iterm11 * ( ml2 + 4.*z1p*z1p*z1m*z1m*t1abs ) * Phi102
+iterm22 * ( ( z1p*z1p + z1m*z1m )*( Phi11_dot_e*Phi11_dot_e + Phi11_cross_e*Phi11_cross_e ) )
+itermtt * ( Phi11_cross_e*Phi11_cross_e - Phi11_dot_e*Phi11_dot_e )
-iterm12 * 4.*z1p*z1m*( z1p-z1m ) * Phi10 * ( q1tx*Phi11_x + q1ty*Phi11_y );
aux2_2 = iterm11 * ( ml2 + 4.*z2p*z2p*z2p*z2m*t2abs ) * Phi202
+iterm22 * ( ( z2p*z2p + z2m*z2m )*( Phi21_dot_e*Phi21_dot_e + Phi21_cross_e*Phi21_cross_e ) )
+itermtt * ( Phi21_cross_e*Phi21_cross_e - Phi21_dot_e*Phi21_dot_e )
-iterm12 * 4.*z2p*z2m*( z2p-z2m ) * Phi20 * ( q2tx*Phi21_x + q2ty*Phi21_y );
//=================================================================
// convention of matrix element as in our kt-factorization
// for heavy flavours
//=================================================================
const double norm = 16.*M_PI*M_PI*Constants::alphaEM*Constants::alphaEM;
double amat2_1 = norm * pow( x1*x2*s_, 2 ) * aux2_1*2.*z1p*z1m*t1abs/( q1t2*q2t2 ) * t2abs/q2t2;
double amat2_2 = norm * pow( x1*x2*s_, 2 ) * aux2_2*2.*z2p*z2m*t2abs/( q1t2*q2t2 );
//=================================================================
// symmetrization
//=================================================================
amat2 = 0.5*( imat1*amat2_1 + imat2*amat2_2 );
DebuggingInsideLoop( Form( "aux2(1/2) = %e / %e\n\t"
"amat2(1/2), amat2 = %e / %e / %e", aux2_1, aux2_2, amat2_1, amat2_2, amat2 ) );
/*const double xx1 = alpha1+alpha2, xx2 = beta1+beta2;
const double sudakov_2 = ( MX_*MX_ - mp2+q2t2+xx2*mp2 )/( ( 1.-xx2 )*s_ );
const double sudakov_1 = ( q1t2 + xx1*mp2 )/( ( 1.-xx1 )*s_ );
const double ratio1 = sudakov_1 / xx1,
ratio2 = sudakov_2 / xx2;*/
//if ( ratio1 > 0.01 ) return 0.;
}
//============================================
// unintegrated photon distributions
//============================================
GenericKTProcess::computeIncomingFluxes( x1, q1t2, x2, q2t2 );
//=================================================================
// factor 2.*pi from integration over phi_sum
// factor 1/4 from jacobian of transformations
// factors 1/pi and 1/pi due to integration over
// d^2 kappa_1 d^2 kappa_2 instead d kappa_1^2 d kappa_2^2
//=================================================================
const double aintegral = amat2 / ( 16.*M_PI*M_PI*x1*x1*x2*x2*s_*s_ )
* flux1_/M_PI * flux2_/M_PI
* Constants::GeV2toBarn * 0.25;
//=================================================================
return aintegral*qt1_*qt2_*pt_diff_;
//=================================================================
}
void
PPtoLL::fillCentralParticlesKinematics()
{
// randomise the charge of the outgoing leptons
int sign = ( drand()>.5 ) ? +1 : -1;
//=================================================================
// first outgoing lepton
//=================================================================
Particle& ol1 = event_->getByRole( Particle::CentralSystem )[0];
ol1.setPdgId( ol1.pdgId(), sign );
ol1.setStatus( Particle::FinalState );
ol1.setMomentum( Pl1_ );
//=================================================================
// second outgoing lepton
//=================================================================
Particle& ol2 = event_->getByRole( Particle::CentralSystem )[1];
ol2.setPdgId( ol2.pdgId(), -sign );
ol2.setStatus( Particle::FinalState );
ol2.setMomentum( Pl2_ );
}
diff --git a/CepGen/Processes/PPtoWW.cpp b/CepGen/Processes/PPtoWW.cpp
index 78d2057..b548f9f 100644
--- a/CepGen/Processes/PPtoWW.cpp
+++ b/CepGen/Processes/PPtoWW.cpp
@@ -1,362 +1,361 @@
#include "PPtoWW.h"
#include "CepGen/Core/Exception.h"
#include <assert.h>
using namespace CepGen::Process;
PPtoWW::PPtoWW() :
- GenericKTProcess( "pptoww", "gamma,gamma->W+,W-", 4, { { Particle::Photon, Particle::Photon } }, { Particle::W, Particle::W } )
+ GenericKTProcess( "pptoww", "gamma,gamma->W+,W-", 4, { { Photon, Photon } }, { W, W } )
{}
void
PPtoWW::prepareKTKinematics()
{
const Kinematics::Limits rap_limits = cuts_.cuts.central[Cuts::rapidity_single];
// outgoing Ws
y1_ = rap_limits.x( xkt( 0 ) );
y2_ = rap_limits.x( xkt( 1 ) );
DebuggingInsideLoop( Form( "W bosons rapidities (%.2f < y < %.2f): %f / %f", rap_limits.min(), rap_limits.max(), y1_, y2_ ) );
Kinematics::Limits ptdiff_limits = cuts_.cuts.central[Cuts::pt_diff];
if ( !ptdiff_limits.hasMax() ) ptdiff_limits.max() = 500.; //FIXME
pt_diff_ = ptdiff_limits.x( xkt( 2 ) );
phi_pt_diff_ = 2.*M_PI*xkt( 3 );
DebuggingInsideLoop( Form( "W bosons pt difference:\n\t"
" mag = %f (%.2f < Dpt < %.2f)\n\t"
" phi = %f",
pt_diff_, ptdiff_limits.min(), ptdiff_limits.max(), phi_pt_diff_ ) );
}
double
PPtoWW::computeJacobian()
{
double jac = GenericKTProcess::minimalJacobian();
jac *= cuts_.cuts.central[Cuts::rapidity_single].range(); // d(y1)
jac *= cuts_.cuts.central[Cuts::rapidity_single].range(); // d(y2)
jac *= cuts_.cuts.central[Cuts::pt_diff].range(); // d(Dpt)
jac *= 2.*M_PI; // d(phiDpt)
return jac;
}
double
PPtoWW::computeKTFactorisedMatrixElement()
{
- const double mp = Particle::massFromPDGId( Particle::Proton ), mp2 = mp*mp;
- const double mw = Particle::massFromPDGId( Particle::W ), mw2 = mw*mw;
+ const double mp = ParticleProperties::mass( Proton ), mp2 = mp*mp;
+ const double mw = ParticleProperties::mass( W ), mw2 = mw*mw;
//=================================================================
// How matrix element is calculated
//=================================================================
const unsigned short method = 1;
//=================================================================
// matrix element computation
//=================================================================
//const double stild = s_/2.*(1+sqrt(1.-(4*pow(mp2, 2))/s_*s_));
// Inner photons
const double q1tx = qt1_*cos( phi_qt1_ ), q1ty = qt1_*sin( phi_qt1_ ),
q2tx = qt2_*cos( phi_qt2_ ), q2ty = qt2_*sin( phi_qt2_ );
DebuggingInsideLoop( Form( "q1t(x/y) = %e / %e\n\t"
"q2t(x/y) = %e / %e", q1tx, q1ty, q2tx, q2ty ) );
// Two-photon system
const double ptsumx = q1tx+q2tx,
ptsumy = q1ty+q2ty,
ptsum = sqrt( ptsumx*ptsumx+ptsumy*ptsumy );
const double ptdiffx = pt_diff_*cos( phi_pt_diff_ ),
ptdiffy = pt_diff_*sin( phi_pt_diff_ );
// Outgoing leptons
const double pt1x = 0.5 * ( ptsumx+ptdiffx ), pt1y = 0.5 * ( ptsumy+ptdiffy ), pt1 = sqrt( pt1x*pt1x+pt1y*pt1y ),
pt2x = 0.5 * ( ptsumx-ptdiffx ), pt2y = 0.5 * ( ptsumy-ptdiffy ), pt2 = sqrt( pt2x*pt2x+pt2y*pt2y );
const Kinematics::Limits pt_limits = cuts_.cuts.central[Cuts::pt_single];
if ( pt_limits.hasMin() && ( pt1 < pt_limits.min() || pt2 < pt_limits.min() ) ) return 0.;
if ( pt_limits.hasMax() && ( pt1 > pt_limits.max() || pt2 > pt_limits.max() ) ) return 0.;
// transverse mass for the two leptons
const double amt1 = sqrt( pt1*pt1+mw2 ),
amt2 = sqrt( pt2*pt2+mw2 );
//=================================================================
// a window in two-boson invariant mass
//=================================================================
const double invm = sqrt( amt1*amt1 + amt2*amt2 + 2.*amt1*amt2*cosh( y1_-y2_ ) - ptsum*ptsum );
const Kinematics::Limits invm_limits = cuts_.cuts.central[Cuts::mass_sum];
if ( invm_limits.hasMin() && invm < invm_limits.min() ) return 0.;
if ( invm_limits.hasMax() && invm > invm_limits.max() ) return 0.;
//=================================================================
// a window in transverse momentum difference
//=================================================================
const Kinematics::Limits ptdiff_limits = cuts_.cuts.central[Cuts::pt_diff];
if ( ptdiff_limits.hasMax() && fabs( pt1-pt2 ) > ptdiff_limits.max() ) return 0.;
//=================================================================
// a window in rapidity distance
//=================================================================
const double dely = fabs( y1_-y2_ );
const Kinematics::Limits dely_limits = cuts_.cuts.central[Cuts::rapidity_diff];
if ( dely_limits.hasMin() && dely < dely_limits.min() ) return 0.;
if ( dely_limits.hasMax() && dely > dely_limits.max() ) return 0.;
//=================================================================
// auxiliary quantities
//=================================================================
const double alpha1 = amt1/sqs_*exp( +y1_ ),
alpha2 = amt2/sqs_*exp( +y2_ ),
beta1 = amt1/sqs_*exp( -y1_ ),
beta2 = amt2/sqs_*exp( -y2_ );
DebuggingInsideLoop( Form( "Sudakov parameters:\n\t"
" alpha1/2 = %f / %f\n\t"
" beta1/2 = %f / %f", alpha1, alpha2, beta1, beta2 ) );
const double q1t2 = q1tx*q1tx + q1ty*q1ty,
q2t2 = q2tx*q2tx + q2ty*q2ty;
//const double old_x2 = 0.; //FIXME figure out where this comes from
//const double delta_x1 = (MX_*MX_+q2t2)/((1.-old_x2)*s_);
//x1 = alpha1+alpha2+delta_x1;
const double x1 = alpha1 + alpha2,
x2 = beta1 + beta2;
/*const double xi_x1 = log10(x1);
const double xi_x2 = log10(x2);*/
const double z1p = alpha1/x1, z1m = alpha2/x1,
z2p = beta1 /x2, z2m = beta2 /x2;
DebuggingInsideLoop( Form( "z(1/2)p = %f / %f\n\t"
"z(1/2)m = %f / %f", z1p, z2p, z1m, z2m ) );
if ( x1 > 1. || x2 > 1. ) return 0.; // sanity check
// FIXME FIXME FIXME
const double ak10 = event_->getOneByRole( Particle::IncomingBeam1 ).energy(),
ak1z = event_->getOneByRole( Particle::IncomingBeam1 ).momentum().pz(),
ak20 = event_->getOneByRole( Particle::IncomingBeam2 ).energy(),
ak2z = event_->getOneByRole( Particle::IncomingBeam2 ).momentum().pz();
DebuggingInsideLoop( Form( "incoming particles: p1: %f / %f\n\t"
" p2: %f / %f", ak1z, ak10, ak2z, ak20 ) );
//=================================================================
// additional conditions for energy-momentum conservation
//=================================================================
const double s1_eff = x1*s_-qt1_*qt1_, s2_eff = x2*s_-qt2_*qt2_;
DebuggingInsideLoop( Form( "s(1/2)_eff = %f / %f GeV^2\n\t"
"dilepton invariant mass = %f GeV", s1_eff, s2_eff, invm ) );
switch ( cuts_.mode ) {
case Kinematics::ElasticInelastic: if ( sqrt( s1_eff ) <= ( MY_+invm ) ) return 0.;
case Kinematics::InelasticElastic: if ( sqrt( s2_eff ) <= ( MX_+invm ) ) return 0.;
case Kinematics::InelasticInelastic: if ( sqrt( s1_eff ) <= ( MY_+invm ) ) return 0.;
if ( sqrt( s2_eff ) <= ( MX_+invm ) ) return 0.;
default: break;
}
//const double qcaptx = pcaptx, qcapty = pcapty;
//=================================================================
// four-momenta of the outgoing protons (or remnants)
//=================================================================
const double px_plus = ( 1.-x1 )*fabs( ak1z )*sqrt( 2. ),
px_minus = ( MX_*MX_ + q1t2 )*0.5/px_plus;
const double py_minus = ( 1.-x2 )*fabs( ak2z )*sqrt( 2. ), // warning! sign of pz??
py_plus = ( MY_*MY_ + q2t2 )*0.5/py_minus;
DebuggingInsideLoop( Form( "px_(+/-) = %f / %f\n\t"
"py_(+/-) = %f / %f", px_plus, px_minus, py_plus, py_minus ) );
PX_ = Particle::Momentum( -q1tx, -q1ty, ( px_plus-px_minus )/sqrt( 2. ), ( px_plus+px_minus )/sqrt( 2. ) );
PY_ = Particle::Momentum( -q2tx, -q2ty, ( py_plus-py_minus )/sqrt( 2. ), ( py_plus+py_minus )/sqrt( 2. ) );
DebuggingInsideLoop( Form( "First remnant: (E,p) = (%f, %f, %f, %f)\n\t"
"Second remnant: (E,p) = (%f, %f, %f, %f)",
PX_.px(), PX_.py(), PX_.pz(), PX_.energy(),
PY_.px(), PY_.py(), PY_.pz(), PY_.energy() ) );
/*assert( fabs( PX_.mass()-MX_ ) < 1.e-6 );
assert( fabs( PY_.mass()-MY_ ) < 1.e-6 );*/
//=================================================================
// four-momenta squared of the virtual photons
//=================================================================
const double ww = 0.5 * ( 1.+sqrt( 1.-4.*mp2/s_ ) );
// FIXME FIXME FIXME /////////////////////
Particle::Momentum q1( q1tx, q1ty, +0.5 * x1*ww*sqs_*( 1.-q1t2/x1/x1/ww/ww/s_ ), 0.5 * x1*ww*sqs_*( 1.+q1t2/x1/x1/ww/ww/s_ ) ),
q2( q2tx, q2ty, -0.5 * x2*ww*sqs_*( 1.-q2t2/x2/x2/ww/ww/s_ ), 0.5 * x2*ww*sqs_*( 1.+q2t2/x2/x2/ww/ww/s_ ) );
//////////////////////////////////////////
DebuggingInsideLoop( Form( "First photon*: (E,p), m2 = (%f, %f, %f, %f), %e\n\t"
"Second photon*: (E,p), m2 = (%f, %f, %f, %f), %e",
q1.px(), q1.py(), q1.pz(), q1.energy(), q1.mass2(),
q2.px(), q2.py(), q2.pz(), q2.energy(), q2.mass2() ) );
//const double q12 = q1.mass2(), q22 = q2.mass2();
//=================================================================
// four-momenta of the outgoing W^+ and W^-
//=================================================================
p_w1_ = Particle::Momentum( pt1x, pt1y, alpha1*ak1z + beta1*ak2z, alpha1*ak10 + beta1*ak20 );
p_w2_ = Particle::Momentum( pt2x, pt2y, alpha2*ak1z + beta2*ak2z, alpha2*ak10 + beta2*ak20 );
DebuggingInsideLoop( Form( "First W: (E,p), m = (%f, %f, %f, %f), %f\n\t"
"Second W: (E,p), m = (%f, %f, %f, %f), %f",
p_w1_.px(), p_w2_.py(), p_w1_.pz(), p_w1_.energy(), p_w1_.mass(),
p_w2_.px(), p_w2_.py(), p_w2_.pz(), p_w2_.energy(), p_w2_.mass() ) );
//assert( fabs( p_w1_.mass()-event_->getByRole( Particle::CentralSystem )[0].mass() ) < 1.e-6 );
//assert( fabs( p_w2_.mass()-event_->getByRole( Particle::CentralSystem )[1].mass() ) < 1.e-6 );
//=================================================================
// Mendelstam variables
//=================================================================
//const double shat = s_*x1*x2; // ishat = 1 (approximation)
const double shat = ( q1+q2 ).mass2(); // ishat = 2 (exact formula)
const double that1 = ( q1-p_w1_ ).mass2(), that2 = ( q2-p_w2_ ).mass2(),
uhat1 = ( q1-p_w2_ ).mass2(), uhat2 = ( q2-p_w1_ ).mass2();
DebuggingInsideLoop( Form( "that(1/2) = %f / %f\n\t"
"uhat(1/2) = %f / %f",
that1, that2, uhat1, uhat2 ) );
//const double mll = sqrt( shat );
const double that = 0.5*( that1+that2 ), uhat = 0.5*( uhat1+uhat2 );
//=================================================================
// matrix elements
//=================================================================
double amat2 = 0.;
if ( method == 0 ) {
//=================================================================
// matrix element for gamma gamma --> W^+ W^-
// (Denner+Dittmaier+Schuster)
// (work in collaboration with C. Royon)
//=================================================================
const double mw4 = mw2*mw2;
const double term1 = 2.*shat * ( 2.*shat+3.*mw2 ) / ( 3.*( mw2-that )*( mw2-uhat ) );
const double term2 = 2.*shat*shat * ( shat*shat + 3.*mw4 ) / ( 3.*pow( mw2-that, 2 )*pow( mw2-uhat, 2 ) );
const double auxil_gamgam = 1. - term1 + term2;
const double beta = sqrt( 1.-4.*mw2/shat );
amat2 = 3.*Constants::alphaEM*Constants::alphaEM*beta / ( 2.*shat ) * auxil_gamgam / ( beta/( 64.*M_PI*M_PI*shat ) );
}
else if ( method == 1 ) {
//=================================================================
// off-shell Nachtmann formulae
//=================================================================
const double e2 = 4.*M_PI*Constants::alphaEM;
const double phi_diff = phi_qt1_-phi_qt2_, phi_sum = phi_qt1_+phi_qt2_;
double amat2_0 = 0., amat2_1 = 0., amat2_interf = 0.;
for ( const auto lam3 : { -1, 0, 1 } ) {
for ( const auto lam4 : { -1, 0, 1 } ) {
double ampli_pp = WWamplitude( shat, that, +1, +1, lam3, lam4 );
double ampli_mm = WWamplitude( shat, that, -1, -1, lam3, lam4 );
double ampli_pm = WWamplitude( shat, that, +1, -1, lam3, lam4 );
double ampli_mp = WWamplitude( shat, that, -1, +1, lam3, lam4 );
amat2_0 += ampli_pp*ampli_pp + ampli_mm*ampli_mm + 2.*cos( 2.*phi_diff )*ampli_pp*ampli_mm;
amat2_1 += ampli_pm*ampli_pm + ampli_mp*ampli_mp + 2.*cos( 2.*phi_sum )*ampli_pm*ampli_mp;
amat2_interf += -2.*( cos( phi_sum+phi_diff )*( ampli_pp*ampli_pm+ampli_mm*ampli_mp ) + cos( phi_sum-phi_diff )*( ampli_pp*ampli_mp+ampli_mm*ampli_pm ) );
}
}
amat2 = e2*e2 * ( amat2_0 + amat2_1 + amat2_interf );
}
//============================================
// unintegrated photon distributions
//============================================
GenericKTProcess::computeIncomingFluxes( x1, q1t2, x2, q2t2 );
//=================================================================
// factor 2.*pi from integration over phi_sum
// factor 1/4 from jacobian of transformations
// factors 1/pi and 1/pi due to integration over
// d^2 kappa_1 d^2 kappa_2 instead d kappa_1^2 d kappa_2^2
//=================================================================
const double aintegral = amat2 * ( 2.*M_PI )/ ( 16.*M_PI*M_PI*( x1*x2*s_ )*( x1*x2*s_ ) )
* flux1_/M_PI * flux2_/M_PI * 0.25
* Constants::GeV2toBarn * 0.5 / M_PI;
/*const double aintegral = amat2 / ( 16.*M_PI*M_PI*x1*x1*x2*x2*s_*s_ )
* flux1_/M_PI * flux2_/M_PI
* Constants::GeV2toBarn * 0.25;*/
//=================================================================
return aintegral*qt1_*qt2_*pt_diff_;
//=================================================================
}
void
PPtoWW::fillCentralParticlesKinematics()
{
// randomise the charge of the outgoing leptons
short sign = ( drand()>.5 ) ? +1 : -1;
//=================================================================
// first outgoing lepton
//=================================================================
Particle& ow1 = event_->getByRole( Particle::CentralSystem )[0];
ow1.setPdgId( ow1.pdgId(), sign );
ow1.setStatus( Particle::Undecayed );
ow1.setMomentum( p_w1_ );
//=================================================================
// second outgoing lepton
//=================================================================
Particle& ow2 = event_->getByRole( Particle::CentralSystem )[1];
ow2.setPdgId( ow2.pdgId(), -sign );
ow2.setStatus( Particle::Undecayed );
ow2.setMomentum( p_w2_ );
}
double
PPtoWW::WWamplitude( double shat, double that, short lam1, short lam2, short lam3, short lam4 ) const
{
- // start by defining some constants
- const double mw = Particle::massFromPDGId( Particle::W ), mw2 = mw*mw;
+ const double mw = ParticleProperties::mass( W ), mw2 = mw*mw;
const double sqrt2 = sqrt( 2. );
// then compute some kinematic variables
const double cos_theta = ( 1.+2.*( that-mw2 )/shat ) / sqrt( 1. + 1.e-10 - 4.*mw2/shat ), cos_theta2 = cos_theta*cos_theta;
const double sin_theta2 = 1.-cos_theta2, sin_theta = sqrt( sin_theta2 );
const double beta = sqrt( 1.-4.*mw2/shat ), beta2 = beta*beta;
const double gamma = 0.5*sqrt( shat )/mw, gamma2 = gamma*gamma;
const double invA = 1./( 1.-beta2*cos_theta2 );
const double term1 = 1./gamma2*( ( gamma2+1. )*( 1.-lam1*lam2 )* sin_theta2 - ( 1.+lam1*lam2 ) );
const double term2 = -sqrt2/gamma*( lam1-lam2 ) * ( 1.+lam1*lam3*cos_theta )*sin_theta;
const double term3 = -0.5*( 2.*beta*( lam1+lam2 )*( lam3+lam4 ) - ( 1./gamma2 )*( 1.+lam3*lam4 )*( 2.*lam1*lam2+( 1.-lam1*lam2 ) * cos_theta2 ) +( 1.+lam1*lam2*lam3*lam4 )*( 3.+lam1*lam2 ) + 2.*( lam1-lam2 )*( lam3-lam4 )*cos_theta + ( 1.-lam1*lam2 )*( 1.-lam3*lam4 )*cos_theta2 );
const double term4 = -sqrt2/gamma*( lam2-lam1 ) *( 1.+lam2*lam4*cos_theta )*sin_theta;
if ( lam3 == 0 && lam4 == 0 ) return invA*term1;
if ( lam4 == 0 ) return invA*term2;
if ( lam3 == 0 ) return invA*term4;
if ( lam3 != 0 && lam4 != 0 ) return invA*term3;
return 0.;
}
diff --git a/CepGen/StructureFunctions/ALLM.cpp b/CepGen/StructureFunctions/ALLM.cpp
index 6780443..10d091f 100644
--- a/CepGen/StructureFunctions/ALLM.cpp
+++ b/CepGen/StructureFunctions/ALLM.cpp
@@ -1,161 +1,162 @@
#include "ALLM.h"
-#include "CepGen/Physics/Constants.h"
+#include "CepGen/Physics/ParticleProperties.h"
#include <cmath>
namespace CepGen
{
namespace SF
{
ALLM::Parameterisation
ALLM::Parameterisation::allm91()
{
Parameterisation p;
p.pomeron = Parameters( {
{ 0.26550, 0.04856, 1.04682 },
{ -0.04503, -0.36407, 8.17091 },
{ 0.49222, 0.52116, 3.5515 } } );
p.reggeon = Parameters( {
{ 0.67639, 0.49027, 2.66275 },
{ 0.60408, 0.17353, 1.61812 },
{ 1.26066, 1.83624, 0.81141 } } );
p.m02 = 0.30508;
p.mp2 = 10.676;
p.mr2 = 0.20623;
p.q02 = 0.27799;
p.lambda2 = 0.06527;
return p;
}
ALLM::Parameterisation
ALLM::Parameterisation::allm97()
{
Parameterisation p;
p.pomeron = Parameters( {
{ 0.28067, 0.22291, 2.1979 },
{ -0.0808, -0.44812, 1.1709 },
{ 0.36292, 1.8917, 1.8439 } } );
p.reggeon = Parameters( {
{ 0.80107, 0.97307, 3.4924 },
{ 0.58400, 0.37888, 2.6063 },
{ 0.01147, 3.7582, 0.49338 } } );
p.m02 = 0.31985;
p.mp2 = 49.457;
p.mr2 = 0.15052;
p.q02 = 0.52544;
p.lambda2 = 0.06526;
return p;
}
ALLM::Parameterisation
ALLM::Parameterisation::hht_allm()
{
Parameterisation p;
p.pomeron = Parameters( {
{ 0.412, 0.164, 17.7 },
{ -0.835, -0.446, 10.6 },
{ -45.8, 55.7, -0.031 } } );
p.reggeon = Parameters( {
{ -1.04, 2.97, 0.163 },
{ 0.706, 0.185, -16.4 },
{ -1.29, 4.51, 1.16 } } );
p.m02 = 0.446;
p.mp2 = 74.2;
p.mr2 = 29.3;
p.q02 = 4.74e-5;
p.lambda2 = 2.2e-8;
return p;
}
ALLM::Parameterisation
ALLM::Parameterisation::hht_allm_ft()
{
Parameterisation p;
p.pomeron = Parameters( {
{ 0.356, 0.171, 18.6 },
{ -0.075, -0.470, 9.2 },
{ -0.477, 54.0, 0.073 } } );
p.reggeon = Parameters( {
{ -0.636, 3.37, -0.660 },
{ 0.882, 0.082, -8.5 },
{ 0.339, 3.38, 1.07 } } );
p.m02 = 0.388;
p.mp2 = 50.8;
p.mr2 = 0.838;
p.q02 = 1.87e-5;
p.lambda2 = 4.4e-9;
return p;
}
ALLM::Parameterisation
ALLM::Parameterisation::gd07p()
{
Parameterisation p;
p.pomeron = Parameters( {
{ 0.339, 0.127, 1.16 },
{ -0.105, -0.495, 1.29 },
{ -1.42, 4.51, 0.551 } } );
p.reggeon = Parameters( {
{ 0.838, 2.36, 1.77 },
{ 0.374, 0.998, 0.775 },
{ 2.71, 1.83, 1.26 } } );
p.m02 = 0.454;
p.mp2 = 30.7;
p.mr2 = 0.117;
p.q02 = 1.15;
p.lambda2 = 0.06527;
return p;
}
ALLM::Parameterisation
ALLM::Parameterisation::gd11p()
{
Parameterisation p;
p.pomeron = Parameters( {
{ 0.3638, 0.1211, 1.166 }, // c
{ -0.11895, -0.4783, 1.353 }, // a
{ 1.0833, 2.656, 1.771 } } ); // b
p.reggeon = Parameters( {
{ 1.3633, 2.256, 2.209 },
{ 0.3425, 1.0603, 0.5164 },
{ -10.408, 14.857, 0.07739 } } );
p.m02 = 0.5063;
p.mp2 = 34.75;
p.mr2 = 0.03190;
p.q02 = 1.374;
p.lambda2 = 0.06527;
return p;
}
ALLM
- ALLM::operator()( double q2, double xbj ) const
+ ALLM::operator()( double q2, double xbj, const SigmaRatio& rcomp ) const
{
const double factor = q2/( q2+params_.m02 );
const double W2_eff = q2*( 1.-xbj )/xbj;
const double xp = ( q2+params_.mp2 )/( q2+W2_eff+params_.mp2 ),
xr = ( q2+params_.mr2 )/( q2+W2_eff+params_.mr2 );
const double xlog1 = log( ( q2+params_.q02 )/ params_.lambda2 ), xlog2 = log( params_.q02/params_.lambda2 );
const double t = log( xlog1/xlog2 );
const double apom = params_.pomeron.a[0] + ( params_.pomeron.a[0]-params_.pomeron.a[1] )*( 1./( 1.+pow( t, params_.pomeron.a[2] ) ) - 1. );
const double bpom = params_.pomeron.b[0] + params_.pomeron.b[1]*pow( t, params_.pomeron.b[2] );
const double cpom = params_.pomeron.c[0] + ( params_.pomeron.c[0]-params_.pomeron.c[1] )*( 1./( 1.+pow( t, params_.pomeron.c[2] ) ) - 1. );
const double areg = params_.reggeon.a[0] + params_.reggeon.a[1]*pow( t, params_.reggeon.a[2] );
const double breg = params_.reggeon.b[0] + params_.reggeon.b[1]*pow( t, params_.reggeon.b[2] );
const double creg = params_.reggeon.c[0] + params_.reggeon.c[1]*pow( t, params_.reggeon.c[2] );
const double F2_Pom = cpom*pow( xp, apom )*pow( 1.-xbj, bpom ),
F2_Reg = creg*pow( xr, areg )*pow( 1.-xbj, breg );
ALLM allm;
allm.F2 = factor * ( F2_Pom + F2_Reg );
- const double R = ratio_comp_( q2, xbj );
- const double tau = 4.*xbj*xbj+Constants::mp*Constants::mp/q2;
+ const double R = rcomp( q2, xbj );
+ const double mp2 = ParticleProperties::mass( Proton )*ParticleProperties::mass( Proton );
+ const double tau = 4.*xbj*xbj*mp2/q2;
allm.FL = allm.F2 * ( 1.+tau ) * ( R/( 1.+R ) );
return allm;
}
}
}
diff --git a/CepGen/StructureFunctions/ALLM.h b/CepGen/StructureFunctions/ALLM.h
index cd8906f..7acd2e0 100644
--- a/CepGen/StructureFunctions/ALLM.h
+++ b/CepGen/StructureFunctions/ALLM.h
@@ -1,62 +1,61 @@
#ifndef CepGen_StructureFunctions_ALLM_h
#define CepGen_StructureFunctions_ALLM_h
#include "StructureFunctions.h"
#include "SigmaRatio.h"
#include <vector>
namespace CepGen
{
namespace SF
{
class ALLM : public StructureFunctions
{
public:
class Parameterisation
{
private:
struct Parameters {
Parameters() :
a( { 0., 0., 0. } ), b( { 0., 0., 0. } ), c( { 0., 0., 0. } ) {}
Parameters( std::vector<double> c, std::vector<double> a, std::vector<double> b ) :
a( a ), b( b ), c( c ) {}
std::vector<double> a, b, c;
};
public:
Parameterisation() :
m02( 0. ), mp2( 0. ), mr2( 0. ), q02( 0. ), lambda2( 0. ) {}
/// Pre-HERA data fit (694 data points)
static Parameterisation allm91();
/// Fixed target and HERA photoproduction total cross sections (1356 points)
static Parameterisation allm97();
static Parameterisation hht_allm();
static Parameterisation hht_allm_ft();
static Parameterisation gd07p();
static Parameterisation gd11p();
Parameters pomeron, reggeon;
/// Effective photon squared mass
double m02;
/// Effective pomeron squared mass
double mp2;
/// Effective reggeon squared mass
double mr2;
double q02;
/// Squared QCD scale
double lambda2;
};
- ALLM( const ALLM::Parameterisation& param = ALLM::Parameterisation::allm97(), const SigmaRatio& sr = E143Ratio() ) :
- params_( param ), ratio_comp_( sr ) {}
- ALLM operator()( double q2, double xbj ) const;
+ ALLM( const ALLM::Parameterisation& param = ALLM::Parameterisation::allm97() ) :
+ params_( param ) {}
+ ALLM operator()( double q2, double xbj, const SigmaRatio& rcomp = E143Ratio() ) const;
private:
Parameterisation params_;
- const SigmaRatio& ratio_comp_;
};
}
}
#endif
diff --git a/CepGen/StructureFunctions/CMakeLists.txt b/CepGen/StructureFunctions/CMakeLists.txt
index a76ce47..e4023af 100644
--- a/CepGen/StructureFunctions/CMakeLists.txt
+++ b/CepGen/StructureFunctions/CMakeLists.txt
@@ -1,26 +1,37 @@
file(GLOB sf_sources *.cpp)
set(sources ${sf_sources})
include_directories(${PROJECT_SOURCE_DIR})
#----- check the external dependencies
set(GRV_PATH ${PROJECT_SOURCE_DIR}/External)
file(GLOB grv_sources ${GRV_PATH}/grv_*.f)
if(grv_sources)
message(STATUS "GRV PDFset found in ${grv_sources}!")
add_definitions(-DGRVPDF)
list(APPEND sources ${grv_sources})
else()
message(STATUS "GRV PDFset not found. Will proceed without it")
endif()
+set(SCH_PATH ${PROJECT_SOURCE_DIR}/External/F2_Luxlike_fit)
+file(GLOB sch_sources ${SCH_PATH}/F2_luxlike_minimal.f ${PROJECT_SOURCE_DIR}/CepGen/IO/MSTWGridHandler.cpp)
+if(sch_sources)
+ message(STATUS "LUXlike structure functions found!")
+ add_definitions(-DSchaeferF2)
+ list(APPEND sources ${sch_sources})
+ configure_file(${SCH_PATH}/mstw_f2_scan_nnlo.dat ${PROJECT_BINARY_DIR}/External/F2_Luxlike_fit/mstw_f2_scan_nnlo.dat COPYONLY)
+else()
+ message(STATUS "LUXlike structure functions not found")
+endif()
+
#----- build the object
add_library(CepGenStructureFunctions SHARED ${sources})
target_link_libraries(CepGenStructureFunctions ${external_deps})
#----- installation rules
install(TARGETS CepGenStructureFunctions DESTINATION lib)
diff --git a/CepGen/StructureFunctions/ChristyBosted.cpp b/CepGen/StructureFunctions/ChristyBosted.cpp
index f4e0eb1..3723856 100644
--- a/CepGen/StructureFunctions/ChristyBosted.cpp
+++ b/CepGen/StructureFunctions/ChristyBosted.cpp
@@ -1,260 +1,275 @@
#include "ChristyBosted.h"
#include "CepGen/Event/Particle.h"
#include "CepGen/Core/Exception.h"
namespace CepGen
{
namespace SF
{
double
ChristyBosted::resmod507( char sf, double w2, double q2 ) const
{
- const double mp = Constants::mp, mp2 = mp*mp,
- mpi = Constants::mpi, mpi2 = mpi*mpi,
- meta = Particle::massFromPDGId( Particle::Eta ), meta2 = meta*meta;
+ const double mp = ParticleProperties::mass( Proton ), mp2 = mp*mp,
+ mpi = ParticleProperties::mass( PiZero ), mpi2 = mpi*mpi,
+ meta = ParticleProperties::mass( Eta ), meta2 = meta*meta;
const double w = sqrt( w2 );
const double xb = q2/( q2+w2-mp2 );
double m0 = 0., q20 = 0.;
if ( sf == 'T' ) { // transverse
m0 = 0.125;
q20 = 0.05;
}
else if ( sf == 'L' ) {
m0 = params_.m0;
q20 = 0.125;
}
else {
InError( "Invalid direction retrieved! Aborting." )
return 0.;
}
const double norm_q2 = 1./0.330/0.330;
const double t = log( log( ( q2+m0 )*norm_q2 )/log( m0*norm_q2 ) );
//--- calculate kinematics needed for threshold relativistic B-W
// equivalent photon energies
const double k = 0.5 * ( w2 - mp2 )/mp;
const double kcm = 0.5 * ( w2 - mp2 )/w;
const double epicm = 0.5 * ( w2 + mpi2 - mp2 )/w, ppicm = sqrt( std::max( 0., epicm* epicm - mpi2 ) );
const double epi2cm = 0.5 * ( w2 + 4.*mpi2 - mp2 )/w, ppi2cm = sqrt( std::max( 0., epi2cm*epi2cm - 4*mpi2 ) );
const double eetacm = 0.5 * ( w2 + meta2 - mp2 )/w, petacm = sqrt( std::max( 0., eetacm*eetacm - meta2 ) );
std::array<double,7> width, height, pgam;
for ( unsigned short i = 0; i < 7; ++i ) {
const Parameterisation::ResonanceParameters& res = params_.resonances[i];
width[i] = res.width;
//--- calculate partial widths
//----- 1-pion decay mode
const double x02 = res.x0*res.x0;
const double partial_width_singlepi = pow( ppicm /res.pcmr( mpi2 ), 2.*res.angular_momentum+1. )
* pow( ( res.pcmr( mpi2 )*res.pcmr( mpi2 )+x02 )/( ppicm *ppicm +x02 ), res.angular_momentum );
//----- 2-pion decay mode
const double partial_width_doublepi = pow( ppi2cm/res.pcmr( 4.*mpi2 ), 2.*( res.angular_momentum+2. ) )
* pow( ( res.pcmr( 4.*mpi2 )*res.pcmr( 4.*mpi2 )+x02 )/( ppi2cm*ppi2cm+x02 ), res.angular_momentum+2 )
* w / res.mass;
//----- eta decay mode (only for S11's)
const double partial_width_eta = ( res.br.eta == 0. ) ? 0. :
pow( petacm/res.pcmr( meta2 ), 2.*res.angular_momentum+1. )
* pow( ( res.pcmr( meta2 )*res.pcmr( meta2 )+x02 )/( petacm*petacm+x02 ), res.angular_momentum );
// virtual photon width
pgam[i] = res.width * pow( kcm/res.kcmr(), 2 ) * ( res.kcmr()*res.kcmr()+x02 )/( kcm*kcm+x02 );
width[i] = ( partial_width_singlepi * res.br.singlepi
+ partial_width_doublepi * res.br.doublepi
+ partial_width_eta * res.br.eta ) * res.width;
//--- resonance Q^2 dependence calculations
if ( sf == 'T' ) height[i] = res.A0_T*( 1.+res.fit_parameters[0]*q2/( 1.+res.fit_parameters[1]*q2 ) )/pow( 1.+q2/0.91, res.fit_parameters[2] );
else if ( sf == 'L' ) height[i] = res.A0_L/( 1.+res.fit_parameters[3]*q2 )*q2*exp( -q2*res.fit_parameters[4] );
height[i] = height[i]*height[i];
}
//--- calculate Breit-Wigners for all resonances
double sig_res = 0.;
for ( unsigned short i = 0; i < 7; ++i ) {
const Parameterisation::ResonanceParameters res = params_.resonances[i];
const double mass2 = res.mass*res.mass, width2 = width[i]*width[i];
const double sigr = height[i]*res.kr()/k*res.kcmr()/kcm/res.width * ( width[i]*pgam[i] / ( pow( w2-mass2, 2 ) + mass2*width2 ) );
sig_res += sigr;
}
sig_res *= w;
//--- non-resonant background calculation
const double xpr = 1./( 1.+( w2-pow( mp+mpi, 2 ) )/( q2+q20 ) );
if ( xpr > 1. ) return 0.; // FIXME
double sig_nr = 0.;
if ( sf == 'T' ) { // transverse
const double wdif = w - ( mp + mpi );
if ( wdif >= 0. ) {
for ( unsigned short i = 0; i < 2; ++i ) {
const double expo = params_.continuum.transverse[i].fit_parameters[1]
+ params_.continuum.transverse[i].fit_parameters[2]*q2
+ params_.continuum.transverse[i].fit_parameters[3]*q2*q2;
sig_nr += params_.continuum.transverse[i].sig0 / pow( q2+params_.continuum.transverse[i].fit_parameters[0], expo ) * pow( wdif, i+1.5 );
}
}
sig_nr *= xpr;
}
else if ( sf == 'L' ) { // longitudinal
for ( unsigned short i = 0; i < 1; ++i ) {
const double expo = params_.continuum.longitudinal[i].fit_parameters[0]
+ params_.continuum.longitudinal[i].fit_parameters[1];
sig_nr += params_.continuum.longitudinal[i].sig0
* pow( 1.-xpr, expo )/( 1.-xb )
* pow( q2/( q2+q20 ), params_.continuum.longitudinal[i].fit_parameters[2] )/( q2+q20 )
* pow( xpr, params_.continuum.longitudinal[i].fit_parameters[3]+params_.continuum.longitudinal[i].fit_parameters[4]*t );
}
}
return sig_res + sig_nr;
}
ChristyBosted::Parameterisation
ChristyBosted::Parameterisation::standard()
{
Parameterisation params;
params.m0 = 4.2802;
params.continuum.transverse = { {
ContinuumParameters::DirectionParameters( 246.06, { { 0.067469, 1.3501, 0.12054, -0.0038495 } } ),
ContinuumParameters::DirectionParameters( -89.360, { { 0.20977, 1.5715, 0.090736, 0.010362 } } )
} };
params.continuum.longitudinal = { {
ContinuumParameters::DirectionParameters( 86.746, { { 0., 4.0294, 3.1285, 0.33403, 4.9623 } } )
} };
//--- P33(1232)
ResonanceParameters p33;
p33.br = ResonanceParameters::BranchingRatios( 1., 0., 0. );
p33.angular_momentum = 1.;
//p33.x0 = 0.15;
p33.x0 = 0.14462;
p33.mass = 1.2298;
p33.width = 0.13573;
p33.fit_parameters = { { 4.2291, 1.2598, 2.1242, 19.910, 0.22587 } };
p33.A0_T = 7.7805;
p33.A0_L = 29.414;
params.resonances.emplace_back( p33 );
//--- S11(1535)
ResonanceParameters s11_1535;
s11_1535.br = ResonanceParameters::BranchingRatios( 0.45, 0.1, 0.45 );
s11_1535.angular_momentum = 0.;
s11_1535.x0 = 0.215;
s11_1535.mass = 1.5304;
s11_1535.width = 0.220;
s11_1535.fit_parameters = { { 6823.2, 33521., 2.5686, 0., 0. } };
s11_1535.A0_T = 6.3351;
s11_1535.A0_L = 0.;
params.resonances.emplace_back( s11_1535 );
//--- D13(1520)
ResonanceParameters d13;
d13.br = ResonanceParameters::BranchingRatios( 0.65, 0.35, 0. );
d13.angular_momentum = 2.;
d13.x0 = 0.215;
d13.mass = 1.5057;
d13.width = 0.082956;
d13.fit_parameters = { { 21.240, 0.055746, 2.4886, 97.046, 0.31042 } };
d13.A0_T = 0.60347;
d13.A0_L = 157.92;
params.resonances.emplace_back( d13 );
//--- F15(1680)
ResonanceParameters f15;
f15.br = ResonanceParameters::BranchingRatios( 0.65, 0.35, 0. );
f15.angular_momentum = 3.;
f15.x0 = 0.215;
f15.mass = 1.6980;
f15.width = 0.095782;
f15.fit_parameters = { { -0.28789, 0.18607, 0.063534, 0.038200, 1.2182 } };
f15.A0_T = 2.3305;
f15.A0_L = 4.2160;
params.resonances.emplace_back( f15 );
//--- S11(1650)
ResonanceParameters s11_1650;
s11_1650.br = ResonanceParameters::BranchingRatios( 0.4, 0.5, 0.1 );
s11_1650.angular_momentum = 0.;
s11_1650.x0 = 0.215;
s11_1650.mass = 1.6650;
s11_1650.width = 0.10936;
s11_1650.fit_parameters = { { -0.56175, 0.38964, 0.54883, 0.31393, 2.9997 } };
s11_1650.A0_T = 1.9790;
s11_1650.A0_L = 13.764;
params.resonances.emplace_back( s11_1650 );
//--- P11(1440) roper
ResonanceParameters p11;
p11.br = ResonanceParameters::BranchingRatios( 0.65, 0.35, 0. );
p11.angular_momentum = 1.;
p11.x0 = 0.215;
p11.mass = 1.4333;
p11.width = 0.37944;
p11.fit_parameters = { { 46.213, 0.19221, 1.9141, 0.053743, 1.3091 } };
p11.A0_T = 0.022506;
p11.A0_L = 5.5124;
params.resonances.emplace_back( p11 );
//--- F37(1950)
ResonanceParameters f37;
f37.br = ResonanceParameters::BranchingRatios( 0.5, 0.5, 0. );
f37.angular_momentum = 3.;
f37.x0 = 0.215;
f37.mass = 1.9341;
f37.width = 0.380;
f37.fit_parameters = { { 0., 0., 1., 1.8951, 0.51376 } };
f37.A0_T = 3.4187;
f37.A0_L = 1.8951;
params.resonances.emplace_back( f37 );
return params;
}
+ double
+ ChristyBosted::Parameterisation::ResonanceParameters::kr() const
+ {
+ const double mp = ParticleProperties::mass( Proton ), mp2 = mp*mp;
+ return 0.5 * ( mass*mass-mp2 ) / mp;
+ }
+
+ double
+ ChristyBosted::Parameterisation::ResonanceParameters::ecmr( double m2 ) const
+ {
+ if ( mass == 0. ) return 0.;
+ const double mp = ParticleProperties::mass( Proton ), mp2 = mp*mp;
+ return 0.5 * ( mass*mass+m2-mp2 ) / mass;
+ }
+
ChristyBosted
ChristyBosted::operator()( double q2, double xbj ) const
{
- const double mp2 = Constants::mp*Constants::mp;
+ const double mp = ParticleProperties::mass( Proton ), mp2 = mp*mp;
const double w2 = mp2 + q2*( 1.-xbj )/xbj;
- const double w_min = Constants::mp+Constants::mpi;
+ const double w_min = mp+ParticleProperties::mass( PiZero );
ChristyBosted cb;
if ( sqrt( w2 ) < w_min ) return cb;
//-----------------------------
// modification of Christy-Bosted at large q2 as described in the LUXqed paper
//-----------------------------
const double q21 = 30., q20 = 8.;
const double delq2 = q2 - q20;
const double qq = q21 - q20;
const double prefac = 1./( 4.*M_PI*M_PI*Constants::alphaEM ) * ( 1.-xbj );
//------------------------------
double q2_eff = q2, w2_eff = w2;
if ( q2 > q20 ) {
q2_eff = q20 + delq2/( 1.+delq2/qq );
w2_eff = mp2 + q2_eff*( 1.-xbj )/xbj;
}
const double tau = 4.*xbj*xbj*mp2/q2_eff;
const double sigT = resmod507( 'T', w2_eff, q2_eff ), sigL = resmod507( 'L', w2_eff, q2_eff );
cb.F2 = prefac * q2_eff / ( 1+tau ) * ( sigT+sigL ) / Constants::GeV2toBarn * 1.e6;
if ( q2 > q20 ) cb.F2 *= q21/( q21 + delq2 );
if ( sigT != 0. ) {
const double R = sigL/sigT;
cb.FL = cb.F2*( 1+tau )*R/( 1.+R );
}
return cb;
}
}
}
diff --git a/CepGen/StructureFunctions/ChristyBosted.h b/CepGen/StructureFunctions/ChristyBosted.h
index 0cd65aa..33cc862 100644
--- a/CepGen/StructureFunctions/ChristyBosted.h
+++ b/CepGen/StructureFunctions/ChristyBosted.h
@@ -1,80 +1,80 @@
#ifndef CepGen_StructureFunctions_ChristyBosted_h
#define CepGen_StructureFunctions_ChristyBosted_h
#include "StructureFunctions.h"
#include "CepGen/Physics/Constants.h"
#include <array>
#include <vector>
namespace CepGen
{
namespace SF
{
class ChristyBosted : public StructureFunctions
{
public:
struct Parameterisation
{
static Parameterisation standard();
struct ResonanceParameters
{
struct BranchingRatios
{
BranchingRatios() : singlepi( 0. ), doublepi( 0. ), eta( 0. ) {}
BranchingRatios( double singlepi, double doublepi, double eta ) : singlepi( singlepi ), doublepi( doublepi ), eta( eta ) {}
bool valid() const { return ( singlepi+doublepi+eta == 1. ); }
/// single pion branching ratio
double singlepi;
/// double pion branching ratio
double doublepi;
/// eta meson branching ratio
double eta;
};
ResonanceParameters() : angular_momentum( 0. ), x0( 0. ), mass( 0. ), width( 0. ), A0_T( 0. ), A0_L( 0. ) {}
- double kr() const { return 0.5 * ( mass*mass-Constants::mp*Constants::mp )/Constants::mp; }
- double ecmr( double m2 ) const { return ( mass == 0. ) ? 0. : 0.5 * ( mass*mass+m2-Constants::mp*Constants::mp ) / mass; }
+ double kr() const;
+ double ecmr( double m2 ) const;
double kcmr() const { return ecmr( 0. ); }
double pcmr( double m2 ) const { return sqrt( std::max( 0., ecmr( m2 )*ecmr( m2 )-m2 ) ); }
BranchingRatios br;
/// meson angular momentum
double angular_momentum;
/// damping parameter
double x0;
/// mass, in GeV/c2
double mass;
/// full width, in GeV
double width;
double A0_T;
double A0_L;
std::array<double,5> fit_parameters;
};
struct ContinuumParameters
{
struct DirectionParameters
{
DirectionParameters() : sig0( 0. ) {}
DirectionParameters( double sig0, const std::vector<double>& params ) : sig0( sig0 ), fit_parameters( params ) {}
double sig0;
std::vector<double> fit_parameters;
};
std::array<DirectionParameters,2> transverse;
std::array<DirectionParameters,1> longitudinal;
};
double m0;
std::vector<ResonanceParameters> resonances;
ContinuumParameters continuum;
};
ChristyBosted( const ChristyBosted::Parameterisation& params = ChristyBosted::Parameterisation::standard() ) : params_( params ) {}
ChristyBosted operator()( double q2, double xbj ) const;
private:
double resmod507( char sf, double w2, double q2 ) const;
Parameterisation params_;
};
}
}
#endif
diff --git a/CepGen/StructureFunctions/FioreBrasse.cpp b/CepGen/StructureFunctions/FioreBrasse.cpp
index 2f9876d..bcad748 100644
--- a/CepGen/StructureFunctions/FioreBrasse.cpp
+++ b/CepGen/StructureFunctions/FioreBrasse.cpp
@@ -1,157 +1,159 @@
#include "FioreBrasse.h"
#include "CepGen/Core/Exception.h"
#include "CepGen/Core/utils.h"
+#include "CepGen/Physics/ParticleProperties.h"
+#include "CepGen/Physics/Constants.h"
#include <complex>
namespace CepGen
{
namespace SF
{
FioreBrasse::Parameterisation
FioreBrasse::Parameterisation::standard()
{
Parameterisation p;
p.s0 = 1.14;
p.norm = 0.021;
p.resonances.emplace_back( -0.8377, 0.95, 0.1473, 1.0, 2.4617, 3./2. );
p.resonances.emplace_back( -0.37, 0.95, 0.1471, 0.5399, 2.4617, 5./2. );
p.resonances.emplace_back( 0.0038, 0.85, 0.1969, 4.2225, 1.5722, 3./2. );
p.resonances.emplace_back( 0.5645, 0.1126, 1.3086, 19.2694, 4.5259, 1. );
return p;
}
FioreBrasse::Parameterisation
FioreBrasse::Parameterisation::alternative()
{
Parameterisation p;
p.s0 = 1.2871;
p.norm = 0.0207;
p.resonances.emplace_back( -0.8070, 0.9632, 0.1387, 1.0, 2.6066, 3./2. );
p.resonances.emplace_back( -0.3640, 0.9531, 0.1239, 0.6086, 2.6066, 5./2. );
p.resonances.emplace_back( -0.0065, 0.8355, 0.2320, 4.7279, 1.4828, 3./2. );
p.resonances.emplace_back( 0.5484, 0.1373, 1.3139, 14.7267, 4.6041, 1. );
return p;
}
FioreBrasse
FioreBrasse::operator()( double q2, double xbj ) const
{
- const double mp2 = Constants::mp*Constants::mp;
+ const double mp = ParticleProperties::mass( Proton ), mp2 = mp*mp;
const double akin = 1. + 4.*mp2 * xbj*xbj/q2;
const double prefactor = q2*( 1.-xbj ) / ( 4.*M_PI*Constants::alphaEM*akin );
const double s = q2*( 1.-xbj )/xbj + mp2;
double ampli_res = 0., ampli_tot = 0.;
for ( unsigned short i = 0; i < 3; ++i ) { //FIXME 4??
const Parameterisation::ResonanceParameters res = params_.resonances[i];
if ( !res.enabled ) continue;
const double sqrts0 = sqrt( params_.s0 );
std::complex<double> alpha;
if ( s > params_.s0 )
alpha = std::complex<double>( res.alpha0 + res.alpha2*sqrts0 + res.alpha1*s, res.alpha2*sqrt( s-params_.s0 ) );
else
alpha = std::complex<double>( res.alpha0 + res.alpha1*s + res.alpha2*( sqrts0 - sqrt( params_.s0 - s ) ), 0. );
double formfactor = 1./pow( 1. + q2/res.q02, 2 );
double denom = pow( res.spin-std::real( alpha ), 2 ) + pow( std::imag( alpha ), 2 );
double ampli_imag = res.a*formfactor*formfactor*std::imag( alpha )/denom;
ampli_res += ampli_imag;
}
{
const Parameterisation::ResonanceParameters res = params_.resonances[3];
double sE = res.alpha2, sqrtsE = sqrt( sE );
std::complex<double> alpha;
if ( s > sE )
alpha = std::complex<double>( res.alpha0 + res.alpha1*sqrtsE, res.alpha1*sqrt( s-sE ) );
else
alpha = std::complex<double>( res.alpha0 + res.alpha1*( sqrtsE - sqrt( sE-s ) ), 0. );
double formfactor = 1./pow( 1. + q2/res.q02, 2 );
double sp = 1.5*res.spin;
double denom = pow( sp-std::real( alpha ), 2 ) + pow( std::imag( alpha ), 2 );
double ampli_bg = res.a*formfactor*formfactor*std::imag( alpha )/denom;
ampli_res += ampli_bg;
}
ampli_tot = params_.norm*ampli_res;
FioreBrasse fb;
fb.F2 = prefactor*ampli_tot;
return fb;
}
FioreBrasse
FioreBrasse::operator()( double q2, double xbj, bool ) const
{
- const double mp2 = Constants::mp*Constants::mp;
+ const double mp = ParticleProperties::mass( Proton ), mp2 = mp*mp;
//const double m_min = Particle::massFromPDGId(Particle::Proton)+0.135;
- const double m_min = Constants::mp+Constants::mpi;
+ const double m_min = mp+ParticleProperties::mass( PiZero );
const double mx2 = mp2 + q2*( 1.-xbj )/xbj, mx = sqrt( mx2 );
FioreBrasse fb;
if ( mx < m_min || mx > 1.99 ) {
InWarning( Form( "Fiore-Brasse form factors to be retrieved for an invalid MX value:\n\t"
"%.2e GeV, while allowed range is [1.07, 1.99] GeV", mx ) );
return fb;
}
int n_bin;
double x_bin, dx;
if ( mx < 1.11 ) {
n_bin = 0;
x_bin = mx-m_min;
dx = 1.11-m_min; // Delta w bin sizes
}
else if ( mx < 1.77 ) { // w in [1.11, 1.77[
dx = 0.015; // Delta w bin sizes
n_bin = ( mx-1.11 )/dx + 1;
x_bin = fmod( mx-1.11, dx );
}
else { // w in [1.77, 1.99[
dx = 0.02; // Delta w bin sizes
n_bin = ( mx-1.77 )/dx + 45;
x_bin = fmod( mx-1.77, dx );
}
// values of a, b, c provided from the fits on ep data and retrieved from
// http://dx.doi.org/10.1016/0550-3213(76)90231-5 with 1.110 <= w2 <=1.990
const double a[56] = { 5.045, 5.126, 5.390,5.621, 5.913, 5.955,6.139,6.178,6.125, 5.999,
5.769, 5.622, 5.431,5.288, 5.175, 5.131,5.003,5.065,5.045, 5.078,
5.145, 5.156, 5.234,5.298, 5.371, 5.457,5.543,5.519,5.465, 5.384,
5.341, 5.320, 5.275,5.290, 5.330, 5.375,5.428,5.478,5.443, 5.390,
5.333, 5.296, 5.223,5.159, 5.146, 5.143,5.125,5.158,5.159, 5.178,
5.182, 5.195, 5.160,5.195, 5.163, 5.172 },
b[56] = { 0.798, 1.052, 1.213,1.334,1.397,1.727,1.750,1.878,1.887,1.927,
2.041, 2.089, 2.148,2.205,2.344,2.324,2.535,2.464,2.564,2.610,
2.609, 2.678, 2.771,2.890,2.982,3.157,3.183,3.315,3.375,3.450,
3.477, 3.471, 3.554,3.633,3.695,3.804,3.900,4.047,4.290,4.519,
4.709, 4.757, 4.840,5.017,5.015,5.129,5.285,5.322,5.545,5.623,
5.775, 5.894, 6.138,6.151,6.301,6.542 },
c[56] = { 0.043, 0.024, 0.000,-0.013,-0.023,-0.069,-0.060,-0.080,-0.065,-0.056,
-0.065,-0.056,-0.043,-0.034,-0.054,-0.018,-0.046,-0.015,-0.029,-0.048,
-0.032,-0.045,-0.084,-0.115,-0.105,-0.159,-0.164,-0.181,-0.203,-0.223,
-0.245,-0.254,-0.239,-0.302,-0.299,-0.318,-0.383,-0.393,-0.466,-0.588,
-0.622,-0.568,-0.574,-0.727,-0.665,-0.704,-0.856,-0.798,-1.048,-0.980,
-1.021,-1.092,-1.313,-1.341,-1.266,-1.473 };
const double d = 3.0;
- const double nu = 0.5 * ( q2 + mx2 - mp2 ) / Constants::mp, nu2 = nu*nu,
- logqq0 = 0.5 * log( ( nu2+q2 ) / pow( ( mx2-mp2 ) / ( 2.*Constants::mp ), 2 ) );
+ const double nu = 0.5 * ( q2 + mx2 - mp2 ) / mp, nu2 = nu*nu,
+ logqq0 = 0.5 * log( ( nu2+q2 ) / pow( ( mx2-mp2 ) / ( 2.*mp ), 2 ) );
const double gd2 = pow( 1. / ( 1+q2 / .71 ), 4 ); // dipole form factor of the proton
const double sigLow = ( n_bin == 0 ) ? 0. :
gd2 * exp( a[n_bin-1] + b[n_bin-1]*logqq0 + c[n_bin-1]*pow( fabs( logqq0 ), d ) );
const double sigHigh =
gd2 * exp( a[n_bin] + b[n_bin] *logqq0 + c[n_bin] *pow( fabs( logqq0 ), d ) );
const double sigma_t = sigLow + x_bin*( sigHigh-sigLow )/dx;
- const double w1 = ( mx2-mp2 )/( 8.*M_PI*M_PI*Constants::mp*Constants::alphaEM )/Constants::GeV2toBarn*1.e6 * sigma_t;
+ const double w1 = ( mx2-mp2 )/( 8.*M_PI*M_PI*mp*Constants::alphaEM )/Constants::GeV2toBarn*1.e6 * sigma_t;
const double w2 = w1 * q2 / ( q2+nu2 );
fb.W1 = w1; //FIXME
fb.W2 = w2; //FIXME
return fb;
}
}
}
diff --git a/CepGen/StructureFunctions/FioreBrasse.h b/CepGen/StructureFunctions/FioreBrasse.h
index 134afbe..86651b6 100644
--- a/CepGen/StructureFunctions/FioreBrasse.h
+++ b/CepGen/StructureFunctions/FioreBrasse.h
@@ -1,49 +1,48 @@
#ifndef CepGen_StructureFunctions_FioreBrasse_h
#define CepGen_StructureFunctions_FioreBrasse_h
-#include "CepGen/Physics/Constants.h"
#include "CepGen/StructureFunctions/StructureFunctions.h"
#include <vector>
namespace CepGen
{
namespace SF
{
class FioreBrasse : public StructureFunctions
{
public:
struct Parameterisation
{
static Parameterisation standard();
static Parameterisation alternative();
struct ResonanceParameters {
ResonanceParameters( double a0, double a1, double a2, double a, double q02, float spin, bool on=true ) :
alpha0( a0 ), alpha1( a1 ), alpha2( a2 ), a( a ), q02( q02 ), spin( spin ), enabled( on ) {}
double alpha0, alpha1, alpha2, a, q02;
float spin;
bool enabled;
};
std::vector<ResonanceParameters> resonances;
double s0, norm;
};
/// Fiore-Brasse proton structure functions (F.W Brasse et al., DESY 76/11 (1976),
/// http://dx.doi.org/10.1016/0550-3213(76)90231-5)
FioreBrasse( const FioreBrasse::Parameterisation& params = FioreBrasse::Parameterisation::standard() ) : params_( params ) {}
/// \param[in] q2 Squared 4-momentum transfer
/// \param[in] xbj Bjorken's x
/// \cite Brasse1976413
FioreBrasse operator()( double q2, double xbj ) const;
FioreBrasse operator()( double q2, double xbj, bool old ) const;
double W1, W2;
private:
Parameterisation params_;
};
}
}
#endif
diff --git a/CepGen/StructureFunctions/Schaefer.cpp b/CepGen/StructureFunctions/Schaefer.cpp
new file mode 100644
index 0000000..7a05b1c
--- /dev/null
+++ b/CepGen/StructureFunctions/Schaefer.cpp
@@ -0,0 +1,35 @@
+#include "Schaefer.h"
+#include "CepGen/Physics/Constants.h"
+#include "CepGen/Physics/ParticleProperties.h"
+
+namespace CepGen
+{
+ namespace SF
+ {
+ Schaefer::Schaefer()
+ {
+#ifdef SchaeferF2
+ luxlike_params_.amp = ParticleProperties::mass( Proton );
+ luxlike_params_.alpha_em = Constants::alphaEM;
+ luxlike_params_.q2_cut = 9.;
+ luxlike_params_.w2_hi = 4.;
+ luxlike_params_.w2_lo = 3.;
+ luxlike_params_.res_model = ChristyBosted;
+ luxlike_params_.cont_model = GD11p;
+#endif
+ }
+
+ Schaefer
+ Schaefer::operator()( double q2, double xbj ) const
+ {
+ Schaefer luxlike;
+#ifndef SchaeferF2
+ FatalError( "LUXlike structure functions cannot be computed "
+ "as the Fortran subroutine is not linked to this instance!" );
+#else
+ f2_fit_luxlike_( xbj, q2, luxlike.F2, luxlike.FL );
+#endif
+ return luxlike;
+ }
+ }
+}
diff --git a/CepGen/StructureFunctions/Schaefer.h b/CepGen/StructureFunctions/Schaefer.h
new file mode 100644
index 0000000..eb76059
--- /dev/null
+++ b/CepGen/StructureFunctions/Schaefer.h
@@ -0,0 +1,36 @@
+#ifndef CepGen_StructureFunctions_Schaefer_h
+#define CepGen_StructureFunctions_Schaefer_h
+
+#include "StructureFunctions.h"
+
+#ifdef SchaeferF2
+extern "C"
+{
+ extern void f2_fit_luxlike_( double& xbj, double& q2, double& F2, double& FL );
+ extern struct
+ {
+ double amp, alpha_em;
+ double q2_cut, w2_lo, w2_hi;
+ int res_model, cont_model;
+ } luxlike_params_;
+}
+#endif
+
+namespace CepGen
+{
+ namespace SF
+ {
+ class Schaefer : public StructureFunctions
+ {
+ public:
+ Schaefer();
+ Schaefer operator()( double q2, double xbj ) const;
+
+ private:
+ enum ResonancesModel { ChristyBosted = 1, FioreBrasse = 2 };
+ enum ContinuumModel { GD11p = 1, ALLM91 = 2, ALLM97 = 3 };
+ };
+ }
+}
+
+#endif
diff --git a/CepGen/StructureFunctions/SigmaRatio.cpp b/CepGen/StructureFunctions/SigmaRatio.cpp
new file mode 100644
index 0000000..a938d7f
--- /dev/null
+++ b/CepGen/StructureFunctions/SigmaRatio.cpp
@@ -0,0 +1,45 @@
+#include "SigmaRatio.h"
+#include <math.h>
+#include <iostream>
+
+namespace CepGen
+{
+ namespace SF
+ {
+ E143Ratio::Parameterisation
+ E143Ratio::Parameterisation::standard()
+ {
+ Parameterisation out;
+ out.q2_b = 0.34;
+ out.a = { { 0.0485, 0.5470, 2.0621, -0.3804, 0.5090, -0.0285 } };
+ out.b = { { 0.0481, 0.6114, -0.3509, -0.4611, 0.7172, -0.0317 } };
+ out.c = { { 0.0577, 0.4644, 1.8288, 12.3708, -43.1043, 41.7415 } };
+ return out;
+ }
+
+ double
+ E143Ratio::operator()( double q2, double xbj ) const
+ {
+ const double u = q2/params_.q2_b;
+ const double xl = log( 25.*q2 );
+ const double pa = ( 1.+params_.a[3]*xbj+params_.a[4]*xbj*xbj )*pow( xbj, params_.a[5] );
+ const double pb = ( 1.+params_.b[3]*xbj+params_.b[4]*xbj*xbj )*pow( xbj, params_.b[5] );
+ const double tt = theta( q2, xbj );
+ const double q2_thr = params_.c[3]*xbj + params_.c[4]*xbj*xbj+params_.c[5]*xbj*xbj*xbj;
+ const double ra = params_.a[0]/xl*tt + params_.a[1]/pow( pow( q2, 4 )+pow( params_.a[2], 4 ), 0.25 )*pa,
+ rb = params_.b[0]/xl*tt + ( params_.b[1]/q2+params_.b[2]/( q2*q2+0.3*0.3 ) )*pb,
+ rc = params_.c[0]/xl*tt + params_.c[1]*pow( pow( q2-q2_thr, 2 )+pow( params_.c[2], 2 ), -0.5 );
+
+ const double r = ( ra+rb+rc ) / 3.;
+ if ( q2 > params_.q2_b ) return r;
+ return r * 0.5 * ( 3.*u-u*u*u );
+ }
+
+ double
+ E143Ratio::theta( double q2, double xbj ) const
+ {
+ return 1.+12.*( q2/( q2+1. ) )*( 0.125*0.125/( 0.125*0.125+xbj*xbj ) );
+ }
+ }
+}
+
diff --git a/CepGen/StructureFunctions/SigmaRatio.h b/CepGen/StructureFunctions/SigmaRatio.h
index 80ea0df..1e6c72c 100644
--- a/CepGen/StructureFunctions/SigmaRatio.h
+++ b/CepGen/StructureFunctions/SigmaRatio.h
@@ -1,62 +1,37 @@
#ifndef CepGen_StructureFunctions_SigmaRatio_h
#define CepGen_StructureFunctions_SigmaRatio_h
#include <array>
-#include <cmath>
namespace CepGen
{
namespace SF
{
class SigmaRatio
{
public:
SigmaRatio() {}
- virtual double operator()( double q2, double xbj ) const { return 0.; }
+ virtual double operator()( double q2, double xbj ) const = 0;
};
class E143Ratio : public SigmaRatio
{
public:
struct Parameterisation
{
double q2_b;
std::array<double,6> a, b, c;
- static Parameterisation standard() {
- Parameterisation out;
- out.q2_b = 0.34;
- out.a = { { 0.0485, 0.5470, 2.0621, -0.3804, 0.5090, -0.0285 } };
- out.b = { { 0.0481, 0.6114, -0.3509, -0.4611, 0.7172, -0.0317 } };
- out.c = { { 0.0577, 0.4644, 1.8288, 12.3708, -43.1043, 41.7415 } };
- return out;
- }
+ static Parameterisation standard();
};
E143Ratio( const Parameterisation& param = Parameterisation::standard() ) : params_( param ) {}
- double operator()( double q2, double xbj ) const override
- {
- const double u = q2/params_.q2_b;
- const double xl = log( 25.*q2 );
- const double pa = ( 1.+params_.a[3]*xbj+params_.a[4]*xbj*xbj )*pow( xbj, params_.a[5] );
- const double pb = ( 1.+params_.b[3]*xbj+params_.b[4]*xbj*xbj )*pow( xbj, params_.b[5] );
- const double tt = theta( q2, xbj );
- const double q2_thr = params_.c[3]*xbj + params_.c[4]*xbj*xbj+params_.c[5]*xbj*xbj*xbj;
- const double ra = params_.a[0]/xl*tt + params_.a[1]/pow( pow( q2, 4 )+pow( params_.a[2], 4 ), 0.25 )*pa,
- rb = params_.b[0]/xl*tt + ( params_.b[1]/q2+params_.b[2]/( q2*q2+0.3*0.3 ) )*pb,
- rc = params_.c[0]/xl*tt + params_.c[1]*pow( pow( q2-q2_thr, 2 )+pow( params_.c[2], 2 ), -0.5 );
-
- const double r = ( ra+rb+rc ) / 3.;
- if ( q2 > params_.q2_b ) return r;
- return r * 0.5 * ( 3.*u-u*u*u );
- }
+ double operator()( double q2, double xbj ) const override;
private:
- double theta( double q2, double xbj ) const {
- return 1.+12.*( q2/( q2+1. ) )*( 0.125*0.125/( 0.125*0.125+xbj*xbj ) );
- }
+ double theta( double q2, double xbj ) const;
Parameterisation params_;
};
}
}
#endif
diff --git a/CepGen/StructureFunctions/StructureFunctions.cpp b/CepGen/StructureFunctions/StructureFunctions.cpp
index fb00939..02aa89d 100644
--- a/CepGen/StructureFunctions/StructureFunctions.cpp
+++ b/CepGen/StructureFunctions/StructureFunctions.cpp
@@ -1,31 +1,33 @@
#include "StructureFunctions.h"
#include <iostream>
namespace CepGen
{
/// Human-readable format of a structure function object
std::ostream&
operator<<( std::ostream& os, const StructureFunctions& sf )
{
return os << "F2 = " << sf.F2 << ", FL = " << sf.FL;
}
/// Human-readable format of a structure function type
std::ostream&
operator<<( std::ostream& os, const StructureFunctions::Type& sf )
{
switch ( sf ) {
case StructureFunctions::Electron: return os << "electron";
case StructureFunctions::ElasticProton: return os << "elastic proton";
case StructureFunctions::SuriYennie: return os << "Suri-Yennie";
case StructureFunctions::SzczurekUleshchenko: return os << "Szczurek-Uleshchenko";
case StructureFunctions::FioreBrasse: return os << "Fiore-Brasse";
case StructureFunctions::ChristyBosted: return os << "Christy-Bosted";
case StructureFunctions::BlockDurandHa: return os << "BDH";
case StructureFunctions::ALLM91: return os << "ALLM;91";
case StructureFunctions::ALLM97: return os << "ALLM;97";
case StructureFunctions::GD07p: return os << "ALLM;GD07p";
case StructureFunctions::GD11p: return os << "ALLM;GD11p";
+ case StructureFunctions::Schaefer: return os << "Schaefer";
+ case StructureFunctions::MSTWgrid: return os << "MSTW (grid)";
}
return os;
}
}
diff --git a/CepGen/StructureFunctions/StructureFunctions.h b/CepGen/StructureFunctions/StructureFunctions.h
index 1bf9472..d1039fa 100644
--- a/CepGen/StructureFunctions/StructureFunctions.h
+++ b/CepGen/StructureFunctions/StructureFunctions.h
@@ -1,34 +1,37 @@
#ifndef CepGen_StructureFunctions_StructureFunctions_h
#define CepGen_StructureFunctions_StructureFunctions_h
#include <iostream>
namespace CepGen
{
class StructureFunctions
{
public:
- StructureFunctions( double f2=0.0 ) : F2( f2 ), FL( 0.0 ) {}
+ StructureFunctions( double f2 = 0., double fl = 0. ) :
+ F2( f2 ), FL( fl ) {}
/// Proton structure function to be used in the outgoing state description
/// \note Values correspond to the LPAIR legacy steering card values
enum Type {
Electron = 1,
ElasticProton = 2,
SuriYennie = 11,
SzczurekUleshchenko = 12,
BlockDurandHa = 13,
FioreBrasse = 101,
ChristyBosted = 102,
ALLM91 = 201,
ALLM97 = 202,
GD07p = 203,
- GD11p = 204
+ GD11p = 204,
+ MSTWgrid = 205,
+ Schaefer = 301
};
double F2, FL;
};
std::ostream& operator<<( std::ostream&, const StructureFunctions& );
std::ostream& operator<<( std::ostream&, const StructureFunctions::Type& );
}
#endif
diff --git a/CepGen/StructureFunctions/StructureFunctionsBuilder.cpp b/CepGen/StructureFunctions/StructureFunctionsBuilder.cpp
index c39006b..6750464 100644
--- a/CepGen/StructureFunctions/StructureFunctionsBuilder.cpp
+++ b/CepGen/StructureFunctions/StructureFunctionsBuilder.cpp
@@ -1,31 +1,69 @@
#include "StructureFunctionsBuilder.h"
#include "CepGen/StructureFunctions/ALLM.h"
#include "CepGen/StructureFunctions/BlockDurandHa.h"
#include "CepGen/StructureFunctions/FioreBrasse.h"
#include "CepGen/StructureFunctions/ChristyBosted.h"
#include "CepGen/StructureFunctions/GenericLHAPDF.h"
#include "CepGen/StructureFunctions/SuriYennie.h"
#include "CepGen/StructureFunctions/SzczurekUleshchenko.h"
+#include "CepGen/StructureFunctions/Schaefer.h"
+#include "CepGen/IO/MSTWGridHandler.h"
namespace CepGen
{
StructureFunctions
StructureFunctionsBuilder::get( const StructureFunctions::Type& sf_type, double q2, double xbj )
{
switch ( sf_type ) {
- case StructureFunctions::Electron: case StructureFunctions::ElasticProton:
- return StructureFunctions(); break;
- case StructureFunctions::SzczurekUleshchenko: { const SF::SzczurekUleshchenko su; return su( q2, xbj ); } break;
- case StructureFunctions::SuriYennie: { const SF::SuriYennie sy; return sy( q2, xbj ); } break;
- case StructureFunctions::FioreBrasse: { const SF::FioreBrasse fb; return fb( q2, xbj ); } break;
- case StructureFunctions::ChristyBosted: { const SF::ChristyBosted cb; return cb( q2, xbj ); } break;
- case StructureFunctions::BlockDurandHa: { const SF::BlockDurandHa bdh; return bdh( q2, xbj ); } break;
- case StructureFunctions::ALLM91: { const SF::ALLM allm91( SF::ALLM::Parameterisation::allm91() ); return allm91( q2, xbj ); } break;
- case StructureFunctions::ALLM97: { const SF::ALLM allm97( SF::ALLM::Parameterisation::allm97() ); return allm97( q2, xbj ); } break;
- case StructureFunctions::GD07p: { const SF::ALLM gd07p( SF::ALLM::Parameterisation::gd07p() ); return gd07p( q2, xbj ); } break;
- case StructureFunctions::GD11p: { const SF::ALLM gd11p( SF::ALLM::Parameterisation::gd11p() ); return gd11p( q2, xbj ); } break;
+ case StructureFunctions::Electron:
+ case StructureFunctions::ElasticProton:
+ return StructureFunctions();
+ break;
+ case StructureFunctions::SzczurekUleshchenko: {
+ const SF::SzczurekUleshchenko su;
+ return su( q2, xbj );
+ } break;
+ case StructureFunctions::SuriYennie: {
+ const SF::SuriYennie sy;
+ return sy( q2, xbj );
+ } break;
+ case StructureFunctions::FioreBrasse: {
+ const SF::FioreBrasse fb;
+ return fb( q2, xbj );
+ } break;
+ case StructureFunctions::ChristyBosted: {
+ const SF::ChristyBosted cb;
+ return cb( q2, xbj );
+ } break;
+ case StructureFunctions::BlockDurandHa: {
+ const SF::BlockDurandHa bdh;
+ return bdh( q2, xbj );
+ } break;
+ case StructureFunctions::ALLM91: {
+ const SF::ALLM allm91( SF::ALLM::Parameterisation::allm91() );
+ return allm91( q2, xbj );
+ } break;
+ case StructureFunctions::ALLM97: {
+ const SF::ALLM allm97( SF::ALLM::Parameterisation::allm97() );
+ return allm97( q2, xbj );
+ } break;
+ case StructureFunctions::GD07p: {
+ const SF::ALLM gd07p( SF::ALLM::Parameterisation::gd07p() );
+ return gd07p( q2, xbj );
+ } break;
+ case StructureFunctions::GD11p: {
+ const SF::ALLM gd11p( SF::ALLM::Parameterisation::gd11p() );
+ return gd11p( q2, xbj );
+ } break;
+ case StructureFunctions::Schaefer: {
+ const SF::Schaefer luxlike;
+ return luxlike( q2, xbj );
+ } break;
+ case StructureFunctions::MSTWgrid: {
+ return MSTW::GridHandler::get().eval( q2, xbj );
+ } break;
}
return StructureFunctions(); //FIXME
}
}
diff --git a/CepGen/StructureFunctions/SuriYennie.cpp b/CepGen/StructureFunctions/SuriYennie.cpp
index 139c8dc..852df0c 100644
--- a/CepGen/StructureFunctions/SuriYennie.cpp
+++ b/CepGen/StructureFunctions/SuriYennie.cpp
@@ -1,52 +1,53 @@
#include "SuriYennie.h"
-#include "CepGen/Physics/Constants.h"
+#include "CepGen/Physics/ParticleProperties.h"
+#include <math.h>
namespace CepGen
{
namespace SF
{
SuriYennie::Parameterisation
SuriYennie::Parameterisation::standard()
{
Parameterisation p;
p.C1 = 0.86926;
p.C2 = 2.23422;
p.D1 = 0.12549;
p.rho2 = 0.585;
p.Cp = 0.96;
p.Bp = 0.63;
return p;
}
SuriYennie::Parameterisation
SuriYennie::Parameterisation::alternative()
{
Parameterisation p;
p.C1 = 0.6303;
p.C2 = 2.3049;
p.D1 = 0.04681;
p.rho2 = 1.05;
p.Cp = 1.23;
p.Bp = 0.61;
return p;
}
SuriYennie
SuriYennie::operator()( double q2, double xbj ) const
{
- const double mp2 = Constants::mp*Constants::mp;
+ const double mp = ParticleProperties::mass( Proton ), mp2 = mp*mp;
const double mx2 = q2 * ( 1.-xbj )/xbj + mp2, // [GeV^2]
- nu = 0.5 * ( q2 + mx2 - mp2 ) / Constants::mp; // [GeV]
+ nu = 0.5 * ( q2 + mx2 - mp2 ) / mp; // [GeV]
const double dm2 = mx2-mp2, Xpr = q2/( q2+mx2 ), En = dm2+q2, Tau = 0.25 * q2/mp2, MQ = params_.rho2+q2;
SuriYennie sy;
sy.FM = ( params_.C1*dm2*pow( params_.rho2/MQ, 2 ) + ( params_.C2*mp2*pow( 1.-Xpr, 4 ) ) / ( 1.+Xpr*( Xpr*params_.Cp-2.*params_.Bp ) ) )/q2;
sy.FE = ( Tau*sy.FM + params_.D1*dm2*q2*params_.rho2/mp2*pow( dm2/MQ/En, 2 ) ) / ( 1.+0.25*En*En/mp2/q2 );
- const double w2 = 2.*Constants::mp*sy.FE/*, w1 = 0.5 * sy.FM*q2/Constants::mp*/;
+ const double w2 = 2.*mp*sy.FE/*, w1 = 0.5 * sy.FM*q2/mp*/;
- sy.F2 = nu/Constants::mp*w2;
+ sy.F2 = nu/mp*w2;
return sy;
}
}
}
diff --git a/CepGen/Version.h b/CepGen/Version.h
new file mode 100644
index 0000000..3c30078
--- /dev/null
+++ b/CepGen/Version.h
@@ -0,0 +1,13 @@
+#ifndef CepGen_Version_h
+#define CepGen_Version_h
+
+#include <stdio.h>
+
+namespace CepGen
+{
+ const unsigned int cepgen_version = 0x000900;
+
+ const char* version();
+}
+
+#endif
diff --git a/External/F2_Luxlike_fit/F2_luxlike_minimal.f b/External/F2_Luxlike_fit/F2_luxlike_minimal.f
new file mode 100644
index 0000000..7584d70
--- /dev/null
+++ b/External/F2_Luxlike_fit/F2_luxlike_minimal.f
@@ -0,0 +1,76 @@
+c ----------------------------------------------------------------
+ subroutine F2_fit_luxlike(xbj,q2,F2,FL)
+c ----------------------------------------------------------------
+ implicit double precision (a-h,o-z)
+c input: x,q2
+c output: F2,FL
+ common/luxlike_params/amp,alpha_em,
+ & q2_cut,w2_lo,w2_hi,
+ & ires_model,icont_model
+c -----------------------------
+ w2 = amp**2 + q2*(1.d0-xbj)/xbj
+c -----------------------------
+ omega = (w2-w2_lo)/(w2_hi-w2_lo)
+ rho = 2.d0*omega**2 - omega**4
+
+ if(q2.ge.q2_cut) then
+ if(w2.gt.w2_hi) then ! MSTW grid, perturbative
+ call F2_perturbative(xbj,q2,F2,FL)
+ else
+ call F2_cont(xbj,q2,icont_model,F2,FL)
+ endif
+ else ! Q2 < Q2cut
+ if(w2.gt.w2_hi) then
+ call F2_cont(xbj,q2,icont_model,F2,FL)
+ elseif(w2.gt.w2_lo) then
+ call F2_res(xbj,q2,ires_model,F2r,FLr)
+ call F2_cont(xbj,q2,icont_model,F2c,FLc)
+ F2 = (1.d0-rho)*F2r + rho*F2c
+ FL = (1.d0-rho)*FLr + rho*FLc
+ else
+ call F2_res(xbj,q2,ires_model,F2,FL)
+ endif
+ endif
+
+ return
+ end
+c ----------------------------------------------------------------
+ subroutine F2_PERTURBATIVE(xbj,q2,F2,FL)
+ double precision Q2,xbj,F2,FL
+
+ call CepGen_Structure_Functions(205,Q2,xbj,F2,FL)
+
+c in the Lux-paper a "higher-twist" correction is applied to F2
+ F2 = F2*(1.d0+5.5d0/Q2)
+
+ return
+ end
+c ----------------------------------------------------------------
+ subroutine F2_RES(xbj,q2,irm,F2,FL)
+ double precision Q2,xbj,F2,FL
+ integer irm
+
+ if(irm.eq.1) then ! Christy-Bosted
+ call CepGen_Structure_Functions(102,Q2,xbj,F2,FL)
+ elseif(irm.eq.2) then ! Fiore-Brasse
+ call CepGen_Structure_Functions(101,Q2,xbj,F2,FL)
+ endif
+
+ return
+ end
+c ----------------------------------------------------------------
+ subroutine F2_CONT(xbj,q2,icm,F2,FL)
+ double precision Q2,xbj,F2,FL
+ integer icm
+
+ if(icm.eq.1) then ! GD11p
+ call CepGen_Structure_Functions(204,Q2,xbj,F2,FL)
+ elseif(icm.eq.2) then ! ALLM91
+ call CepGen_Structure_Functions(201,Q2,xbj,F2,FL)
+ elseif(icm.eq.3) then ! ALLM97
+ call CepGen_Structure_Functions(202,Q2,xbj,F2,FL)
+ endif
+
+ return
+ end
+c ----------------------------------------------------------------
diff --git a/External/F2_Luxlike_fit/mstw_f2_scan_nnlo.dat b/External/F2_Luxlike_fit/mstw_f2_scan_nnlo.dat
new file mode 100644
index 0000000..c514844
Binary files /dev/null and b/External/F2_Luxlike_fit/mstw_f2_scan_nnlo.dat differ
diff --git a/cmake/UseEnvironment.cmake b/cmake/UseEnvironment.cmake
index 2be399b..fc0e946 100644
--- a/cmake/UseEnvironment.cmake
+++ b/cmake/UseEnvironment.cmake
@@ -1,74 +1,76 @@
if($ENV{HOSTNAME} MATCHES "^lxplus[0-9]+.cern.ch")
set(BASE_DIR "/cvmfs/sft.cern.ch/lcg/external")
set(GSL_DIR "${BASE_DIR}/GSL/1.14/x86_64-slc5-gcc44-opt")
set(HEPMC_DIR "${BASE_DIR}/HepMC/2.06.08/x86_64-slc6-gcc48-opt")
#set(LHAPDF_DIR "${BASE_DIR}/MCGenerators/lhapdf/5.8.9/x86_64-slc6-gcc46-opt")
set(LHAPDF_DIR "${BASE_DIR}/MCGenerators_lcgcmt67c/lhapdf/6.1.5/x86_64-slc6-gcc48-opt")
set(PYTHIA_DIR "${BASE_DIR}/MCGenerators_lcgcmt67c/pythia8/201/x86_64-slc6-gcc48-opt")
set(ROOTSYS "/cvmfs/sft.cern.ch/lcg/app/releases/ROOT/6.02.00/x86_64-slc6-gcc48-opt/root")
message(STATUS "Compiling on LXPLUS. Do not forget to source the environment variables!")
message(STATUS "e.g. source /cvmfs/sft.cern.ch/lcg/external/gcc/6.2.0/x86_64-slc6-gcc62-opt/setup.sh")
#--- searching for GSL
find_library(GSL_LIB gsl HINTS "${GSL_DIR}/lib")
find_library(GSL_CBLAS_LIB gslcblas HINTS "${GSL_DIR}/lib")
#--- searching for Pythia 8
find_library(PYTHIA8 pythia8 HINTS "${PYTHIA_DIR}/include")
find_path(PYTHIA8_INCLUDE Pythia8 HINTS "${PYTHIA_DIR}/include")
#--- searching for LHAPDF
find_library(LHAPDF LHAPDF HINTS "${LHAPDF_DIR}/lib")
find_path(LHAPDF_INCLUDE LHAPDF HINTS "${LHAPDF_DIR}/include")
#--- searching for HepMC
find_library(HEPMC_LIB HepMC HINTS "${HEPMC_DIR}/lib")
find_library(HEPMC_FIO_LIB HepMCfio HINTS "${HEPMC_DIR}/lib")
find_path(HEPMC_INCLUDE HepMC HINTS "${HEPMC_DIR}/include")
else()
find_library(GSL_LIB gsl)
find_library(GSL_CBLAS_LIB gslcblas)
find_library(PYTHIA8 pythia8)
find_path(PYTHIA8_INCLUDE Pythia8)
find_library(LHAPDF LHAPDF)
find_path(LHAPDF_INCLUDE LHAPDF)
find_library(HEPMC_LIB HepMC)
find_library(HEPMC_FIO_LIB HepMCfio)
find_path(HEPMC_INCLUDE HepMC)
endif()
find_library(LIBCONFIG config++)
find_library(MUPARSER muparser)
-if(EXISTS ${GSL_LIB})
+if(GSL_LIB)
message(STATUS "GSL found in ${GSL_LIB}")
list(APPEND CEPGEN_EXTERNAL_REQS ${GSL_LIB} ${GSL_CBLAS_LIB})
else()
message(FATAL_ERROR "GSL not found on your system!")
endif()
-if(EXISTS ${LHAPDF})
+if(LHAPDF)
message(STATUS "LHAPDF found in ${LHAPDF}")
list(APPEND CEPGEN_EXTERNAL_REQS ${LHAPDF})
add_definitions(-DLIBLHAPDF)
include_directories(${LHAPDF_INCLUDE})
endif()
-if(EXISTS ${HEPMV_LIB})
+if(HEPMC_LIB)
message(STATUS "HepMC found in ${HEPMC_INCLUDE}")
list(APPEND CEPGEN_EXTERNAL_REQS ${HEPMC_LIB})
- #list(APPEND CEPGEN_EXTERNAL_REQS ${HEPMC_FIO_LIB})
+ if(HEPMC_FIO_LIB)
+ list(APPEND CEPGEN_EXTERNAL_REQS ${HEPMC_FIO_LIB})
+ endif()
add_definitions(-DLIBHEPMC)
include_directories(${HEPMC_INCLUDE})
endif()
if(EXISTS ${LIBCONFIG})
message(STATUS "libconfig++ found in ${LIBCONFIG}")
list(APPEND CEPGEN_EXTERNAL_REQS ${LIBCONFIG})
add_definitions(-DLIBCONFIG)
endif()
if(EXISTS ${MUPARSER})
message(STATUS "muParser found in ${MUPARSER}")
list(APPEND CEPGEN_EXTERNAL_REQS ${MUPARSER})
add_definitions(-DMUPARSER)
endif()
if(EXISTS ${PYTHIA8})
message(STATUS "Pythia8 found in ${PYTHIA8}")
list(APPEND CEPGEN_EXTERNAL_REQS ${PYTHIA8})
add_definitions(-DPYTHIA8)
include_directories(${PYTHIA8_INCLUDE})
endif()
diff --git a/test/Canvas.h b/test/Canvas.h
index e7eddc6..ecf674a 100644
--- a/test/Canvas.h
+++ b/test/Canvas.h
@@ -1,314 +1,320 @@
#ifndef Canvas_h
#define Canvas_h
#include "TCanvas.h"
#include "TLegend.h"
#include "TPaveText.h"
#include "TObjArray.h"
#include "TObjString.h"
#include "TH1.h"
#include "TGraphErrors.h"
#include "TStyle.h"
#include <string.h>
#define font_type(x) 130+x
namespace CepGen
{
class PaveText : public TPaveText
{
public:
inline PaveText( const float& x1, const float& y1, const float& x2, const float& y2, const char* text="" ) :
TPaveText( x1, y1, x2, y2, "NDC" )
{
TPaveText::SetTextAlign( 13 );
if ( strcmp( text, "" )!=0 ) {
TString txt = text;
if ( txt.Contains( "\\" ) ) {
TObjArray* tok = txt.Tokenize( "\\" );
for ( int i=0; i<tok->GetEntries(); i++ ) { TPaveText::AddText( dynamic_cast<TObjString*>( tok->At( i ) )->String() ); }
}
else TPaveText::AddText( text );
}
TPaveText::SetFillColor( 0 );
TPaveText::SetFillStyle( 0 );
TPaveText::SetLineColor( 0 );
TPaveText::SetLineWidth( 0 );
TPaveText::SetShadowColor( 0 );
TPaveText::SetTextFont( font_type( 2 ) );
TPaveText::SetTextSize( 0.058 );
}
};
class Canvas : public TCanvas
{
public:
inline Canvas( const char* name, const char* title="", bool ratio=false ) :
//TCanvas( name, "", 450, 450 ),
TCanvas( name, "", 600, 600 ),
fTitle( title ), fTopLabel( 0 ),
fLeg( 0 ), fLegX1( 0.5 ), fLegY1( 0.75 ),
fRatio( ratio )
{
gStyle->SetOptStat( 0 );
Build();
}
inline ~Canvas() {
if ( fLeg ) delete fLeg;
if ( fTopLabel ) delete fTopLabel;
}
inline void SetSize( const float& size=600 ) {
TCanvas::SetCanvasSize( size, 600 );
}
inline void Prettify( TH1* obj ) {
TAxis* x = dynamic_cast<TAxis*>( obj->GetXaxis() ),
- *y = dynamic_cast<TAxis*>( obj->GetYaxis() );
+ *y = dynamic_cast<TAxis*>( obj->GetYaxis() ),
+ *z = dynamic_cast<TAxis*>( obj->GetZaxis() );
x->SetLabelFont( font_type( 3 ) ); x->SetLabelSize( 20 );
x->SetTitleFont( font_type( 3 ) ); x->SetTitleSize( 29 );
y->SetLabelFont( font_type( 3 ) ); y->SetLabelSize( 20 );
y->SetTitleFont( font_type( 3 ) ); y->SetTitleSize( 29 );
+ z->SetLabelFont( font_type( 3 ) ); z->SetLabelSize( 16 );
+ z->SetTitleFont( font_type( 3 ) ); z->SetTitleSize( 29 );
if ( fRatio ) {
x->SetTitleOffset( 3. );
x->SetLabelOffset( 0.02 );
}
y->SetTitleOffset( 1.3 );
x->SetTickLength( 0.03 );
y->SetTickLength( 0.03 );
// axis titles
TString ttle = obj->GetTitle();
if ( ttle.Contains( "\\" ) ) {
TObjArray* tok = ttle.Tokenize( "\\" );
TString x_title = "", y_title = "", unit = "", form_spec = "", distrib = "";
if ( tok->GetEntries()>0 ) x_title = dynamic_cast<TObjString*>( tok->At( 0 ) )->String();
if ( tok->GetEntries()>1 ) y_title = dynamic_cast<TObjString*>( tok->At( 1 ) )->String();
if ( tok->GetEntries()>2 ) {
unit = ( ( TObjString* )tok->At( 2 ) )->String();
if ( unit.Contains( "?" ) ) { // extract format specifier
TObjArray* tok2 = unit.Tokenize( "?" );
if ( tok2->GetEntries()>1 ) {
unit = dynamic_cast<TObjString*>( tok2->At( 0 ) )->String();
form_spec = dynamic_cast<TObjString*>( tok2->At( 1 ) )->String();
}
else {
unit = "";
form_spec = dynamic_cast<TObjString*>( tok2->At( 0 ) )->String();
}
}
}
if ( tok->GetEntries()>3 ) {
distrib = ( ( TObjString* )tok->At( 3 ) )->String();
}
if ( !unit.IsNull() or !form_spec.IsNull() ) {
if ( !unit.IsNull() ) x_title = Form( "%s (%s)", x_title.Data(), unit.Data() );
if ( !distrib.IsNull() ) {
if ( !form_spec.IsNull() ) {
TString format = Form( "%%s (%s / %%%s %%s)", distrib.Data(), form_spec.Data() );
y_title = Form( format.Data(), y_title.Data(), GetBinning( obj ), unit.Data() );
}
else y_title = Form( "%s (%s / %d %s)", y_title.Data(), distrib.Data(), static_cast<unsigned int>( GetBinning( obj ) ), unit.Data() );
}
else {
if ( !form_spec.IsNull() ) {
TString format = Form( "%%s / %%%s %%s", form_spec.Data() );
y_title = Form( format.Data(), y_title.Data(), GetBinning( obj ), unit.Data() );
}
else y_title = Form( "%s / %d %s", y_title.Data(), static_cast<unsigned int>( GetBinning( obj ) ), unit.Data() );
}
}
obj->GetXaxis()->SetTitle( x_title );
obj->GetYaxis()->SetTitle( y_title );
obj->SetTitle( "" );
}
//else obj->GetXaxis()->SetTitle(ttle);
}
inline void DrawDiagonal(const TH1* obj) {
TLine l;
l.SetLineWidth( 2 );
l.SetLineColor( kGray );
l.SetLineStyle( 2 );
l.DrawLine( obj->GetXaxis()->GetXmin(), obj->GetYaxis()->GetXmin(), obj->GetXaxis()->GetXmax(), obj->GetYaxis()->GetXmax() );
}
inline void RatioPlot(TH1* obj1, const TH1* obj2, const TH1* obj3, float ymin=-999., float ymax=-999.) {
if (!fRatio) return;
TH1* ratio1 = (TH1*)obj2->Clone(), *ratio2 = (TH1*)obj3->Clone();
//ratio1->Sumw2(); ratio2->Sumw2();
ratio1->Divide(obj1);
ratio2->Divide(obj1);
TCanvas::cd(2);
ratio1->Draw("p");
ratio2->Draw("p same");
obj1->GetXaxis()->SetTitle("");
if ( ymin!=ymax ) {
ratio1->GetYaxis()->SetRangeUser(ymin, ymax);
}
Prettify(ratio1);
TCanvas::cd();
}
inline void RatioPlot( TH1* obj1, const TH1* obj2=0, float ymin=-999., float ymax=-999. ) {
if ( !fRatio ) return;
TH1* ratio;
if ( obj2 ) {
ratio = dynamic_cast<TH1*>( obj2->Clone() );
ratio->Divide( obj1 );
}
else { ratio = dynamic_cast<TH1*>( obj1->Clone() ); }
TCanvas::cd( 2 );
ratio->Draw("p");
obj1->GetXaxis()->SetTitle("");
if ( ymin!=ymax ) {
ratio->GetYaxis()->SetRangeUser( ymin, ymax );
}
Prettify(ratio);
ratio->GetYaxis()->SetTitle("Ratio");
TCanvas::cd();
}
inline TGraphErrors* RatioPlot(TGraphErrors* obj1, const TGraphErrors* obj2, float ymin=-999., float ymax=-999.) {
if (!fRatio) return 0;
TGraphErrors* ratio = new TGraphErrors;
ratio->SetTitle( obj1->GetTitle() );
unsigned int n = 0;
float min_x = 9.e10, max_x = -9.e10;
for ( int i=0; i<obj1->GetN(); i++ ) {
const float x1 = obj1->GetX()[i];
for ( int j=0; j<obj2->GetN(); j++ ) {
const float x2 = obj2->GetX()[j];
if (x2>max_x) max_x = x2;
if (x2<min_x) min_x = x2;
if ( fabs( x2-x1 )>1.e-3 ) continue;
const float y1 = obj1->GetY()[i], y1_err = obj1->GetEY()[i],
y2 = obj2->GetY()[j], y2_err = obj2->GetEY()[j];
const float y = (y2-y1)/y1,
err_y = sqrt( pow( y1_err/y1, 2 )+pow( y2_err/y2, 2 )*y2/y1 );
ratio->SetPoint( n, x1, y );
ratio->SetPointError( n, 0., err_y );
n++;
}
}
TCanvas::cd(2);
ratio->Draw("ap");
ratio->GetXaxis()->SetRangeUser( obj1->GetXaxis()->GetXmin(), obj1->GetXaxis()->GetXmax() );
ratio->SetMarkerStyle( 20 );
if ( ymin!=ymax ) {
ratio->GetYaxis()->SetRangeUser(ymin, ymax);
}
ratio->GetXaxis()->SetLimits(min_x, max_x);
Prettify( ratio->GetHistogram() );
obj1->GetXaxis()->SetTitle("");
TLine l( min_x, 0., max_x, 0. );
l.Draw();
ratio->GetYaxis()->SetLabelSize( 14 );
TCanvas::cd();
return ratio;
}
inline void SetTopLabel(const char* lab="") {
TCanvas::cd();
if (strcmp(lab, "")!=0) fTitle = lab;
if (!fTopLabel) BuildTopLabel();
else fTopLabel->Clear();
fTopLabel->AddText(fTitle);
//fTopLabel->Draw();
}
inline void SetLegendX1(double x) { fLegX1 = x; }
inline void SetLegendY1(double y) { fLegY1 = y; }
inline void AddLegendEntry(const TObject* obj, const char* title, Option_t* option="lpf") {
if (!fLeg) BuildLeg();
fLeg->AddEntry(obj, title, option);
const unsigned int num_entries = fLeg->GetNRows();
if ( num_entries>3 ) {
fLeg->SetY1( fLeg->GetY1()-( num_entries-3 )*0.015 );
}
}
inline void Save(const char* ext, const char* out_dir=".") {
if (strstr(ext, "pdf")==NULL) {
if (strstr(ext, "png")==NULL) {
- return;
+ if (strstr(ext, "root")==NULL) {
+ return;
+ }
}
}
TCanvas::cd();
if ( fLeg ) fLeg->Draw();
if ( fTopLabel ) fTopLabel->Draw();
TCanvas::SaveAs(Form("%s/%s.%s", out_dir, TCanvas::GetName(), ext));
}
+ inline TLegend* GetLegend() { return fLeg; }
private:
inline void Build() {
TCanvas::SetLeftMargin(0.14);
TCanvas::SetTopMargin(0.06);
TCanvas::SetRightMargin(0.1);
TCanvas::SetBottomMargin(0.12);
TCanvas::SetTicks(1,1);
SetTopLabel();
if (fRatio) DivideCanvas();
}
inline void DivideCanvas() {
TCanvas::Divide(1,2);
TPad* p1 = (TPad*)TCanvas::GetPad(1), *p2 = (TPad*)TCanvas::GetPad(2);
p1->SetPad(0., 0.3, 1., 1.);
p2->SetPad(0., 0.0, 1., 0.3);
p1->SetLeftMargin(TCanvas::GetLeftMargin());
p1->SetRightMargin(TCanvas::GetRightMargin());
p2->SetLeftMargin(TCanvas::GetLeftMargin());
p2->SetRightMargin(TCanvas::GetRightMargin());
p1->SetTopMargin(TCanvas::GetTopMargin()+0.025);
p1->SetBottomMargin(0.02);
p2->SetTopMargin(0.02);
p2->SetBottomMargin(TCanvas::GetBottomMargin()+0.25);
p1->SetTicks(1,1); p2->SetTicks(1,1);
p2->SetGrid(0,1);
TCanvas::cd(1);
}
inline void BuildTopLabel() {
TCanvas::cd();
fTopLabel = new TPaveText(0.5, 0.95, 0.915, 0.96, "NB NDC");
fTopLabel->SetFillStyle(0);
fTopLabel->SetFillColor(0);
fTopLabel->SetLineColor(0);
fTopLabel->SetLineStyle(0);
fTopLabel->SetTextFont( font_type( 2 ) );
fTopLabel->SetTextSize(0.04);
fTopLabel->SetTextAlign(kHAlignRight+kVAlignBottom);
}
inline void BuildLeg() {
if ( fLeg ) return;
if ( fRatio ) TCanvas::cd(1);
fLeg = new TLegend(fLegX1, fLegY1, fLegX1+0.3, fLegY1+0.15);
fLeg->SetLineColor(kWhite);
fLeg->SetLineWidth(0);
fLeg->SetFillStyle(0);
fLeg->SetTextFont( font_type( 2 ) );
fLeg->SetTextSize(0.04);
}
inline float GetBinning(const TH1* h) {
return (h->GetXaxis()->GetXmax()-h->GetXaxis()->GetXmin())/h->GetXaxis()->GetNbins();
}
TString fTitle;
TPaveText* fTopLabel;
TLegend* fLeg;
double fLegX1, fLegY1;
bool fRatio;
};
}
#endif
diff --git a/test/cepgen-lhe.cpp b/test/cepgen-lhe.cpp
index 9a78427..fe84607 100644
--- a/test/cepgen-lhe.cpp
+++ b/test/cepgen-lhe.cpp
@@ -1,57 +1,49 @@
#include <iostream>
#include "CepGen/Generator.h"
-#include "CepGen/Cards/LpairHandler.h"
-//#include "CepGen/Export/LHEFHandler.h"
-#include "CepGen/Export/HepMCHandler.h"
+#include "CepGen/Cards/ConfigHandler.h"
+#include "CepGen/Export/LHEFHandler.h"
#include "HepMC/Version.h"
using namespace std;
/**
* Main caller for this Monte Carlo generator. Loads the configuration files'
* variables if set as an argument to this program, else loads a default
* "LHC-like" configuration, then launches the cross-section computation and
* the events generation.
* \author Laurent Forthomme <laurent.forthomme@cern.ch>
*/
int main( int argc, char* argv[] ) {
CepGen::Generator mg;
- if ( argc==1 ) InError( "No config file provided." );
+ if ( argc == 1 ) FatalError( "No config file provided." );
Debugging( Form( "Reading config file stored in %s", argv[1] ) );
- CepGen::Cards::LpairHandler card( argv[1] );
+ CepGen::Cards::ConfigHandler card( argv[1] );
mg.setParameters( card.parameters() );
// We might want to cross-check visually the validity of our run
mg.parameters->dump();
// Let there be cross-section...
double xsec, err;
mg.computeXsection( xsec, err );
- //if ( !mg.parameters->generation ) return 0;
-
- CepGen::OutputHandler::HepMCHandler writer( "example.dat" );
+ CepGen::OutputHandler::LHEFHandler writer( "example.dat" );
writer.setCrossSection( xsec, err );
writer.initialise( *mg.parameters );
- Information( Form( "HepMC version: %s", HepMC::versionName().c_str() ) );
-
// The events generation starts here !
- for ( unsigned int i=0; i<mg.parameters->generation.maxgen; i++ ) {
- if ( i%1000==0 )
+ for ( unsigned int i = 0; i < mg.parameters->generation.maxgen; ++i ) {
+ if ( i%1000 == 0 )
cout << "Generating event #" << i+1 << endl;
try {
- const CepGen::Event* ev = mg.generateOneEvent();
- writer << ev;
+ writer << mg.generateOneEvent();
} catch ( CepGen::Exception& e ) { e.dump(); }
}
- //mg.parameters->StoreConfigFile( "lastrun.card" );
-
return 0;
}
diff --git a/test/cepgen.cpp b/test/cepgen.cpp
index 3418eee..096b36a 100644
--- a/test/cepgen.cpp
+++ b/test/cepgen.cpp
@@ -1,83 +1,83 @@
#include <iostream>
#include "CepGen/Generator.h"
#include "CepGen/Cards/LpairHandler.h"
#include "CepGen/Cards/ConfigHandler.h"
#include "CepGen/Core/Logger.h"
#include "CepGen/Core/Exception.h"
#include "CepGen/Processes/GamGamLL.h"
#include "CepGen/Hadronisers/Pythia8Hadroniser.h"
#include "CepGen/StructureFunctions/StructureFunctions.h"
using namespace std;
/**
* Main caller for this Monte Carlo generator. Loads the configuration files'
* variables if set as an argument to this program, else loads a default
* "LHC-like" configuration, then launches the cross-section computation and
* the events generation.
* \author Laurent Forthomme <laurent.forthomme@cern.ch>
*/
int main( int argc, char* argv[] ) {
CepGen::Generator mg;
//CepGen::Logger::get().level = CepGen::Logger::Debug;
//CepGen::Logger::get().level = CepGen::Logger::DebugInsideLoop;
//CepGen::Logger::get().outputStream( ofstream( "log.txt" ) );
if ( argc == 1 ) {
Information( "No config file provided. Setting the default parameters." );
mg.parameters->setProcess( new CepGen::Process::GamGamLL );
//mg.parameters->process_mode = Kinematics::InelasticElastic;
mg.parameters->kinematics.mode = CepGen::Kinematics::ElasticElastic;
mg.parameters->kinematics.structure_functions = CepGen::StructureFunctions::SuriYennie;
#ifdef PYTHIA8
mg.parameters->setHadroniser( new CepGen::Hadroniser::Pythia8Hadroniser );
#endif
mg.parameters->kinematics.inp = { 6500., 6500. };
- mg.parameters->kinematics.central_system = { CepGen::Particle::Muon, CepGen::Particle::Muon };
+ mg.parameters->kinematics.central_system = { CepGen::Muon, CepGen::Muon };
mg.parameters->kinematics.cuts.central[CepGen::Cuts::pt_single].min() = 15.;
mg.parameters->kinematics.cuts.central[CepGen::Cuts::eta_single] = { -2.5, 2.5 };
mg.parameters->integrator.ncvg = 5e4; //FIXME
mg.parameters->generation.enabled = true;
//mg.parameters->maxgen = 2;
mg.parameters->generation.maxgen = 2e4;
}
else {
Information( Form( "Reading config file stored in %s", argv[1] ) );
//CepGen::Cards::LpairReader card( argv[1] );
const std::string file( argv[1] ), extension = file.substr( file.find_last_of( "." )+1 );
if ( extension == "card" ) mg.setParameters( CepGen::Cards::LpairHandler( argv[1] ).parameters() );
else if ( extension == "cfg" ) mg.setParameters( CepGen::Cards::ConfigHandler( argv[1] ).parameters() );
}
// We might want to cross-check visually the validity of our run
mg.parameters->dump();
// Let there be cross-section...
double xsec, err;
mg.computeXsection( xsec, err );
if ( mg.parameters->generation.enabled ) {
// The events generation starts here !
CepGen::Event ev;
for ( unsigned int i=0; i<mg.parameters->generation.maxgen; i++ ) {
ev = *mg.generateOneEvent();
if ( i%1000==0 ) {
Information( Form( "Generating event #%d", i ) );
ev.dump();
}
}
}
// store the current configuration
CepGen::Cards::ConfigHandler::store( mg.parameters.get(), "last_run.cfg" );
return 0;
}
diff --git a/test/test_f77_interface.f b/test/test_f77_interface.f
index 828107e..9703f67 100644
--- a/test/test_f77_interface.f
+++ b/test/test_f77_interface.f
@@ -1,20 +1,21 @@
program main
implicit none
integer i,niter,nsf
double precision f2,fl
double precision xbj,min_xbj,max_xbj
double precision q2
- nsf=204 ! GD11p
- q2=0.225
+c nsf=204 ! GD11p
+ nsf=301 ! LUXlike
+ q2=10.225
min_xbj=1.0d-3
max_xbj=1.0
niter=101
do i=1,niter
xbj=min_xbj+(max_xbj-min_xbj)*(i-1)/(niter-1)
call CepGen_Structure_Functions(nsf,q2,xbj,f2,fl)
print *,xbj,f2,fl
enddo
end
diff --git a/test/utils/structure_functions.cxx b/test/utils/structure_functions.cxx
index 44daf64..0a373b3 100644
--- a/test/utils/structure_functions.cxx
+++ b/test/utils/structure_functions.cxx
@@ -1,145 +1,151 @@
#include "CepGen/Event/Particle.h"
#include "CepGen/StructureFunctions/StructureFunctionsBuilder.h"
#include "test/Canvas.h"
#include "TGraph.h"
#include "TMultiGraph.h"
#include <iostream>
using namespace std;
int
main( int argc, char* argv[] )
{
const float min_xbj = 1.e-5, max_xbj = 0.99, q2 = ( argc>1 ) ? atof( argv[1] ) : 2.5;
const char* q2_str = ( argc>2 ) ? argv[2] : std::to_string( q2 ).c_str();
const unsigned int npoints = 5000;
TGraph g_sy_f2, g_fb_f2, g_su_f2, g_bdh_f2, g_cteq_f2, g_mrst_f2;
TGraph g_allm97_f2, g_allm_hht_f2, g_allm_hht_ft_f2, g_gd11p_f2;
TGraph g_lux_f2;
- TGraph g_cb_f2;
+ TGraph g_luxlike_f2;
const bool use_logarithmic_x = ( argc>3 ) ? atoi( argv[3] ) : false;
/*CepGen::SF::GenericLHAPDF cteq( "cteq6l1" );
CepGen::SF::GenericLHAPDF mrst( "MRST2004qed_proton" );
CepGen::SF::GenericLHAPDF lux( "LUXqed17_plus_PDF4LHC15_nnlo_100" );*/
for ( unsigned int i=0; i<npoints; i++ ) {
float xbj;
if ( use_logarithmic_x ) {
const float min_lxbj = log10( min_xbj ), max_lxbj = log10( max_xbj );
xbj = pow( 10, min_lxbj + i*( max_lxbj-min_lxbj )/( npoints-1 ) );
}
else xbj = min_xbj + i*( max_xbj-min_xbj )/( npoints-1 );
auto sf_sy = CepGen::StructureFunctionsBuilder::get( CepGen::StructureFunctions::SuriYennie, q2, xbj ),
sf_fb = CepGen::StructureFunctionsBuilder::get( CepGen::StructureFunctions::FioreBrasse, q2, xbj ),
sf_su = CepGen::StructureFunctionsBuilder::get( CepGen::StructureFunctions::SzczurekUleshchenko, q2, xbj ),
sf_allm97 = CepGen::StructureFunctionsBuilder::get( CepGen::StructureFunctions::ALLM97, q2, xbj ),
//sf_allm_hht = CepGen::SF::ALLM( q2, xbj, CepGen::SF::ALLMParameterisation::hht_allm() ),
//sf_allm_hht_ft = CepGen::SF::ALLM( q2, xbj, CepGen::SF::ALLMParameterisation::hht_allm_ft() ),
- sf_gd11p = CepGen::StructureFunctionsBuilder::get( CepGen::StructureFunctions::GD11p, q2, xbj ),
- sf_cb = CepGen::StructureFunctionsBuilder::get( CepGen::StructureFunctions::ChristyBosted, q2, xbj );
+ sf_luxlike = CepGen::StructureFunctionsBuilder::get( CepGen::StructureFunctions::Schaefer, q2, xbj ),
+ sf_gd11p = CepGen::StructureFunctionsBuilder::get( CepGen::StructureFunctions::GD11p, q2, xbj );
g_sy_f2.SetPoint( i, xbj, sf_sy.F2 );
g_fb_f2.SetPoint( i, xbj, sf_fb.F2 );
g_su_f2.SetPoint( i, xbj, sf_su.F2 );
//g_bdh_f2.SetPoint( i, xbj, sf_bdh.F2 );
//g_cteq_f2.SetPoint( i, xbj, sf_cteq.F2 );
//g_mrst_f2.SetPoint( i, xbj, sf_mrst.F2 );
//g_lux_f2.SetPoint( i, xbj, sf_lux.F2 );
g_gd11p_f2.SetPoint( i, xbj, sf_gd11p.F2 );
- g_cb_f2.SetPoint( i, xbj, sf_cb.F2 );
+ g_luxlike_f2.SetPoint( i, xbj, sf_luxlike.F2 );
+ g_gd11p_f2.SetPoint( i, xbj, sf_gd11p.F2 );
g_allm97_f2.SetPoint( i, xbj, sf_allm97.F2 );
//g_allm_hht_f2.SetPoint( i, xbj, sf_allm_hht.F2 );
//g_allm_hht_ft_f2.SetPoint( i, xbj, sf_allm_hht_ft.F2 );
}
CepGen::Canvas c( "test", Form( "CepGen proton structure functions, Q^{2} = %s GeV^{2}", q2_str ) );
c.SetLegendX1( 0.4 );
TMultiGraph mg;
/*g_sy_f2.SetLineStyle( 2 );
g_sy_f2.SetLineWidth( 3 );
mg.Add( &g_sy_f2, "l" );
c.AddLegendEntry( &g_sy_f2, "Suri-Yennie", "l" );*/
//g_fb_f2.SetLineStyle( 2 );
g_fb_f2.SetLineColor( kRed+1 );
g_fb_f2.SetLineWidth( 3 );
mg.Add( &g_fb_f2, "l" );
c.AddLegendEntry( &g_fb_f2, "Fiore-Brasse", "l" );
//g_su_f2.SetLineStyle( 2 );
/*g_su_f2.SetLineColor( kGreen+2 );
g_su_f2.SetLineWidth( 3 );
mg.Add( &g_su_f2, "l" );
c.AddLegendEntry( &g_su_f2, "Szczurek-Uleshchenko", "l" );*/
g_allm97_f2.SetLineColor( kBlue+1 );
g_allm97_f2.SetLineWidth( 3 );
mg.Add( &g_allm97_f2, "l" );
c.AddLegendEntry( &g_allm97_f2, "Abramowicz et al. 97", "l" );
g_gd11p_f2.SetLineColor( kBlue+1 );
g_gd11p_f2.SetLineWidth( 3 );
g_gd11p_f2.SetLineStyle( 2 );
mg.Add( &g_gd11p_f2, "l" );
c.AddLegendEntry( &g_gd11p_f2, "GD11p", "l" );
/*g_allm_hht_f2.SetLineColor( kBlue+1 );
g_allm_hht_f2.SetLineWidth( 3 );
g_allm_hht_f2.SetLineStyle( 2 );
mg.Add( &g_allm_hht_f2, "l" );
c.AddLegendEntry( &g_allm_hht_f2, "Abramowicz et al. HHT", "l" );
g_allm_hht_ft_f2.SetLineColor( kBlue+1 );
g_allm_hht_ft_f2.SetLineWidth( 3 );
g_allm_hht_ft_f2.SetLineStyle( 3 );
mg.Add( &g_allm_hht_ft_f2, "l" );
c.AddLegendEntry( &g_allm_hht_ft_f2, "Abramowicz et al. HHT-FT", "l" );*/
- g_cb_f2.SetLineColor( kMagenta );
+ /*g_cb_f2.SetLineColor( kMagenta );
g_cb_f2.SetLineWidth( 3 );
mg.Add( &g_cb_f2, "l" );
- c.AddLegendEntry( &g_cb_f2, "Christy-Bosted", "l" );
+ c.AddLegendEntry( &g_cb_f2, "Christy-Bosted", "l" );*/
/*g_bdh_f2.SetLineColor( kOrange );
g_bdh_f2.SetLineWidth( 3 );
mg.Add( &g_bdh_f2, "l" );
c.AddLegendEntry( &g_bdh_f2, "Block-Durand-Ha", "l" );
g_cteq_f2.SetLineColor( kMagenta );
g_cteq_f2.SetLineWidth( 3 );
mg.Add( &g_cteq_f2, "l" );
c.AddLegendEntry( &g_cteq_f2, "CTEQ6", "l" );
g_mrst_f2.SetLineColor( kMagenta+1 );
g_mrst_f2.SetLineWidth( 3 );
mg.Add( &g_mrst_f2, "l" );
c.AddLegendEntry( &g_mrst_f2, "MRST2004 (QED/proton)", "l" );*/
/*g_lux_f2.SetLineColor( kOrange );
g_lux_f2.SetLineWidth( 3 );
mg.Add( &g_lux_f2, "l" );
c.AddLegendEntry( &g_lux_f2, "LUXqed", "l" );*/
+ g_luxlike_f2.SetLineColor( kOrange+2 );
+ g_luxlike_f2.SetLineWidth( 3 );
+ mg.Add( &g_luxlike_f2, "l" );
+ c.AddLegendEntry( &g_luxlike_f2, "Sch#ddot{a}fer et al.", "l" );
+
mg.Draw( "alpr" );
mg.SetTitle( "x_{Bj}\\Proton form factor F_{2}" );
c.Prettify( mg.GetHistogram() );
//mg.GetYaxis()->SetRangeUser( 1.e-10, 10. );
mg.GetYaxis()->SetRangeUser( 0., 0.8 );
mg.GetXaxis()->SetLimits( min_xbj, max_xbj );
if ( use_logarithmic_x ) c.SetLogx();
//c.SetLogy();
c.Save( "pdf" );
return 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Jan 20, 10:51 PM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4242719
Default Alt Text
(328 KB)

Event Timeline