StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
LHAPDF5.h
1 // LHAPDF5.h is a part of the PYTHIA event generator.
2 // Copyright (C) 2020 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // This file contains the LHAPDF5 PDF plugin class.
7 
8 #ifndef Pythia8_LHAPDF5_H
9 #define Pythia8_LHAPDF5_H
10 
11 #include "Pythia8/PartonDistributions.h"
12 
13 namespace Pythia8 {
14 
15 //==========================================================================
16 
17 // Interfaces to to make the C++ calls similar to f77.
18 
19 //--------------------------------------------------------------------------
20 
21 // Declare the LHAPDF5 f77 subroutines that are needed.
22 
23 extern "C" {
24 
25  extern void initpdfsetm_(int&, const char*, int);
26 
27  extern void initpdfsetbynamem_(int&, const char*, int);
28 
29  extern void initpdfm_(int&, int&);
30 
31  extern void evolvepdfm_(int&, double&, double&, double*);
32 
33  extern void evolvepdfpm_(int&, double&, double&, double&, double&, double*);
34 
35  extern void evolvepdfphotonm_(int&, double&, double&, double*, double&);
36 
37  extern void setlhaparm_(const char*, int);
38 
39  extern void getxminm_(int &, int &, double &);
40 
41  extern void getxmaxm_(int &, int &, double &);
42 
43  extern void getq2minm_(int &, int &, double &);
44 
45  extern void getq2maxm_(int &, int &, double &);
46 
47 }
48 
49 //--------------------------------------------------------------------------
50 
51 // Map the f77 routines to C++.
52 
53 namespace LHAPDF5Interface {
54 
55  // Initialize set with full pathname, allowing multiple sets.
56  void initPDFsetM( int& nSet, string name) {
57  const char* cName = name.c_str(); int lenName = name.length();
58  initpdfsetm_( nSet, cName, lenName);
59  }
60 
61  // Initialize set with simple name, allowing multiple sets.
62  void initPDFsetByNameM( int& nSet, string name) {
63  const char* cName = name.c_str(); int lenName = name.length();
64  initpdfsetbynamem_( nSet, cName, lenName);
65  }
66 
67  // Initialize member of set.
68  void initPDFM(int& nSet, int member) {
69  initpdfm_(nSet, member);
70  }
71 
72  // Evaluate x f_i(x, Q).
73  void evolvePDFM( int& nSet, double x, double Q, double* xfArray) {
74  evolvepdfm_( nSet, x, Q, xfArray);
75  }
76 
77  // Evaluate x f_i(x, Q) for photon beams.
78  void evolvePDFpM( int& nSet, double x, double Q, double P2, double IP2,
79  double* xfArray) {
80  evolvepdfpm_( nSet, x, Q, P2, IP2, xfArray);
81  }
82 
83  // Evaluate x f_i(x, Q) including photon
84  void evolvePDFPHOTONM(int& nSet, double x, double Q, double* xfArray,
85  double& xPhoton) {
86  evolvepdfphotonm_( nSet, x, Q, xfArray, xPhoton);
87  }
88 
89  // Extrapolate PDF set beyond boundaries, or freeze them there.
90  void setPDFparm(string name) {
91  const char* cName = name.c_str(); int lenName = name.length();
92  setlhaparm_( cName, lenName);
93  }
94 
95  // Simple structure to hold LHAPDF set information.
96  struct LHAPDFInfo {
97  string name;
98  int member;
99  bool photon;
100  };
101 
102  // Global tracking of opened PDF sets.
103  map<int, LHAPDFInfo> initializedSets;
104 
105  // Method to find the nSet number corresponding to a name and member.
106  // Returns -1 if no such LHAPDF5 set has been initialized.
107  int findNSet(string setName, int member) {
108  for (map<int, LHAPDFInfo>::const_iterator i = initializedSets.begin();
109  i != initializedSets.end(); ++i) {
110  int iSet = i->first;
111  string iName = i->second.name;
112  int iMember = i->second.member;
113  if (iName == setName && iMember == member) return iSet;
114  }
115  return -1;
116  }
117 
118  // Method to return the lowest non-occupied nSet number.
119  int freeNSet() {
120  for (int iSet = 1; iSet <= int(initializedSets.size()); ++iSet) {
121  if (initializedSets.find(iSet) == initializedSets.end())
122  return iSet;
123  }
124  return initializedSets.size() + 1;
125  }
126 
127 }
128 
129 //==========================================================================
130 
131 // Plugin interface to the LHAPDF5 library.
132 
133 //==========================================================================
134 
135 // Provide plugin interface to the LHAPDF5 library of parton densities.
136 
137 class LHAPDF5 : public PDF {
138 
139 public:
140 
141  // Constructor.
142  LHAPDF5(int idBeamIn, string setName, int member, int nSetIn = -1) :
143  PDF(idBeamIn), doExtraPol(false), nSet(nSetIn)
144  { init(setName, member); isPhoton = (idBeamIn == 22) ? true : false; }
145 
146  // Allow extrapolation beyond boundaries. This is optional.
147  void setExtrapolate(bool extrapol);
148 
149 private:
150 
151  // Initialization of PDF set.
152  void init(string setName, int member);
153 
154  // Update all PDF values.
155  void xfUpdate(int , double x, double Q2);
156 
157  // Current set and pdf values.
158  bool doExtraPol;
159  int nSet;
160  double xfArray[13];
161  bool hasPhoton, isPhoton;
162  double xPhoton;
163 
164 };
165 
166 //--------------------------------------------------------------------------
167 
168 // Initialize a parton density function from LHAPDF5.
169 
170 void LHAPDF5::init(string setName, int member) {
171 
172  // If already initialized then need not do anything further.
173  LHAPDF5Interface::LHAPDFInfo initializedInfo =
174  LHAPDF5Interface::initializedSets[nSet];
175  string initializedSetName = initializedInfo.name;
176  int initializedMember = initializedInfo.member;
177  hasPhoton = initializedInfo.photon;
178  if (setName == initializedSetName && member == initializedMember) return;
179 
180  // Initialize set. If first character is '/' then assume that name
181  // is given with path, else not.
182  if (setName[0] == '/') LHAPDF5Interface::initPDFsetM( nSet, setName);
183  else LHAPDF5Interface::initPDFsetByNameM( nSet, setName);
184  isSet = (nSet >= 0);
185 
186  // Initialize member.
187  LHAPDF5Interface::initPDFM(nSet, member);
188 
189  // Do not collect statistics on under/overflow to save time and space.
190  LHAPDF5Interface::setPDFparm( "NOSTAT" );
191  LHAPDF5Interface::setPDFparm( "LOWKEY" );
192 
193  // Check if photon PDF available (has_photon does not work properly).
194  xPhoton = 0;
195  LHAPDF5Interface::evolvePDFPHOTONM(nSet, 0.01, 1, xfArray, xPhoton);
196  hasPhoton = xPhoton != 0;
197 
198  // Save values to avoid unnecessary reinitializations.
199  initializedInfo.name = setName;
200  initializedInfo.member = member;
201  initializedInfo.photon = hasPhoton;
202  if (nSet > 0) LHAPDF5Interface::initializedSets[nSet] = initializedInfo;
203 
204 }
205 
206 //--------------------------------------------------------------------------
207 
208 // Allow optional extrapolation beyond boundaries.
209 
210 void LHAPDF5::setExtrapolate(bool extrapol) {
211 
212  doExtraPol = extrapol;
213  LHAPDF5Interface::setPDFparm( (extrapol) ? "EXTRAPOLATE" : "18" );
214 
215 }
216 
217 //--------------------------------------------------------------------------
218 
219 // Give the parton distribution function set from LHAPDF5.
220 
221 void LHAPDF5::xfUpdate(int, double x, double Q2) {
222 
223  // Freeze at boundary value if PDF is evaluated outside the fit region.
224  int member = LHAPDF5Interface::initializedSets[nSet].member;
225  double xMin, xMax, q2Min, q2Max;
226  getxminm_( nSet, member, xMin);
227  getxmaxm_( nSet, member, xMax);
228  getq2minm_(nSet, member, q2Min);
229  getq2maxm_(nSet, member, q2Max);
230  if (x < xMin && !doExtraPol) x = xMin;
231  if (x > xMax) x = xMax;
232  if (Q2 < q2Min) Q2 = q2Min;
233  if (Q2 > q2Max) Q2 = q2Max;
234  double Q = sqrt( max( 0., Q2));
235 
236  // Use special call if photon included in proton.
237  if (hasPhoton) {
238  LHAPDF5Interface::evolvePDFPHOTONM( nSet, x, Q, xfArray, xPhoton);
239  }
240 
241  // Use special call with photon beams. No virtualities implemented yet.
242  else if (isPhoton) {
243  LHAPDF5Interface::evolvePDFpM( nSet, x, Q, 0., 0., xfArray);
244  }
245 
246  // Else use default LHAPDF5 call.
247  else {
248  LHAPDF5Interface::evolvePDFM( nSet, x, Q, xfArray);
249  xPhoton=0.0;
250  }
251 
252  // Update values.
253  xg = xfArray[6];
254  xu = xfArray[8];
255  xd = xfArray[7];
256  xs = xfArray[9];
257  xubar = xfArray[4];
258  xdbar = xfArray[5];
259  xsbar = xfArray[3];
260  xc = xfArray[10];
261  xb = xfArray[11];
262  xgamma = xPhoton;
263 
264  // Subdivision of valence and sea.
265  xuVal = xu - xubar;
266  xuSea = xubar;
267  xdVal = xd - xdbar;
268  xdSea = xdbar;
269 
270  // idSav = 9 to indicate that all flavours reset.
271  idSav = 9;
272 
273 }
274 
275 //--------------------------------------------------------------------------
276 
277 // Define external handles to the plugin for dynamic loading.
278 
279 extern "C" {
280 
281  LHAPDF5* newPDF(int idBeamIn, string setName, int member) {
282  int nSet = LHAPDF5Interface::findNSet(setName, member);
283  if (nSet == -1) nSet = LHAPDF5Interface::freeNSet();
284  return new LHAPDF5(idBeamIn, setName, member, nSet);
285  }
286 
287  void deletePDF(LHAPDF5* pdf) {delete pdf;}
288 
289 }
290 
291 //==========================================================================
292 
293 } // end namespace Pythia8
294 
295 #endif // end Pythia8_LHAPDF5_H