Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F19252254
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
18 KB
Referenced Files
None
Subscribers
None
View Options
Index: amcatnlo-bridge/trunk/src/amcbridge_interface.cxx
===================================================================
--- amcatnlo-bridge/trunk/src/amcbridge_interface.cxx (revision 1162)
+++ amcatnlo-bridge/trunk/src/amcbridge_interface.cxx (revision 1163)
@@ -1,545 +1,545 @@
/*
NLO mode of aMCatNLO
*/
#include <cstdlib>
#include <iostream>
#include <cmath>
// applgrid header files
#include "appl_grid/appl_grid.h"
#include "appl_grid/lumi_pdf.h"
// LHAPDF
#include "LHAPDF/LHAPDF.h"
// amcbridge header files
#include "amcbridge_interface.h"
#include "amcatnlo_common.h"
// ROOT header files
#include "TPad.h"
// lhapdf functions
extern "C" double alphasPDF_(const double&);
extern "C" void evolvePDF_(const double&, const double&, double*);
// External hook functions for aMC@NLO control
extern void (*appl_initptr)();
extern void (*appl_fillptr)();
extern void (*appl_fillrefptr)();
extern void (*appl_termptr)();
extern void (*appl_fillrefoutptr)();
extern void (*appl_recoptr)();
// Hook functions
extern "C" bool setup_amcbridge_() {
std::cout << "setup_amcatnlo() setting up hook functions ..." << std::endl;
appl_initptr = amcbridge::init;
appl_fillptr = amcbridge::fill;
appl_fillrefptr = amcbridge::fill_ref;
appl_termptr = amcbridge::term;
appl_fillrefoutptr = amcbridge::fill_ref_out;
appl_recoptr = amcbridge::reco;
return true;
}
namespace amcbridge {
// Initialise the hook functions
bool amcbridge_ready = setup_amcbridge_();
// Parton luminosity
double lhapdf_lumi(double, double, double, int);
// Check if a file exists
bool file_exists(const std::string& s) {
if(std::FILE* testfile=std::fopen(s.c_str(),"r")) {
std::fclose(testfile);
return true;
}
else return false;
}
// Different names for reading and writing grids to avoid overwriting
appl::grid* grid_obsA = 0;
std::string grid_filenameA_in = "grid_obsA_in.root";
std::string grid_filenameA_out = "grid_obsA_out.root";
appl::grid* grid_obsB = 0;
std::string grid_filenameB_in = "grid_obsB_in.root";
std::string grid_filenameB_out = "grid_obsB_out.root";
//
// Initialization
//
void init() {
//std::cout << "C++, entering init() ..." << std::endl;
// leading_order -> Power of alphas of Born events
int const leading_order = appl_common_fixed_.bpower;
//std::cout << "bpower = " << leading_order << std::endl;
// Number of loops in the APPLgrid formalism.
// Here we store four grids, W0, WR, WF and W0, in the notation of arXiv:1110.4738.
// Always book with nloops = 3
int const nloops = 3; // 4 grids
// Define the settings for the interpolation in x and Q2.
// These are common to all the grids computed.
// (Should we implement a dynamical tuning of the following parameters?)
// Number of points for the Q2 interpolation
int NQ2 = 10;
// Max and min value of Q2
double Q2min = 100;
double Q2max = 1000000;
// Order of the polynomial interpolation in Q2
int Q2order = 3;
// Number of points for the x interpolation
int Nx = 50;
// Min and max value of x
double xmin = 2e-7;
double xmax = 1;
// Order of the polynomial interpolation in x
int xorder = 3;
// Set up the APPLgrid PDF luminosities
std::vector<int> pdf_luminosities;
pdf_luminosities.push_back(appl_common_lumi_.nlumi);
// Loop over parton luminosities
for(int ilumi=0; ilumi<appl_common_lumi_.nlumi; ilumi++) {
int nproc = appl_common_lumi_.nproc[ilumi];
pdf_luminosities.push_back(ilumi);
pdf_luminosities.push_back(nproc);
// Loop over parton-parton combinations within each luminosity
for(int iproc=0; iproc<nproc; iproc++) {
pdf_luminosities.push_back(appl_common_lumi_.lumimap[ilumi][iproc][0]);
pdf_luminosities.push_back(appl_common_lumi_.lumimap[ilumi][iproc][1]);
}
}
// Use a name for the PDF combination type ending with .config.
// This will configure from a file with the same format as the
// aMC@NLO initial_states_map.dat file unless a serialised
// vector including the combinations is also passed to the
// constructor, as is the case here.
std::string genpdf = "amcatnlo.config";
new lumi_pdf(genpdf,pdf_luminosities);
// Grid Initialization and definition of the observables.
// The default is an histogram with equally spaced bins.
// Check that the grid files exists. If so read the grid from the file,
// otherwise create a new grid from scratch.
// Observable A
if(file_exists(grid_filenameA_in)) {
std::cout << "Reading existing APPLgrid from file " << grid_filenameA_in << " ..." << std::endl;
// Open the existing grid
grid_obsA = new appl::grid(grid_filenameA_in);
grid_obsA->optimise(true);
}
else {
std::cout << "Booking grid from scratch with name " << grid_filenameA_in << " ..." << std::endl;
// Create a grid
int Nobs = appl_common_histokin_.obsA_nbins;
double obsmin = appl_common_histokin_.obsA_min;
double obsmax = appl_common_histokin_.obsA_max;
grid_obsA = new appl::grid(NQ2, Q2min, Q2max, Q2order,
Nx, xmin, xmax, xorder,
Nobs, obsmin, obsmax,
genpdf, leading_order, nloops);
// Use the reweighting function
grid_obsA->reweight(true);
// The grid is an aMC@NLO type
grid_obsA->amcatnlo();
// Optimise the grid
//grid_obsA->optimise(true);
}
// Observable B
if(file_exists(grid_filenameB_in)) {
std::cout << "Reading existing applgrid from file " << grid_filenameB_in << " ..." << std::endl;
// Open the existing grid
grid_obsB = new appl::grid(grid_filenameB_in);
grid_obsB->optimise(true);
}
else {
std::cout << "Booking grid from scratch with name " << grid_filenameB_in << " ..." << std::endl;
// Create a grid
int Nobs = appl_common_histokin_.obsB_nbins;
double obsmin = appl_common_histokin_.obsB_min;
double obsmax = appl_common_histokin_.obsB_max;
grid_obsB = new appl::grid(NQ2, Q2min, Q2max, Q2order,
Nx, xmin, xmax, xorder,
Nobs, obsmin, obsmax,
genpdf, leading_order, nloops);
// Use the reweighting function
grid_obsB->reweight(true);
// The grid is an aMC@NLO type
grid_obsB->amcatnlo();
// Optimise the grid
//grid_obsB->optimise(true);
}
//std::cout << "C++, ... exiting init()" << std::endl;
}
//
// Fill the APPLgrid grid with the weights
//
void fill() {
//std::cout << "C++, entering fill() ..." << std::endl;
// Check that itype ranges from 1 to 3.
int itype = appl_common_histokin_.itype_histo;
if(itype != 1 && itype != 2 && itype != 3) {
std::cout << "ERROR: Invalid value of itype = " << itype << std::endl;
exit(-10);
}
// aMC@NLO weights. Four grids, ordered as {W0,WR,WF,WB}.
double* W0 = appl_common_weights_.W0;
double* WR = appl_common_weights_.WR;
double* WF = appl_common_weights_.WF;
double* WB = appl_common_weights_.WB;
int ilumi;
int nlumi = appl_common_lumi_.nlumi;
double ttol = 1e-100;
double x1,x2;
double scale2;
double obsA = appl_common_histokin_.obsA_histo;
double obsB = appl_common_histokin_.obsB_histo;
// Weight vector whose size is the total number of subprocesses
std::vector<double> weight(nlumi,0);
// (n+1)-body contribution (corresponding to xsec11 in aMC@NLO)
// It uses only Events (k=0) and the W0 weight.
if(itype == 1) {
// Get Bjorken x's
x1 = appl_common_weights_.x1[0];
x2 = appl_common_weights_.x2[0];
// Energy scale
scale2 = appl_common_weights_.muF2[0];
// Relevant parton luminosity combinations (-1 offset in c++)
ilumi = appl_common_weights_.flavmap[0] - 1;
if(x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) {
std::cout << "ERROR: Invalid value of x1 and/or x2 = " << x1 << " " << x2 << std::endl;
exit(-10);
}
// Fill grid only if x1 and x1 are non-zero
if(x1 == 0 && x2 == 0) return;
// Fill only if W0 is non zero
if(fabs(W0[0]) < ttol) return;
// Fill the grid with the values of the observables
// W0
weight.at(ilumi) = W0[0];
grid_obsA->fill_grid(x1,x2,scale2,obsA,&weight[0],0);
grid_obsB->fill_grid(x1,x2,scale2,obsB,&weight[0],0);
weight.at(ilumi) = 0;
}
// n-body contribution without Born (corresponding to xsec12 in aMC@NLO)
// It uses all the CounterEvents (k=1,2,3) and the weights W0, WR and WF.
else if(itype == 2) {
for(int k=1; k<=3; k++) {
x1 = appl_common_weights_.x1[k];
x2 = appl_common_weights_.x2[k];
scale2 = appl_common_weights_.muF2[k];
ilumi = appl_common_weights_.flavmap[k] - 1;
if(x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) {
std::cout << "ERROR: Invalid value of x1 and/or x2 = " << x1 << " " << x2 << std::endl;
exit(-10);
}
if(x1 == 0 && x2 == 0) continue;
if(fabs(W0[k]) < ttol && fabs(WR[k]) < ttol && fabs(WF[k]) < ttol) continue;
// W0
weight.at(ilumi) = W0[k];
grid_obsA->fill_grid(x1,x2,scale2,obsA,&weight[0],0);
grid_obsB->fill_grid(x1,x2,scale2,obsB,&weight[0],0);
weight.at(ilumi) = 0;
// WR
weight.at(ilumi) = WR[k];
grid_obsA->fill_grid(x1,x2,scale2,obsA,&weight[0],1);
grid_obsB->fill_grid(x1,x2,scale2,obsB,&weight[0],1);
weight.at(ilumi) = 0;
// WF
weight.at(ilumi) = WF[k];
grid_obsA->fill_grid(x1,x2,scale2,obsA,&weight[0],2);
grid_obsB->fill_grid(x1,x2,scale2,obsB,&weight[0],2);
weight.at(ilumi) = 0;
}
}
// Born (n-body) contribution (corresponding to xsec20 in aMC@NLO)
// It uses only the soft kinematics (k=1) and the weight WB.
else if(itype == 3) {
x1 = appl_common_weights_.x1[1];
x2 = appl_common_weights_.x2[1];
scale2 = appl_common_weights_.muF2[1];
ilumi = appl_common_weights_.flavmap[1] - 1;
if(x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) {
std::cout << "ERROR: Invalid value of x1 and/or x2 = " << x1 << " " << x2 << std::endl;
exit(-10);
}
if(x1 == 0 && x2 == 0) return;
if(fabs(WB[1]) < ttol) return;
// WB
weight.at(ilumi) = WB[1];
grid_obsA->fill_grid(x1,x2,scale2,obsA,&weight[0],3);
grid_obsB->fill_grid(x1,x2,scale2,obsB,&weight[0],3);
weight.at(ilumi) = 0;
}
//std::cout << "C++, ... exiting fill()" << std::endl;
}
//
// Fill the APPLgrid reference histogram.
//
void fill_ref() {
//std::cout << "C++, entering fill_ref() ..." << std::endl;
// Event weights to fill the histograms
double www = appl_common_histokin_.www_histo;
// Physical observables
double obsA = appl_common_histokin_.obsA_histo;
double obsB = appl_common_histokin_.obsB_histo;
grid_obsA->getReference()->Fill(obsA,www);
grid_obsB->getReference()->Fill(obsB,www);
//std::cout << "C++, ... exiting fill_ref()" << std::endl;
}
//
// Final normalization of the APPLgrid reference histogram.
//
void fill_ref_out() {
//std::cout << "C++, entering fill_ref_out() ..." << std::endl;
// Normalization factor
double norm = appl_common_histokin_.norm_histo;
// Check normalization value
if(norm <= 0.0 || norm > 1e50) {
std::cout << "ERROR: Invalid value for histogram normalization = " << norm << std::endl;
exit(-10);
}
// APPLgrid does not normalizes the reference histograms to the bin width
// just as in aMC@NLO, so no extra scaling by bin width needed.
grid_obsA->getReference()->Scale(norm);
grid_obsB->getReference()->Scale(norm);
//std::cout << "C++, ... exiting fill_ref_out()" << std::endl;
}
//
// Write out the grids
//
void term() {
//std::cout << "C++, entering term() ..." << std::endl;
// Normalization factor
double norm = appl_common_histokin_.norm_histo;
double n_runs = 1 / norm;
int n_runs_int = int(round(n_runs));
std::cout << "number of runs = " << n_runs_int << " " << n_runs << " " << norm << std::endl;
// Write out all the grids that have been filled.
// Save only if the pointer has been initialized.
if(grid_obsA) {
grid_obsA->run() = n_runs_int;
//grid_obsA->optimise(true);
// Write the grid to file
grid_obsA->Write(grid_filenameA_out);
}
if(grid_obsB) {
grid_obsB->run() = n_runs_int;
//grid_obsB->optimise(true);
// Write the grid to file
grid_obsB->Write(grid_filenameB_out);
}
//std::cout << "C++, ... exiting term()" << std::endl;
}
//
// Test that the original aMC@NLO event weight is properly reproduced
// by the APPLgrid information and LHAPDF.
//
void reco() {
//std::cout << "C++, entering reco() ..." << std::endl;
// Initialization
double xsec11 = 0;
double xsec12 = 0;
double xsec20 = 0;
// Set the Born alphas power
int const bpow = appl_common_fixed_.bpower;
// Bjorken x's
double x1bj = appl_common_weights_.x1[0];
double x2bj = appl_common_weights_.x2[0];
// Renormalization scale
double muR = std::sqrt(appl_common_weights_.muR2[0]);
// Factorization scale
double muF = std::sqrt(appl_common_weights_.muF2[0]);
// Get value of the strong coupling
double g;
if(muR != 0) g = std::sqrt(4 * M_PI * LHAPDF::alphasPDF(muR));
else g = 0;
// Compute the partonic luminosities
double pdflumi;
if(muF != 0 && x1bj != 0 && x2bj != 0) pdflumi = lhapdf_lumi(x1bj,x2bj,muF,0);
else pdflumi = 0;
// Compute the (n+1)-body NLO contribution to the xsec (xsec11)
xsec11 = pdflumi * appl_common_weights_.W0[0] * std::pow(g,2*bpow+2);
// Counter Events.
// Soft (k=1), Collinear (k=2) and Soft-Collinear (k=3)
for(int k=1; k<4; k++) {
double QES = std::sqrt(appl_common_weights_.muQES2[k]);
double muR = std::sqrt(appl_common_weights_.muR2[k]);
double muF = std::sqrt(appl_common_weights_.muF2[k]);
double xlgmuf = 0;
double xlgmur = 0;
if(QES != 0 && muR != 0 && muF != 0) {
xlgmuf = 2 * std::log(muF / QES);
xlgmur = 2 * std::log(muR / QES);
}
-
+ /*
// Check that (for the moment) the scale variation logarithms are
// always set to zero.
// Scale variation is included a posteriori using APPLgrid.
double const eps_scale = 1e-10;
if(fabs(xlgmuf) > eps_scale || fabs(xlgmur) > eps_scale) {
std::cout << "ERROR: scale variations logarithms non-zero" << std::endl;
std::cout << "xlgmuf = " << xlgmuf << std::endl;
std::cout << "xlgmur = " << xlgmur << std::endl;
exit(-10);
}
-
+ */
// Get values of Bjorken's x for the counterevent k
double x1bj = appl_common_weights_.x1[k];
double x2bj = appl_common_weights_.x2[k];
// Get value of the strong coupling
double g;
if(muR != 0) g = std::sqrt(4 * M_PI * LHAPDF::alphasPDF(muR));
else g = 0;
// Compute the partonic luminosities
double pdflumi;
if(muF != 0 && x1bj != 0 && x2bj != 0) pdflumi = lhapdf_lumi(x1bj,x2bj,muF,k);
else pdflumi = 0;
// Compute the n-body NLO contribution to the xsec (xsec12)
xsec12 += pdflumi * ( appl_common_weights_.W0[k] + appl_common_weights_.WF[k] * xlgmuf + appl_common_weights_.WR[k] * xlgmur ) * std::pow(g,2*bpow+2);
// Compute the Born contribution to the xsec (xsec20)
if(k == 1) {
if(bpow > 0) xsec20 += pdflumi * appl_common_weights_.WB[k] * std::pow(g,2*bpow);
else xsec20 += pdflumi * appl_common_weights_.WB[k];
}
}
// Sum up all the contributions
double xsec = xsec20 + xsec11 + xsec12;
// Divide by the vegas weight to compare with the physical cross section
xsec /= appl_common_reco_.vegaswgt;
// Compare with the reference weight
double xsec_ref = appl_common_reco_.event_weight;
double diff;
if(xsec_ref == 0) {
if(xsec == 0) diff = 0;
else {
std::cout << "ERROR: Failed reconstruction of original event weight" << std::endl;
std::cout << "xsec = " << xsec << std::endl;
std::cout << "xsec_ref = " << xsec_ref << std::endl;
exit(-10);
}
}
else diff = fabs( ( xsec - xsec_ref ) / xsec_ref );
// Check the accuracy
if(diff > 1e-5) {
std::cout << "ERROR: Failed reconstruction of original event weight" << std::endl;
std::cout << "xsec = " << xsec << std::endl;
std::cout << "xsec_ref = " << xsec_ref << std::endl;
exit(-10);
}
//std::cout << "C++, ... exiting reco()" << std::endl;
return;
}
//
// PDF luminosity based on LHAPDF and the information on the appl_common.inc block
//
double lhapdf_lumi(double x1bj, double x2bj, double qpdf, int k) {
// Conversion factor from natural units to pb
double const conv = 389379660;
// initialization
double pdflumi = 0;
// Check
if(k<0 || k>3) {
std::cout << "ERROR: Invalid value of k = " << k << std::endl;
exit(-10);
}
// Return zero if the Bjorken's x is equal to zero
if(x1bj == 0 || x2bj == 0 ) return 0;
// Select luminosity
int ilumi = appl_common_weights_.flavmap[k] - 1;
// Check physical range
if(ilumi < 0 || ilumi >= appl_common_lumi_.nlumi) {
std::cout << "ERROR: Invalid value of flavor map" << std::endl;
std::cout << "flavmap[k], nlumi = " << ilumi << " " << appl_common_lumi_.nlumi << std::endl;
exit(-10);
}
// Call the PDFs
for(int iproc=0; iproc<appl_common_lumi_.nproc[ilumi]; iproc++) {
// Get PDF flavors ID
int flav1 = appl_common_lumi_.lumimap[ilumi][iproc][0];
int flav2 = appl_common_lumi_.lumimap[ilumi][iproc][1];
// Check LHAPDF conventions are satisfied
// Assume always working in nf=5 scheme at most
if(flav1 < (-5) || flav2 < (-5) || flav2 > (+5) || flav2 > (+5)) {
std::cout << "ERROR: Invalid value of PDF flavor indices" << std::endl;
std::cout << "flav1, flav2 = " << flav1 << " " << flav2 << std::endl;
exit(-10);
}
// Compute the luminosity
double xpdflh_1 = LHAPDF::xfx(x1bj,qpdf,flav1);
double xpdflh_2 = LHAPDF::xfx(x2bj,qpdf,flav2);
pdflumi += ( xpdflh_1 / x1bj ) * ( xpdflh_2 / x2bj );
}
pdflumi *= conv;
return pdflumi;
}
} // end namespace amcbridge
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Sep 30, 6:15 AM (2 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
6566505
Default Alt Text
(18 KB)
Attached To
Mode
rAPPLGRIDSVN applgridsvn
Attached
Detach File
Event Timeline
Log In to Comment