StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
PartonDistributions.cc
1 // PartonDistributions.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2014 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // Function definitions (not found in the header) for the PDF, LHAPDF,
7 // GRV94L, CTEQ5L, MSTWpdf, CTEQ6pdf, GRVpiL, PomFix, PomH1FitAB,
8 // PomH1Jets, Lepton and NNPDF classes.
9 
10 #include "Pythia8/PartonDistributions.h"
11 #include "Pythia8/LHAPDFInterface.h"
12 
13 namespace Pythia8 {
14 
15 //==========================================================================
16 
17 // Base class for parton distribution functions.
18 
19 //--------------------------------------------------------------------------
20 
21 // Resolve valence content for assumed meson. Possibly modified later.
22 
23 void PDF::setValenceContent() {
24 
25  // Subdivide meson by flavour content.
26  if (idBeamAbs < 100 || idBeamAbs > 1000) return;
27  int idTmp1 = idBeamAbs/100;
28  int idTmp2 = (idBeamAbs/10)%10;
29 
30  // Find which is quark and which antiquark.
31  if (idTmp1%2 == 0) {
32  idVal1 = idTmp1;
33  idVal2 = -idTmp2;
34  } else {
35  idVal1 = idTmp2;
36  idVal2 = -idTmp1;
37  }
38  if (idBeam < 0) {
39  idVal1 = -idVal1;
40  idVal2 = -idVal2;
41  }
42 
43  // Special case for Pomeron, to start off.
44  if (idBeamAbs == 990) {
45  idVal1 = 1;
46  idVal2 = -1;
47  }
48 }
49 
50 //--------------------------------------------------------------------------
51 
52 // Standard parton densities.
53 
54 double PDF::xf(int id, double x, double Q2) {
55 
56  // Need to update if flavour, x or Q2 changed.
57  // Use idSav = 9 to indicate that ALL flavours are up-to-date.
58  // Assume that flavour and antiflavour always updated simultaneously.
59  if ( (abs(idSav) != abs(id) && idSav != 9) || x != xSav || Q2 != Q2Sav)
60  {idSav = id; xfUpdate(id, x, Q2); xSav = x; Q2Sav = Q2;}
61 
62  // Baryon and nondiagonal meson beams: only p, pbar, pi+, pi- for now.
63  if (idBeamAbs == 2212 || idBeamAbs == 211) {
64  int idNow = (idBeam > 0) ? id : -id;
65  int idAbs = abs(id);
66  if (idNow == 0 || idAbs == 21) return max(0., xg);
67  if (idNow == 1) return max(0., xd);
68  if (idNow == -1) return max(0., xdbar);
69  if (idNow == 2) return max(0., xu);
70  if (idNow == -2) return max(0., xubar);
71  if (idNow == 3) return max(0., xs);
72  if (idNow == -3) return max(0., xsbar);
73  if (idAbs == 4) return max(0., xc);
74  if (idAbs == 5) return max(0., xb);
75  if (idAbs == 22) return max(0., xgamma);
76  return 0.;
77 
78  // Baryon beams: n and nbar by isospin conjugation of p and pbar.
79  } else if (idBeamAbs == 2112) {
80  int idNow = (idBeam > 0) ? id : -id;
81  int idAbs = abs(id);
82  if (idNow == 0 || idAbs == 21) return max(0., xg);
83  if (idNow == 1) return max(0., xu);
84  if (idNow == -1) return max(0., xubar);
85  if (idNow == 2) return max(0., xd);
86  if (idNow == -2) return max(0., xdbar);
87  if (idNow == 3) return max(0., xs);
88  if (idNow == -3) return max(0., xsbar);
89  if (idAbs == 4) return max(0., xc);
90  if (idAbs == 5) return max(0., xb);
91  if (idAbs == 22) return max(0., xgamma);
92  return 0.;
93 
94  // Diagonal meson beams: only pi0, Pomeron for now.
95  } else if (idBeam == 111 || idBeam == 990) {
96  int idAbs = abs(id);
97  if (id == 0 || idAbs == 21) return max(0., xg);
98  if (id == idVal1 || id == idVal2) return max(0., xu);
99  if (idAbs <= 2) return max(0., xubar);
100  if (idAbs == 3) return max(0., xs);
101  if (idAbs == 4) return max(0., xc);
102  if (idAbs == 5) return max(0., xb);
103  if (idAbs == 22) return max(0., xgamma);
104  return 0.;
105 
106 
107  // Lepton beam.
108  } else {
109  if (id == idBeam ) return max(0., xlepton);
110  if (abs(id) == 22) return max(0., xgamma);
111  return 0.;
112  }
113 
114 }
115 
116 //--------------------------------------------------------------------------
117 
118 // Only valence part of parton densities.
119 
120 double PDF::xfVal(int id, double x, double Q2) {
121 
122  // Need to update if flavour, x or Q2 changed.
123  // Use idSav = 9 to indicate that ALL flavours are up-to-date.
124  // Assume that flavour and antiflavour always updated simultaneously.
125  if ( (abs(idSav) != abs(id) && idSav != 9) || x != xSav || Q2 != Q2Sav)
126  {idSav = id; xfUpdate(id, x, Q2); xSav = x; Q2Sav = Q2;}
127 
128  // Baryon and nondiagonal meson beams: only p, pbar, n, nbar, pi+, pi-.
129  if (idBeamAbs == 2212) {
130  int idNow = (idBeam > 0) ? id : -id;
131  if (idNow == 1) return max(0., xdVal);
132  if (idNow == 2) return max(0., xuVal);
133  return 0.;
134  } else if (idBeamAbs == 2112) {
135  int idNow = (idBeam > 0) ? id : -id;
136  if (idNow == 1) return max(0., xuVal);
137  if (idNow == 2) return max(0., xdVal);
138  return 0.;
139  } else if (idBeamAbs == 211) {
140  int idNow = (idBeam > 0) ? id : -id;
141  if (idNow == 2 || idNow == -1) return max(0., xuVal);
142  return 0.;
143 
144  // Diagonal meson beams: only pi0, Pomeron for now.
145  } else if (idBeam == 111 || idBeam == 990) {
146  if (id == idVal1 || id == idVal2) return max(0., xuVal);
147  return 0.;
148 
149  // Lepton beam.
150  } else {
151  if (id == idBeam) return max(0., xlepton);
152  return 0.;
153  }
154 
155 }
156 
157 //--------------------------------------------------------------------------
158 
159 // Only sea part of parton densities.
160 
161 double PDF::xfSea(int id, double x, double Q2) {
162 
163  // Need to update if flavour, x or Q2 changed.
164  // Use idSav = 9 to indicate that ALL flavours are up-to-date.
165  // Assume that flavour and antiflavour always updated simultaneously.
166  if ( (abs(idSav) != abs(id) && idSav != 9) || x != xSav || Q2 != Q2Sav)
167  {idSav = id; xfUpdate(id, x, Q2); xSav = x; Q2Sav = Q2;}
168 
169  // Hadron beams.
170  if (idBeamAbs > 100) {
171  int idNow = (idBeam > 0) ? id : -id;
172  int idAbs = abs(id);
173  if (idNow == 0 || idAbs == 21) return max(0., xg);
174  if (idBeamAbs == 2212) {
175  if (idNow == 1) return max(0., xdSea);
176  if (idNow == -1) return max(0., xdbar);
177  if (idNow == 2) return max(0., xuSea);
178  if (idNow == -2) return max(0., xubar);
179  } else if (idBeamAbs == 2112) {
180  if (idNow == 1) return max(0., xuSea);
181  if (idNow == -1) return max(0., xubar);
182  if (idNow == 2) return max(0., xdSea);
183  if (idNow == -2) return max(0., xdbar);
184  } else {
185  if (idAbs <= 2) return max(0., xuSea);
186  }
187  if (idNow == 3) return max(0., xs);
188  if (idNow == -3) return max(0., xsbar);
189  if (idAbs == 4) return max(0., xc);
190  if (idAbs == 5) return max(0., xb);
191  if (idAbs == 22) return max(0., xgamma);
192  return 0.;
193 
194  // Lepton beam.
195  } else {
196  if (abs(id) == 22) return max(0., xgamma);
197  return 0.;
198  }
199 
200 }
201 
202 //==========================================================================
203 
204 // Interface to the LHAPDF library.
205 
206 //--------------------------------------------------------------------------
207 
208 // Define static member of the LHAPDF class.
209 
210 map< int, pair<string, int> > LHAPDF::initializedSets;
211 
212 //--------------------------------------------------------------------------
213 
214 // Static method to find the nSet number corresponding to a name and member.
215 // Returns -1 if no such LHAPDF set has been initialized.
216 
217 int LHAPDF::findNSet(string setName, int member) {
218  for (map<int, pair<string, int> >::const_iterator
219  i = initializedSets.begin(); i != initializedSets.end(); ++i) {
220  int iSet = i->first;
221  string iName = i->second.first;
222  int iMember = i->second.second;
223  if (iName == setName && iMember == member) return iSet;
224  }
225  return -1;
226 }
227 
228 //--------------------------------------------------------------------------
229 
230 // Static method to return the lowest non-occupied nSet number.
231 
232 int LHAPDF::freeNSet() {
233  for (int iSet = 1; iSet <= int(initializedSets.size()); ++iSet) {
234  if (initializedSets.find(iSet) == initializedSets.end()) return iSet;
235  }
236  return initializedSets.size() + 1;
237 }
238 
239 //--------------------------------------------------------------------------
240 
241 // Initialize a parton density function from LHAPDF.
242 
243 void LHAPDF::init(string setName, int member, Info* infoPtr) {
244 
245  // Determine whether the pdf set contains the photon or not.
246  // So far only MRST2004QED and NNPDF2.3QED.
247  if ( setName == "MRST2004qed.LHgrid"
248  || setName == "NNPDF23_lo_as_0130_qed.LHgrid"
249  || setName == "NNPDF23_lo_as_0130_qed_mem0.LHgrid"
250  || setName == "NNPDF23_lo_as_0119_qed_mem0.LHgrid"
251  || setName == "NNPDF23_lo_as_0130_qed_mem0.LHgrid"
252  || setName == "NNPDF23_nlo_as_0119_qed_mc.LHgrid"
253  || setName == "NNPDF23_nlo_as_0119_qed_mc_mem0.LHgrid"
254  || setName == "NNPDF23_nnlo_as_0119_qed_mc.LHgrid"
255  || setName == "NNPDF23_nnlo_as_0119_qed_mc_mem0.LHgrid" ) hasPhoton = true;
256  else hasPhoton = false;
257 
258  // If already initialized then need not do anything further.
259  pair<string, int> initializedNameMember = initializedSets[nSet];
260  string initializedSetName = initializedNameMember.first;
261  int initializedMember = initializedNameMember.second;
262  if (setName == initializedSetName && member == initializedMember) return;
263 
264  // Initialize set. If first character is '/' then assume that name
265  // is given with path, else not.
266  if (setName[0] == '/') LHAPDFInterface::initPDFsetM( nSet, setName);
267  else LHAPDFInterface::initPDFsetByNameM( nSet, setName);
268 
269  // Check that not dummy library was linked and put nSet negative.
270  isSet = (nSet >= 0);
271  if (!isSet) {
272  if (infoPtr != 0) infoPtr->errorMsg("Error from LHAPDF::init: "
273  "you try to use LHAPDF but did not link it");
274  else cout << " Error from LHAPDF::init: you try to use LHAPDF "
275  << "but did not link it" << endl;
276  }
277 
278  // Initialize member.
279  LHAPDFInterface::initPDFM(nSet, member);
280 
281  // Do not collect statistics on under/overflow to save time and space.
282  LHAPDFInterface::setPDFparm( "NOSTAT" );
283  LHAPDFInterface::setPDFparm( "LOWKEY" );
284 
285  // Save values to avoid unnecessary reinitializations.
286  if (nSet > 0) initializedSets[nSet] = make_pair(setName, member);
287 
288 }
289 
290 //--------------------------------------------------------------------------
291 
292 // Allow optional extrapolation beyond boundaries.
293 
294 void LHAPDF::setExtrapolate(bool extrapol) {
295 
296  LHAPDFInterface::setPDFparm( (extrapol) ? "EXTRAPOLATE" : "18" );
297 
298 }
299 
300 //--------------------------------------------------------------------------
301 
302 // Give the parton distribution function set from LHAPDF.
303 
304 void LHAPDF::xfUpdate(int , double x, double Q2) {
305 
306  // Let LHAPDF do the evaluation of parton densities.
307  double Q = sqrt( max( 0., Q2));
308 
309  // Use special call if photon included in proton.
310  if (hasPhoton) {
311  LHAPDFInterface::evolvePDFPHOTONM( nSet, x, Q, xfArray, xPhoton);
312  }
313  // Else use default LHAPDF call.
314  else {
315  LHAPDFInterface::evolvePDFM( nSet, x, Q, xfArray);
316  xPhoton=0.0;
317  }
318 
319  // Update values.
320  xg = xfArray[6];
321  xu = xfArray[8];
322  xd = xfArray[7];
323  xs = xfArray[9];
324  xubar = xfArray[4];
325  xdbar = xfArray[5];
326  xsbar = xfArray[3];
327  xc = xfArray[10];
328  xb = xfArray[11];
329  xgamma = xPhoton;
330 
331  // Subdivision of valence and sea.
332  xuVal = xu - xubar;
333  xuSea = xubar;
334  xdVal = xd - xdbar;
335  xdSea = xdbar;
336 
337  // idSav = 9 to indicate that all flavours reset.
338  idSav = 9;
339 
340 }
341 
342 //==========================================================================
343 
344 // Gives the GRV 94 L (leading order) parton distribution function set
345 // in parametrized form. Authors: M. Glueck, E. Reya and A. Vogt.
346 // Ref: M. Glueck, E. Reya and A. Vogt, Z.Phys. C67 (1995) 433.
347 
348 void GRV94L::xfUpdate(int , double x, double Q2) {
349 
350  // Common expressions. Constrain Q2 for which parametrization is valid.
351  double mu2 = 0.23;
352  double lam2 = 0.2322 * 0.2322;
353  double s = (Q2 > mu2) ? log( log(Q2/lam2) / log(mu2/lam2) ) : 0.;
354  double ds = sqrt(s);
355  double s2 = s * s;
356  double s3 = s2 * s;
357 
358  // uv :
359  double nu = 2.284 + 0.802 * s + 0.055 * s2;
360  double aku = 0.590 - 0.024 * s;
361  double bku = 0.131 + 0.063 * s;
362  double au = -0.449 - 0.138 * s - 0.076 * s2;
363  double bu = 0.213 + 2.669 * s - 0.728 * s2;
364  double cu = 8.854 - 9.135 * s + 1.979 * s2;
365  double du = 2.997 + 0.753 * s - 0.076 * s2;
366  double uv = grvv (x, nu, aku, bku, au, bu, cu, du);
367 
368  // dv :
369  double nd = 0.371 + 0.083 * s + 0.039 * s2;
370  double akd = 0.376;
371  double bkd = 0.486 + 0.062 * s;
372  double ad = -0.509 + 3.310 * s - 1.248 * s2;
373  double bd = 12.41 - 10.52 * s + 2.267 * s2;
374  double cd = 6.373 - 6.208 * s + 1.418 * s2;
375  double dd = 3.691 + 0.799 * s - 0.071 * s2;
376  double dv = grvv (x, nd, akd, bkd, ad, bd, cd, dd);
377 
378  // udb :
379  double alx = 1.451;
380  double bex = 0.271;
381  double akx = 0.410 - 0.232 * s;
382  double bkx = 0.534 - 0.457 * s;
383  double agx = 0.890 - 0.140 * s;
384  double bgx = -0.981;
385  double cx = 0.320 + 0.683 * s;
386  double dx = 4.752 + 1.164 * s + 0.286 * s2;
387  double ex = 4.119 + 1.713 * s;
388  double esx = 0.682 + 2.978 * s;
389  double udb = grvw (x, s, alx, bex, akx, bkx, agx, bgx, cx,
390  dx, ex, esx);
391 
392  // del :
393  double ne = 0.082 + 0.014 * s + 0.008 * s2;
394  double ake = 0.409 - 0.005 * s;
395  double bke = 0.799 + 0.071 * s;
396  double ae = -38.07 + 36.13 * s - 0.656 * s2;
397  double be = 90.31 - 74.15 * s + 7.645 * s2;
398  double ce = 0.;
399  double de = 7.486 + 1.217 * s - 0.159 * s2;
400  double del = grvv (x, ne, ake, bke, ae, be, ce, de);
401 
402  // sb :
403  double sts = 0.;
404  double als = 0.914;
405  double bes = 0.577;
406  double aks = 1.798 - 0.596 * s;
407  double as = -5.548 + 3.669 * ds - 0.616 * s;
408  double bs = 18.92 - 16.73 * ds + 5.168 * s;
409  double dst = 6.379 - 0.350 * s + 0.142 * s2;
410  double est = 3.981 + 1.638 * s;
411  double ess = 6.402;
412  double sb = grvs (x, s, sts, als, bes, aks, as, bs, dst, est, ess);
413 
414  // cb :
415  double stc = 0.888;
416  double alc = 1.01;
417  double bec = 0.37;
418  double akc = 0.;
419  double ac = 0.;
420  double bc = 4.24 - 0.804 * s;
421  double dct = 3.46 - 1.076 * s;
422  double ect = 4.61 + 1.49 * s;
423  double esc = 2.555 + 1.961 * s;
424  double chm = grvs (x, s, stc, alc, bec, akc, ac, bc, dct, ect, esc);
425 
426  // bb :
427  double stb = 1.351;
428  double alb = 1.00;
429  double beb = 0.51;
430  double akb = 0.;
431  double ab = 0.;
432  double bb = 1.848;
433  double dbt = 2.929 + 1.396 * s;
434  double ebt = 4.71 + 1.514 * s;
435  double esb = 4.02 + 1.239 * s;
436  double bot = grvs (x, s, stb, alb, beb, akb, ab, bb, dbt, ebt, esb);
437 
438  // gl :
439  double alg = 0.524;
440  double beg = 1.088;
441  double akg = 1.742 - 0.930 * s;
442  double bkg = - 0.399 * s2;
443  double ag = 7.486 - 2.185 * s;
444  double bg = 16.69 - 22.74 * s + 5.779 * s2;
445  double cg = -25.59 + 29.71 * s - 7.296 * s2;
446  double dg = 2.792 + 2.215 * s + 0.422 * s2 - 0.104 * s3;
447  double eg = 0.807 + 2.005 * s;
448  double esg = 3.841 + 0.316 * s;
449  double gl = grvw (x, s, alg, beg, akg, bkg, ag, bg, cg,
450  dg, eg, esg);
451 
452  // Update values
453  xg = gl;
454  xu = uv + 0.5*(udb - del);
455  xd = dv + 0.5*(udb + del);
456  xubar = 0.5*(udb - del);
457  xdbar = 0.5*(udb + del);
458  xs = sb;
459  xsbar = sb;
460  xc = chm;
461  xb = bot;
462 
463  // Subdivision of valence and sea.
464  xuVal = uv;
465  xuSea = xubar;
466  xdVal = dv;
467  xdSea = xdbar;
468 
469  // idSav = 9 to indicate that all flavours reset.
470  idSav = 9;
471 
472 }
473 
474 //--------------------------------------------------------------------------
475 
476 double GRV94L::grvv (double x, double n, double ak, double bk, double a,
477  double b, double c, double d) {
478 
479  double dx = sqrt(x);
480  return n * pow(x, ak) * (1. + a * pow(x, bk) + x * (b + c * dx)) *
481  pow(1. - x, d);
482 
483 }
484 
485 //--------------------------------------------------------------------------
486 
487 double GRV94L::grvw (double x, double s, double al, double be, double ak,
488  double bk, double a, double b, double c, double d, double e, double es) {
489 
490  double lx = log(1./x);
491  return (pow(x, ak) * (a + x * (b + x * c)) * pow(lx, bk) + pow(s, al)
492  * exp(-e + sqrt(es * pow(s, be) * lx))) * pow(1. - x, d);
493 
494 }
495 
496 //--------------------------------------------------------------------------
497 
498 double GRV94L::grvs (double x, double s, double sth, double al, double be,
499  double ak, double ag, double b, double d, double e, double es) {
500 
501  if(s <= sth) {
502  return 0.;
503  } else {
504  double dx = sqrt(x);
505  double lx = log(1./x);
506  return pow(s - sth, al) / pow(lx, ak) * (1. + ag * dx + b * x) *
507  pow(1. - x, d) * exp(-e + sqrt(es * pow(s, be) * lx));
508  }
509 
510 }
511 
512 //==========================================================================
513 
514 // Gives the CTEQ 5 L (leading order) parton distribution function set
515 // in parametrized form. Parametrization by J. Pumplin.
516 // Ref: CTEQ Collaboration, H.L. Lai et al., Eur.Phys.J. C12 (2000) 375.
517 
518 // The range of (x, Q) covered by this parametrization of the QCD
519 // evolved parton distributions is 1E-6 < x < 1, 1.1 GeV < Q < 10 TeV.
520 // In the current implementation, densities are frozen at borders.
521 
522 void CTEQ5L::xfUpdate(int , double x, double Q2) {
523 
524  // Constrain x and Q2 to range for which parametrization is valid.
525  double Q = sqrt( max( 1., min( 1e8, Q2) ) );
526  x = max( 1e-6, min( 1.-1e-10, x) );
527 
528  // Derived kinematical quantities.
529  double y = - log(x);
530  double u = log( x / 0.00001);
531  double x1 = 1. - x;
532  double x1L = log(1. - x);
533  double sumUbarDbar = 0.;
534 
535  // Parameters of parametrizations.
536  const double Qmin[8] = { 0., 0., 0., 0., 0., 0., 1.3, 4.5};
537  const double alpha[8] = { 0.2987216, 0.3407552, 0.4491863, 0.2457668,
538  0.5293999, 0.3713141, 0.03712017, 0.004952010 };
539  const double ut1[8] = { 4.971265, 2.612618, -0.4656819, 3.862583,
540  0.1895615, 3.753257, 4.400772, 5.562568 };
541  const double ut2[8] = { -1.105128, -1.258304e5, -274.2390, -1.265969,
542  -3.069097, -1.113085, -1.356116, -1.801317 };
543  const double am[8][9][3] = {
544  // d.
545  { { 0.5292616E+01, -0.2751910E+01, -0.2488990E+01 },
546  { 0.9714424E+00, 0.1011827E-01, -0.1023660E-01 },
547  { -0.1651006E+02, 0.7959721E+01, 0.8810563E+01 },
548  { -0.1643394E+02, 0.5892854E+01, 0.9348874E+01 },
549  { 0.3067422E+02, 0.4235796E+01, -0.5112136E+00 },
550  { 0.2352526E+02, -0.5305168E+01, -0.1169174E+02 },
551  { -0.1095451E+02, 0.3006577E+01, 0.5638136E+01 },
552  { -0.1172251E+02, -0.2183624E+01, 0.4955794E+01 },
553  { 0.1662533E-01, 0.7622870E-02, -0.4895887E-03 } },
554  // u.
555  { { 0.9905300E+00, -0.4502235E+00, 0.1624441E+00 },
556  { 0.8867534E+00, 0.1630829E-01, -0.4049085E-01 },
557  { 0.8547974E+00, 0.3336301E+00, 0.1371388E+00 },
558  { 0.2941113E+00, -0.1527905E+01, 0.2331879E+00 },
559  { 0.3384235E+02, 0.3715315E+01, 0.8276930E+00 },
560  { 0.6230115E+01, 0.3134639E+01, -0.1729099E+01 },
561  { -0.1186928E+01, -0.3282460E+00, 0.1052020E+00 },
562  { -0.8545702E+01, -0.6247947E+01, 0.3692561E+01 },
563  { 0.1724598E-01, 0.7120465E-02, 0.4003646E-04 } },
564  // g.
565  { { 0.1193572E+03, -0.3886845E+01, -0.1133965E+01 },
566  { -0.9421449E+02, 0.3995885E+01, 0.1607363E+01 },
567  { 0.4206383E+01, 0.2485954E+00, 0.2497468E+00 },
568  { 0.1210557E+03, -0.3015765E+01, -0.1423651E+01 },
569  { -0.1013897E+03, -0.7113478E+00, 0.2621865E+00 },
570  { -0.1312404E+01, -0.9297691E+00, -0.1562531E+00 },
571  { 0.1627137E+01, 0.4954111E+00, -0.6387009E+00 },
572  { 0.1537698E+00, -0.2487878E+00, 0.8305947E+00 },
573  { 0.2496448E-01, 0.2457823E-02, 0.8234276E-03 } },
574  // ubar + dbar.
575  { { 0.2647441E+02, 0.1059277E+02, -0.9176654E+00 },
576  { 0.1990636E+01, 0.8558918E-01, 0.4248667E-01 },
577  { -0.1476095E+02, -0.3276255E+02, 0.1558110E+01 },
578  { -0.2966889E+01, -0.3649037E+02, 0.1195914E+01 },
579  { -0.1000519E+03, -0.2464635E+01, 0.1964849E+00 },
580  { 0.3718331E+02, 0.4700389E+02, -0.2772142E+01 },
581  { -0.1872722E+02, -0.2291189E+02, 0.1089052E+01 },
582  { -0.1628146E+02, -0.1823993E+02, 0.2537369E+01 },
583  { -0.1156300E+01, -0.1280495E+00, 0.5153245E-01 } },
584  // dbar/ubar.
585  { { -0.6556775E+00, 0.2490190E+00, 0.3966485E-01 },
586  { 0.1305102E+01, -0.1188925E+00, -0.4600870E-02 },
587  { -0.2371436E+01, 0.3566814E+00, -0.2834683E+00 },
588  { -0.6152826E+01, 0.8339877E+00, -0.7233230E+00 },
589  { -0.8346558E+01, 0.2892168E+01, 0.2137099E+00 },
590  { 0.1279530E+02, 0.1021114E+00, 0.5787439E+00 },
591  { 0.5858816E+00, -0.1940375E+01, -0.4029269E+00 },
592  { -0.2795725E+02, -0.5263392E+00, 0.1290229E+01 },
593  { 0.0000000E+00, 0.0000000E+00, 0.0000000E+00 } },
594  // sbar.
595  { { 0.1580931E+01, -0.2273826E+01, -0.1822245E+01 },
596  { 0.2702644E+01, 0.6763243E+00, 0.7231586E-02 },
597  { -0.1857924E+02, 0.3907500E+01, 0.5850109E+01 },
598  { -0.3044793E+02, 0.2639332E+01, 0.5566644E+01 },
599  { -0.4258011E+01, -0.5429244E+01, 0.4418946E+00 },
600  { 0.3465259E+02, -0.5532604E+01, -0.4904153E+01 },
601  { -0.1658858E+02, 0.2923275E+01, 0.2266286E+01 },
602  { -0.1149263E+02, 0.2877475E+01, -0.7999105E+00 },
603  { 0.0000000E+00, 0.0000000E+00, 0.0000000E+00 } },
604  // cbar.
605  { { -0.8293661E+00, -0.3982375E+01, -0.6494283E-01 },
606  { 0.2754618E+01, 0.8338636E+00, -0.6885160E-01 },
607  { -0.1657987E+02, 0.1439143E+02, -0.6887240E+00 },
608  { -0.2800703E+02, 0.1535966E+02, -0.7377693E+00 },
609  { -0.6460216E+01, -0.4783019E+01, 0.4913297E+00 },
610  { 0.3141830E+02, -0.3178031E+02, 0.7136013E+01 },
611  { -0.1802509E+02, 0.1862163E+02, -0.4632843E+01 },
612  { -0.1240412E+02, 0.2565386E+02, -0.1066570E+02 },
613  { 0.0000000E+00, 0.0000000E+00, 0.0000000E+00 } },
614  // bbar.
615  { { -0.6031237E+01, 0.1992727E+01, -0.1076331E+01 },
616  { 0.2933912E+01, 0.5839674E+00, 0.7509435E-01 },
617  { -0.8284919E+01, 0.1488593E+01, -0.8251678E+00 },
618  { -0.1925986E+02, 0.2805753E+01, -0.3015446E+01 },
619  { -0.9480483E+01, -0.9767837E+00, -0.1165544E+01 },
620  { 0.2193195E+02, -0.1788518E+02, 0.9460908E+01 },
621  { -0.1327377E+02, 0.1201754E+02, -0.6277844E+01 },
622  { 0.0000000E+00, 0.0000000E+00, 0.0000000E+00 },
623  { 0.0000000E+00, 0.0000000E+00, 0.0000000E+00 } } };
624 
625  // Loop over 8 different parametrizations. Check if inside allowed region.
626  for (int i = 0; i < 8; ++i) {
627  double answer = 0.;
628  if (Q > max(Qmin[i], alpha[i])) {
629 
630  // Evaluate answer.
631  double tmp = log(Q / alpha[i]);
632  double sb = log(tmp);
633  double sb1 = sb - 1.2;
634  double sb2 = sb1*sb1;
635  double af[9];
636  for (int j = 0; j < 9; ++j)
637  af[j] = am[i][j][0] + sb1 * am[i][j][1] + sb2 * am[i][j][2];
638  double part1 = af[1] * pow( y, 1. + 0.01 * af[4]) * (1. + af[8] * u);
639  double part2 = af[0] * x1 + af[3] * x;
640  double part3 = x * x1 * (af[5] + af[6] * x1 + af[7] * x * x1);
641  double part4 = (ut2[i] < -100.) ? ut1[i] * x1L + af[2] * x1L
642  : ut1[i] * x1L + af[2] * log(x1 + exp(ut2[i]));
643  answer = x * exp( part1 + part2 + part3 + part4);
644  answer *= 1. - Qmin[i] / Q;
645  }
646 
647  // Store results.
648  if (i == 0) xd = x * answer;
649  else if (i == 1) xu = x * answer;
650  else if (i == 2) xg = x * answer;
651  else if (i == 3) sumUbarDbar = x * answer;
652  else if (i == 4) { xubar = sumUbarDbar / (1. + answer);
653  xdbar = sumUbarDbar * answer / (1. + answer); }
654  else if (i == 5) {xs = x * answer; xsbar = xs;}
655  else if (i == 6) xc = x * answer;
656  else if (i == 7) xb = x * answer;
657  }
658 
659  // Subdivision of valence and sea.
660  xuVal = xu - xubar;
661  xuSea = xubar;
662  xdVal = xd - xdbar;
663  xdSea = xdbar;
664 
665  // idSav = 9 to indicate that all flavours reset.
666  idSav = 9;
667 
668 }
669 
670 //==========================================================================
671 
672 // The MSTWpdf class.
673 // MSTW 2008 PDF's, specifically the LO one.
674 // Original C++ version by Jeppe Andersen.
675 // Modified by Graeme Watt <watt(at)hep.ucl.ac.uk>.
676 
677 //--------------------------------------------------------------------------
678 
679 // Constants: could be changed here if desired, but normally should not.
680 // These are of technical nature, as described for each.
681 
682 // Number of parton flavours, x and Q2 grid points,
683 // bins below c and b thresholds.
684 const int MSTWpdf::np = 12;
685 const int MSTWpdf::nx = 64;
686 const int MSTWpdf::nq = 48;
687 const int MSTWpdf::nqc0 = 4;
688 const int MSTWpdf::nqb0 = 14;
689 
690 // Range of (x, Q2) grid.
691 const double MSTWpdf::xmin = 1e-6;
692 const double MSTWpdf::xmax = 1.0;
693 const double MSTWpdf::qsqmin = 1.0;
694 const double MSTWpdf::qsqmax = 1e9;
695 
696 // Array of x values.
697 const double MSTWpdf::xxInit[65] = {0., 1e-6, 2e-6, 4e-6, 6e-6, 8e-6,
698  1e-5, 2e-5, 4e-5, 6e-5, 8e-5, 1e-4, 2e-4, 4e-4, 6e-4, 8e-4,
699  1e-3, 2e-3, 4e-3, 6e-3, 8e-3, 1e-2, 1.4e-2, 2e-2, 3e-2, 4e-2, 6e-2,
700  8e-2, 0.10, 0.125, 0.15, 0.175, 0.20, 0.225, 0.25, 0.275, 0.30,
701  0.325, 0.35, 0.375, 0.40, 0.425, 0.45, 0.475, 0.50, 0.525, 0.55,
702  0.575, 0.60, 0.625, 0.65, 0.675, 0.70, 0.725, 0.75, 0.775, 0.80,
703  0.825, 0.85, 0.875, 0.90, 0.925, 0.95, 0.975, 1.0 };
704 
705 // Array of Q values.
706 const double MSTWpdf::qqInit[49] = {0., 1.0, 1.25, 1.5, 0., 0., 2.5, 3.2,
707  4.0, 5.0, 6.4, 8.0, 10., 12., 0., 0., 26.0, 40.0, 64.0, 1e2, 1.6e2,
708  2.4e2, 4e2, 6.4e2, 1e3, 1.8e3, 3.2e3, 5.6e3, 1e4, 1.8e4, 3.2e4, 5.6e4,
709  1e5, 1.8e5, 3.2e5, 5.6e5, 1e6, 1.8e6, 3.2e6, 5.6e6, 1e7, 1.8e7, 3.2e7,
710  5.6e7, 1e8, 1.8e8, 3.2e8, 5.6e8, 1e9 };
711 
712 //--------------------------------------------------------------------------
713 
714 // Initialize PDF: read in data grid from file and set up interpolation.
715 
716 void MSTWpdf::init(int iFitIn, string xmlPath, Info* infoPtr) {
717 
718  // Choice of fit among possibilities. Counters and temporary variables.
719  iFit = iFitIn;
720  int i,n,m,k,l,j;
721  double dtemp;
722 
723  // Variables used for initialising c_ij array:
724  double f[np+1][nx+1][nq+1];
725  double f1[np+1][nx+1][nq+1]; // derivative w.r.t. x
726  double f2[np+1][nx+1][nq+1]; // derivative w.r.t. q
727  double f12[np+1][nx+1][nq+1];// cross derivative
728  double f21[np+1][nx+1][nq+1];// cross derivative
729  int wt[16][16]={{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
730  {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0},
731  {-3,0,0,3,0,0,0,0,-2,0,0,-1,0,0,0,0},
732  {2,0,0,-2,0,0,0,0,1,0,0,1,0,0,0,0},
733  {0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
734  {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0},
735  {0,0,0,0,-3,0,0,3,0,0,0,0,-2,0,0,-1},
736  {0,0,0,0,2,0,0,-2,0,0,0,0,1,0,0,1},
737  {-3,3,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0},
738  {0,0,0,0,0,0,0,0,-3,3,0,0,-2,-1,0,0},
739  {9,-9,9,-9,6,3,-3,-6,6,-6,-3,3,4,2,1,2},
740  {-6,6,-6,6,-4,-2,2,4,-3,3,3,-3,-2,-1,-1,-2},
741  {2,-2,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
742  {0,0,0,0,0,0,0,0,2,-2,0,0,1,1,0,0},
743  {-6,6,-6,6,-3,-3,3,3,-4,4,2,-2,-2,-2,-1,-1},
744  {4,-4,4,-4,2,2,-2,-2,2,-2,-2,2,1,1,1,1}};
745  double xxd,d1d2,cl[16],x[16],d1,d2,y[5],y1[5],y2[5],y12[5];
746  double mc2,mb2,eps=1e-6; // q^2 grid points at mc2+eps, mb2+eps
747 
748  // Select which data file to read for current fit.
749  if (xmlPath[ xmlPath.length() - 1 ] != '/') xmlPath += "/";
750  string fileName = " ";
751  if (iFit == 1) fileName = "mrstlostar.00.dat";
752  if (iFit == 2) fileName = "mrstlostarstar.00.dat";
753  if (iFit == 3) fileName = "mstw2008lo.00.dat";
754  if (iFit == 4) fileName = "mstw2008nlo.00.dat";
755 
756  // Open data file.
757  ifstream data_file( (xmlPath + fileName).c_str() );
758  if (!data_file.good()) {
759  if (infoPtr != 0) infoPtr->errorMsg("Error from MSTWpdf::init: "
760  "did not find parametrization file ", fileName);
761  else cout << " Error from MSTWpdf::init: "
762  << "did not find parametrization file " << fileName << endl;
763  isSet = false;
764  return;
765  }
766 
767  // Read distance, tolerance, heavy quark masses
768  // and alphaS values from file.
769  char comma;
770  int nExtraFlavours;
771  data_file.ignore(256,'\n');
772  data_file.ignore(256,'\n');
773  data_file.ignore(256,'='); data_file >> distance >> tolerance;
774  data_file.ignore(256,'='); data_file >> mCharm;
775  data_file.ignore(256,'='); data_file >> mBottom;
776  data_file.ignore(256,'='); data_file >> alphaSQ0;
777  data_file.ignore(256,'='); data_file >> alphaSMZ;
778  data_file.ignore(256,'='); data_file >> alphaSorder >> comma >> alphaSnfmax;
779  data_file.ignore(256,'='); data_file >> nExtraFlavours;
780  data_file.ignore(256,'\n');
781  data_file.ignore(256,'\n');
782  data_file.ignore(256,'\n');
783 
784  // Use c and b quark masses for outlay of qq array.
785  for (int iqq = 0; iqq < 49; ++iqq) qq[iqq] = qqInit[iqq];
786  mc2=mCharm*mCharm;
787  mb2=mBottom*mBottom;
788  qq[4]=mc2;
789  qq[5]=mc2+eps;
790  qq[14]=mb2;
791  qq[15]=mb2+eps;
792 
793  // Check that the heavy quark masses are sensible.
794  if (mc2 < qq[3] || mc2 > qq[6]) {
795  if (infoPtr != 0) infoPtr->errorMsg("Error from MSTWpdf::init: "
796  "invalid mCharm");
797  else cout << " Error from MSTWpdf::init: invalid mCharm" << endl;
798  isSet = false;
799  return;
800  }
801  if (mb2 < qq[13] || mb2 > qq[16]) {
802  if (infoPtr != 0) infoPtr->errorMsg("Error from MSTWpdf::init: "
803  "invalid mBottom");
804  else cout << " Error from MSTWpdf::init: invalid mBottom" << endl;
805  isSet = false;
806  return;
807  }
808 
809  // The nExtraFlavours variable is provided to aid compatibility
810  // with future grids where, for example, a photon distribution
811  // might be provided (cf. the MRST2004QED PDFs).
812  if (nExtraFlavours < 0 || nExtraFlavours > 1) {
813  if (infoPtr != 0) infoPtr->errorMsg("Error from MSTWpdf::init: "
814  "invalid nExtraFlavours");
815  else cout << " Error from MSTWpdf::init: invalid nExtraFlavours" << endl;
816  isSet = false;
817  return;
818  }
819 
820  // Now read in the grids from the grid file.
821  for (n=1;n<=nx-1;n++)
822  for (m=1;m<=nq;m++) {
823  for (i=1;i<=9;i++)
824  data_file >> f[i][n][m];
825  if (alphaSorder==2) { // only at NNLO
826  data_file >> f[10][n][m]; // = chm-cbar
827  data_file >> f[11][n][m]; // = bot-bbar
828  }
829  else {
830  f[10][n][m] = 0.; // = chm-cbar
831  f[11][n][m] = 0.; // = bot-bbar
832  }
833  if (nExtraFlavours>0)
834  data_file >> f[12][n][m]; // = photon
835  else
836  f[12][n][m] = 0.; // photon
837  if (data_file.eof()) {
838  if (infoPtr != 0) infoPtr->errorMsg("Error from MSTWpdf::init: "
839  "failed to read in data file");
840  else cout << " Error from MSTWpdf::init: failed to read in data file"
841  << endl;
842  isSet = false;
843  return;
844  }
845  }
846 
847  // Check that ALL the file contents have been read in.
848  data_file >> dtemp;
849  if (!data_file.eof()) {
850  if (infoPtr != 0) infoPtr->errorMsg("Error from MSTWpdf::init: "
851  "failed to read in data file");
852  else cout << " Error from MSTWpdf::init: failed to read in data file"
853  << endl;
854  isSet = false;
855  return;
856  }
857 
858  // Close the datafile.
859  data_file.close();
860 
861  // PDFs are identically zero at x = 1.
862  for (i=1;i<=np;i++)
863  for (m=1;m<=nq;m++)
864  f[i][nx][m]=0.0;
865 
866  // Set up the new array in log10(x) and log10(qsq).
867  for (i=1;i<=nx;i++)
868  xx[i]=log10(xxInit[i]);
869  for (m=1;m<=nq;m++)
870  qq[m]=log10(qq[m]);
871 
872  // Now calculate the derivatives used for bicubic interpolation.
873  for (i=1;i<=np;i++) {
874 
875  // Start by calculating the first x derivatives
876  // along the first x value:
877  for (m=1;m<=nq;m++) {
878  f1[i][1][m]=polderivative1(xx[1],xx[2],xx[3],f[i][1][m],f[i][2][m],
879  f[i][3][m]);
880  // Then along the rest (up to the last):
881  for (k=2;k<nx;k++)
882  f1[i][k][m]=polderivative2(xx[k-1],xx[k],xx[k+1],f[i][k-1][m],
883  f[i][k][m],f[i][k+1][m]);
884  // Then for the last column:
885  f1[i][nx][m]=polderivative3(xx[nx-2],xx[nx-1],xx[nx],f[i][nx-2][m],
886  f[i][nx-1][m],f[i][nx][m]);
887  }
888 
889  // Then calculate the qq derivatives. At NNLO there are
890  // discontinuities in the PDFs at mc2 and mb2, so calculate
891  // the derivatives at q^2 = mc2, mc2+eps, mb2, mb2+eps in
892  // the same way as at the endpoints qsqmin and qsqmax.
893  for (m=1;m<=nq;m++) {
894  if (m==1 || m==nqc0+1 || m==nqb0+1) {
895  for (k=1;k<=nx;k++)
896  f2[i][k][m]=polderivative1(qq[m],qq[m+1],qq[m+2],
897  f[i][k][m],f[i][k][m+1],f[i][k][m+2]);
898  }
899  else if (m==nq || m==nqc0 || m==nqb0) {
900  for (k=1;k<=nx;k++)
901  f2[i][k][m]=polderivative3(qq[m-2],qq[m-1],qq[m],
902  f[i][k][m-2],f[i][k][m-1],f[i][k][m]);
903  }
904  else {
905  // The rest:
906  for (k=1;k<=nx;k++)
907  f2[i][k][m]=polderivative2(qq[m-1],qq[m],qq[m+1],
908  f[i][k][m-1],f[i][k][m],f[i][k][m+1]);
909  }
910  }
911 
912  // Now, calculate the cross derivatives.
913  // Calculate these as the average between (d/dx)(d/dy) and (d/dy)(d/dx).
914 
915  // First calculate (d/dx)(d/dy).
916  // Start by calculating the first x derivatives
917  // along the first x value:
918  for (m=1;m<=nq;m++)
919  f12[i][1][m]=polderivative1(xx[1],xx[2],xx[3],f2[i][1][m],
920  f2[i][2][m],f2[i][3][m]);
921  // Then along the rest (up to the last):
922  for (k=2;k<nx;k++) {
923  for (m=1;m<=nq;m++)
924  f12[i][k][m]=polderivative2(xx[k-1],xx[k],xx[k+1],f2[i][k-1][m],
925  f2[i][k][m],f2[i][k+1][m]);
926  }
927  // Then for the last column:
928  for (m=1;m<=nq;m++)
929  f12[i][nx][m]=polderivative3(xx[nx-2],xx[nx-1],xx[nx],
930  f2[i][nx-2][m],f2[i][nx-1][m],f2[i][nx][m]);
931 
932  // Now calculate (d/dy)(d/dx).
933  for (m=1;m<=nq;m++) {
934  if (m==1 || m==nqc0+1 || m==nqb0+1) {
935  for (k=1;k<=nx;k++)
936  f21[i][k][m]=polderivative1(qq[m],qq[m+1],qq[m+2],
937  f1[i][k][m],f1[i][k][m+1],f1[i][k][m+2]);
938  }
939  else if (m==nq || m==nqc0 || m==nqb0) {
940  for (k=1;k<=nx;k++)
941  f21[i][k][m]=polderivative3(qq[m-2],qq[m-1],qq[m],
942  f1[i][k][m-2],f1[i][k][m-1],f1[i][k][m]);
943  }
944  else {
945  // The rest:
946  for (k=1;k<=nx;k++)
947  f21[i][k][m]=polderivative2(qq[m-1],qq[m],qq[m+1],
948  f1[i][k][m-1],f1[i][k][m],f1[i][k][m+1]);
949  }
950  }
951 
952  // Now take the average of (d/dx)(d/dy) and (d/dy)(d/dx).
953  for (k=1;k<=nx;k++) {
954  for (m=1;m<=nq;m++) {
955  f12[i][k][m] = 0.5*(f12[i][k][m]+f21[i][k][m]);
956  }
957  }
958 
959  // Now calculate the coefficients c_ij.
960  for (n=1;n<=nx-1;n++) {
961  for (m=1;m<=nq-1;m++) {
962  d1=xx[n+1]-xx[n];
963  d2=qq[m+1]-qq[m];
964  d1d2=d1*d2;
965 
966  y[1]=f[i][n][m];
967  y[2]=f[i][n+1][m];
968  y[3]=f[i][n+1][m+1];
969  y[4]=f[i][n][m+1];
970 
971  y1[1]=f1[i][n][m];
972  y1[2]=f1[i][n+1][m];
973  y1[3]=f1[i][n+1][m+1];
974  y1[4]=f1[i][n][m+1];
975 
976  y2[1]=f2[i][n][m];
977  y2[2]=f2[i][n+1][m];
978  y2[3]=f2[i][n+1][m+1];
979  y2[4]=f2[i][n][m+1];
980 
981  y12[1]=f12[i][n][m];
982  y12[2]=f12[i][n+1][m];
983  y12[3]=f12[i][n+1][m+1];
984  y12[4]=f12[i][n][m+1];
985 
986  for (k=1;k<=4;k++) {
987  x[k-1]=y[k];
988  x[k+3]=y1[k]*d1;
989  x[k+7]=y2[k]*d2;
990  x[k+11]=y12[k]*d1d2;
991  }
992 
993  for (l=0;l<=15;l++) {
994  xxd=0.0;
995  for (k=0;k<=15;k++) xxd+= wt[l][k]*x[k];
996  cl[l]=xxd;
997  }
998 
999  l=0;
1000  for (k=1;k<=4;k++)
1001  for (j=1;j<=4;j++) c[i][n][m][k][j]=cl[l++];
1002  } //m
1003  } //n
1004  } // i
1005 
1006 }
1007 
1008 //--------------------------------------------------------------------------
1009 
1010 // Update PDF values.
1011 
1012 void MSTWpdf::xfUpdate(int , double x, double Q2) {
1013 
1014  // Update using MSTW routine.
1015  double q = sqrtpos(Q2);
1016  // Quarks:
1017  double dn = parton(1,x,q);
1018  double up = parton(2,x,q);
1019  double str = parton(3,x,q);
1020  double chm = parton(4,x,q);
1021  double bot = parton(5,x,q);
1022  // Valence quarks:
1023  double dnv = parton(7,x,q);
1024  double upv = parton(8,x,q);
1025  double sv = parton(9,x,q);
1026  double cv = parton(10,x,q);
1027  double bv = parton(11,x,q);
1028  // Antiquarks = quarks - valence quarks:
1029  double dsea = dn - dnv;
1030  double usea = up - upv;
1031  double sbar = str - sv;
1032  double cbar = chm - cv;
1033  double bbar = bot - bv;
1034  // Gluon:
1035  double glu = parton(0,x,q);
1036  // Photon (= zero unless considering QED contributions):
1037  double phot = parton(13,x,q);
1038 
1039  // Transfer to Pythia notation.
1040  xg = glu;
1041  xu = up;
1042  xd = dn;
1043  xubar = usea;
1044  xdbar = dsea;
1045  xs = str;
1046  xsbar = sbar;
1047  xc = 0.5 * (chm + cbar);
1048  xb = 0.5 * (bot + bbar);
1049  xgamma = phot;
1050 
1051  // Subdivision of valence and sea.
1052  xuVal = upv;
1053  xuSea = xubar;
1054  xdVal = dnv;
1055  xdSea = xdbar;
1056 
1057  // idSav = 9 to indicate that all flavours reset.
1058  idSav = 9;
1059 
1060 }
1061 
1062 //--------------------------------------------------------------------------
1063 
1064 // Returns the PDF value for parton of flavour 'f' at x,q.
1065 
1066 double MSTWpdf::parton(int f,double x,double q) {
1067 
1068  double qsq;
1069  int ip;
1070  int interpolate(1);
1071  double parton_pdf=0,parton_pdf1=0,anom;
1072  double xxx,qqq;
1073 
1074  qsq=q*q;
1075 
1076  // If mc2 < qsq < mc2+eps, then qsq = mc2+eps.
1077  if (qsq>pow(10.,qq[nqc0]) && qsq<pow(10.,qq[nqc0+1])) {
1078  qsq = pow(10.,qq[nqc0+1]);
1079  }
1080 
1081  // If mb2 < qsq < mb2+eps, then qsq = mb2+eps.
1082  if (qsq>pow(10.,qq[nqb0]) && qsq<pow(10.,qq[nqb0+1])) {
1083  qsq = pow(10.,qq[nqb0+1]);
1084  }
1085 
1086  if (x<xmin) {
1087  interpolate=0;
1088  if (x<=0.) return 0.;
1089  }
1090  else if (x>xmax) return 0.;
1091 
1092  if (qsq<qsqmin) {
1093  interpolate=-1;
1094  if (q<=0.) return 0.;
1095  }
1096  else if (qsq>qsqmax) {
1097  interpolate=0;
1098  }
1099 
1100  if (f==0) ip=1;
1101  else if (f>=1 && f<=5) ip=f+1;
1102  else if (f<=-1 && f>=-5) ip=-f+1;
1103  else if (f>=7 && f<=11) ip=f;
1104  else if (f==13) ip=12;
1105  else if (abs(f)==6 || f==12) return 0.;
1106  else return 0.;
1107 
1108  // Interpolation in log10(x), log10(qsq):
1109  xxx=log10(x);
1110  qqq=log10(qsq);
1111 
1112  if (interpolate==1) { // do usual interpolation
1113  parton_pdf=parton_interpolate(ip,xxx,qqq);
1114  if (f<=-1 && f>=-5) // antiquark = quark - valence
1115  parton_pdf -= parton_interpolate(ip+5,xxx,qqq);
1116  }
1117  else if (interpolate==-1) { // extrapolate to low Q^2
1118 
1119  if (x<xmin) { // extrapolate to low x
1120  parton_pdf = parton_extrapolate(ip,xxx,log10(qsqmin));
1121  parton_pdf1 = parton_extrapolate(ip,xxx,log10(1.01*qsqmin));
1122  if (f<=-1 && f>=-5) { // antiquark = quark - valence
1123  parton_pdf -= parton_extrapolate(ip+5,xxx,log10(qsqmin));
1124  parton_pdf1 -= parton_extrapolate(ip+5,xxx,log10(1.01*qsqmin));
1125  }
1126  }
1127  else { // do usual interpolation
1128  parton_pdf = parton_interpolate(ip,xxx,log10(qsqmin));
1129  parton_pdf1 = parton_interpolate(ip,xxx,log10(1.01*qsqmin));
1130  if (f<=-1 && f>=-5) { // antiquark = quark - valence
1131  parton_pdf -= parton_interpolate(ip+5,xxx,log10(qsqmin));
1132  parton_pdf1 -= parton_interpolate(ip+5,xxx,log10(1.01*qsqmin));
1133  }
1134  }
1135  // Calculate the anomalous dimension, dlog(xf)/dlog(qsq),
1136  // evaluated at qsqmin. Then extrapolate the PDFs to low
1137  // qsq < qsqmin by interpolating the anomalous dimenion between
1138  // the value at qsqmin and a value of 1 for qsq << qsqmin.
1139  // If value of PDF at qsqmin is very small, just set
1140  // anomalous dimension to 1 to prevent rounding errors.
1141  if (fabs(parton_pdf) >= 1.e-5)
1142  anom = max(-2.5, (parton_pdf1-parton_pdf)/parton_pdf/0.01);
1143  else anom = 1.;
1144  parton_pdf = parton_pdf*pow(qsq/qsqmin,anom*qsq/qsqmin+1.-qsq/qsqmin);
1145 
1146  }
1147  else { // extrapolate outside PDF grid to low x or high Q^2
1148  parton_pdf = parton_extrapolate(ip,xxx,qqq);
1149  if (f<=-1 && f>=-5) // antiquark = quark - valence
1150  parton_pdf -= parton_extrapolate(ip+5,xxx,qqq);
1151  }
1152 
1153  return parton_pdf;
1154 }
1155 
1156 //--------------------------------------------------------------------------
1157 
1158 // Interpolate PDF value inside data grid.
1159 
1160 double MSTWpdf::parton_interpolate(int ip, double xxx, double qqq) {
1161 
1162  double g, t, u;
1163  int n, m, l;
1164 
1165  n=locate(xx,nx,xxx); // 0: below xmin, nx: above xmax
1166  m=locate(qq,nq,qqq); // 0: below qsqmin, nq: above qsqmax
1167 
1168  t=(xxx-xx[n])/(xx[n+1]-xx[n]);
1169  u=(qqq-qq[m])/(qq[m+1]-qq[m]);
1170 
1171  // Assume PDF proportional to (1-x)^p as x -> 1.
1172  if (n==nx-1) {
1173  double g0=((c[ip][n][m][1][4]*u+c[ip][n][m][1][3])*u
1174  +c[ip][n][m][1][2])*u+c[ip][n][m][1][1]; // value at xx[n]
1175  double g1=((c[ip][n-1][m][1][4]*u+c[ip][n-1][m][1][3])*u
1176  +c[ip][n-1][m][1][2])*u+c[ip][n-1][m][1][1]; // value at xx[n-1]
1177  double p = 1.0;
1178  if (g0>0.0&&g1>0.0) p = log(g1/g0)/log((xx[n+1]-xx[n-1])/(xx[n+1]-xx[n]));
1179  if (p<=1.0) p=1.0;
1180  g=g0*pow((xx[n+1]-xxx)/(xx[n+1]-xx[n]),p);
1181  }
1182 
1183  // Usual interpolation.
1184  else {
1185  g=0.0;
1186  for (l=4;l>=1;l--) {
1187  g=t*g+((c[ip][n][m][l][4]*u+c[ip][n][m][l][3])*u
1188  +c[ip][n][m][l][2])*u+c[ip][n][m][l][1];
1189  }
1190  }
1191 
1192  return g;
1193 }
1194 
1195 //--------------------------------------------------------------------------
1196 
1197 // Extrapolate PDF value outside data grid.
1198 
1199 
1200 double MSTWpdf::parton_extrapolate(int ip, double xxx, double qqq) {
1201 
1202  double parton_pdf=0.;
1203  int n,m;
1204 
1205  n=locate(xx,nx,xxx); // 0: below xmin, nx: above xmax
1206  m=locate(qq,nq,qqq); // 0: below qsqmin, nq: above qsqmax
1207 
1208  if (n==0&&(m>0&&m<nq)) { // if extrapolation in small x only
1209 
1210  double f0,f1;
1211  f0=parton_interpolate(ip,xx[1],qqq);
1212  f1=parton_interpolate(ip,xx[2],qqq);
1213  if ( f0>1e-3 && f1>1e-3 ) { // if values are positive, keep them so
1214  f0=log(f0);
1215  f1=log(f1);
1216  parton_pdf=exp(f0+(f1-f0)/(xx[2]-xx[1])*(xxx-xx[1]));
1217  } else // otherwise just extrapolate in the value
1218  parton_pdf=f0+(f1-f0)/(xx[2]-xx[1])*(xxx-xx[1]);
1219 
1220  } if (n>0&&m==nq) { // if extrapolation into large q only
1221 
1222  double f0,f1;
1223  f0=parton_interpolate(ip,xxx,qq[nq]);
1224  f1=parton_interpolate(ip,xxx,qq[nq-1]);
1225  if ( f0>1e-3 && f1>1e-3 ) { // if values are positive, keep them so
1226  f0=log(f0);
1227  f1=log(f1);
1228  parton_pdf=exp(f0+(f0-f1)/(qq[nq]-qq[nq-1])*(qqq-qq[nq]));
1229  } else // otherwise just extrapolate in the value
1230  parton_pdf=f0+(f0-f1)/(qq[nq]-qq[nq-1])*(qqq-qq[nq]);
1231 
1232  } if (n==0&&m==nq) { // if extrapolation into large q AND small x
1233 
1234  double f0,f1;
1235  f0=parton_extrapolate(ip,xx[1],qqq);
1236  f1=parton_extrapolate(ip,xx[2],qqq);
1237  if ( f0>1e-3 && f1>1e-3 ) { // if values are positive, keep them so
1238  f0=log(f0);
1239  f1=log(f1);
1240  parton_pdf=exp(f0+(f1-f0)/(xx[2]-xx[1])*(xxx-xx[1]));
1241  } else // otherwise just extrapolate in the value
1242  parton_pdf=f0+(f1-f0)/(xx[2]-xx[1])*(xxx-xx[1]);
1243 
1244  }
1245 
1246  return parton_pdf;
1247 }
1248 
1249 //--------------------------------------------------------------------------
1250 
1251 // Returns an integer j such that x lies inbetween xloc[j] and xloc[j+1].
1252 // unit offset of increasing ordered array xloc assumed.
1253 // n is the length of the array (xloc[n] highest element).
1254 
1255 int MSTWpdf::locate(double xloc[],int n,double x) {
1256  int ju,jm,jl(0),j;
1257  ju=n+1;
1258 
1259  while (ju-jl>1) {
1260  jm=(ju+jl)/2; // compute a mid point.
1261  if ( x>= xloc[jm])
1262  jl=jm;
1263  else ju=jm;
1264  }
1265  if (x==xloc[1]) j=1;
1266  else if (x==xloc[n]) j=n-1;
1267  else j=jl;
1268 
1269  return j;
1270 }
1271 
1272 //--------------------------------------------------------------------------
1273 
1274 // Returns the estimate of the derivative at x1 obtained by a polynomial
1275 // interpolation using the three points (x_i,y_i).
1276 
1277 double MSTWpdf::polderivative1(double x1, double x2, double x3, double y1,
1278  double y2, double y3) {
1279 
1280  return (x3*x3*(y1-y2)+2.0*x1*(x3*(-y1+y2)+x2*(y1-y3))+x2*x2*(-y1+y3)
1281  +x1*x1*(-y2+y3))/((x1-x2)*(x1-x3)*(x2-x3));
1282 
1283 }
1284 
1285 //--------------------------------------------------------------------------
1286 
1287 // Returns the estimate of the derivative at x2 obtained by a polynomial
1288 // interpolation using the three points (x_i,y_i).
1289 
1290 double MSTWpdf::polderivative2(double x1, double x2, double x3, double y1,
1291  double y2, double y3) {
1292 
1293  return (x3*x3*(y1-y2)-2.0*x2*(x3*(y1-y2)+x1*(y2-y3))+x2*x2*(y1-y3)
1294  +x1*x1*(y2-y3))/((x1-x2)*(x1-x3)*(x2-x3));
1295 
1296 }
1297 
1298 //--------------------------------------------------------------------------
1299 
1300 // Returns the estimate of the derivative at x3 obtained by a polynomial
1301 // interpolation using the three points (x_i,y_i).
1302 
1303 double MSTWpdf::polderivative3(double x1, double x2, double x3, double y1,
1304  double y2, double y3) {
1305 
1306  return (x3*x3*(-y1+y2)+2.0*x2*x3*(y1-y3)+x1*x1*(y2-y3)+x2*x2*(-y1+y3)
1307  +2.0*x1*x3*(-y2+y3))/((x1-x2)*(x1-x3)*(x2-x3));
1308 
1309 }
1310 
1311 //==========================================================================
1312 
1313 // The CTEQ6pdf class.
1314 // Code for handling CTEQ6L, CTEQ6L1, CTEQ66.00, CT09MC1, CT09MC2, (CT09MCS?).
1315 
1316 // Constants: could be changed here if desired, but normally should not.
1317 // These are of technical nature, as described for each.
1318 
1319 // Stay away from xMin, xMax, Qmin, Qmax limits.
1320 const double CTEQ6pdf::EPSILON = 1e-6;
1321 
1322 // Assumed approximate power of small-x behaviour for interpolation.
1323 const double CTEQ6pdf::XPOWER = 0.3;
1324 
1325 //--------------------------------------------------------------------------
1326 
1327 // Initialize PDF: read in data grid from file.
1328 
1329 void CTEQ6pdf::init(int iFitIn, string xmlPath, Info* infoPtr) {
1330 
1331  // Choice of fit among possibilities.
1332  iFit = iFitIn;
1333 
1334  // Select which data file to read for current fit.
1335  if (xmlPath[ xmlPath.length() - 1 ] != '/') xmlPath += "/";
1336  string fileName = " ";
1337  if (iFit == 1) fileName = "cteq6l.tbl";
1338  if (iFit == 2) fileName = "cteq6l1.tbl";
1339  if (iFit == 3) fileName = "ctq66.00.pds";
1340  if (iFit == 4) fileName = "ct09mc1.pds";
1341  if (iFit == 5) fileName = "ct09mc2.pds";
1342  if (iFit == 6) fileName = "ct09mcs.pds";
1343  bool isPdsGrid = (iFit > 2);
1344 
1345  // Open data file.
1346  ifstream pdfgrid( (xmlPath + fileName).c_str() );
1347  if (!pdfgrid.good()) {
1348  if (infoPtr != 0) infoPtr->errorMsg("Error from CTEQ6pdf::init: "
1349  "did not find parametrization file ", fileName);
1350  else cout << " Error from CTEQ6pdf::init: "
1351  << "did not find parametrization file " << fileName << endl;
1352  isSet = false;
1353  return;
1354  }
1355 
1356  // Read in common information.
1357  int iDum;
1358  double orderTmp, nQTmp, qTmp, rDum;
1359  string line;
1360  getline( pdfgrid, line);
1361  getline( pdfgrid, line);
1362  getline( pdfgrid, line);
1363  istringstream is1(line);
1364  is1 >> orderTmp >> nQTmp >> lambda >> mQ[1] >> mQ[2] >> mQ[3]
1365  >> mQ[4] >> mQ[5] >> mQ[6];
1366  order = int(orderTmp + 0.5);
1367  nQuark = int(nQTmp + 0.5);
1368  getline( pdfgrid, line);
1369 
1370  // Read in information for the .pds grid format.
1371  if (isPdsGrid) {
1372  getline( pdfgrid, line);
1373  istringstream is2(line);
1374  is2 >> iDum >> iDum >> iDum >> nfMx >> mxVal >> iDum;
1375  if (mxVal > 4) mxVal = 3;
1376  getline( pdfgrid, line);
1377  getline( pdfgrid, line);
1378  istringstream is3(line);
1379  is3 >> nX >> nT >> iDum >> nG >> iDum;
1380  for (int i = 0; i < nG + 2; ++i) getline( pdfgrid, line);
1381  getline( pdfgrid, line);
1382  istringstream is4(line);
1383  is4 >> qIni >> qMax;
1384  for (int iT = 0; iT <= nT; ++iT) {
1385  getline( pdfgrid, line);
1386  istringstream is5(line);
1387  is5 >> qTmp;
1388  tv[iT] = log( log( qTmp/lambda));
1389  }
1390  getline( pdfgrid, line);
1391  getline( pdfgrid, line);
1392  istringstream is6(line);
1393  is6 >> xMin >> rDum;
1394  int nPackX = 6;
1395  xv[0] = 0.;
1396  for (int iXrng = 0; iXrng < int( (nX + nPackX - 1) / nPackX); ++iXrng) {
1397  getline( pdfgrid, line);
1398  istringstream is7(line);
1399  for (int iX = nPackX * iXrng + 1; iX <= nPackX * (iXrng + 1); ++iX)
1400  if (iX <= nX) is7 >> xv[iX];
1401  }
1402  }
1403 
1404  // Read in information for the .tbl grid format.
1405  else {
1406  mxVal = 2;
1407  getline( pdfgrid, line);
1408  istringstream is2(line);
1409  is2 >> nX >> nT >> nfMx;
1410  getline( pdfgrid, line);
1411  getline( pdfgrid, line);
1412  istringstream is3(line);
1413  is3 >> qIni >> qMax;
1414  int nPackT = 6;
1415  for (int iTrng = 0; iTrng < int( (nT + nPackT) / nPackT); ++iTrng) {
1416  getline( pdfgrid, line);
1417  istringstream is4(line);
1418  for (int iT = nPackT * iTrng; iT < nPackT * (iTrng + 1); ++iT)
1419  if (iT <= nT) {
1420  is4 >> qTmp;
1421  tv[iT] = log( log( qTmp / lambda) );
1422  }
1423  }
1424  getline( pdfgrid, line);
1425  getline( pdfgrid, line);
1426  istringstream is5(line);
1427  is5 >> xMin;
1428  int nPackX = 6;
1429  for (int iXrng = 0; iXrng < int( (nX + nPackX) / nPackX); ++iXrng) {
1430  getline( pdfgrid, line);
1431  istringstream is6(line);
1432  for (int iX = nPackX * iXrng; iX < nPackX * (iXrng + 1); ++iX)
1433  if (iX <= nX) is6 >> xv[iX];
1434  }
1435  }
1436 
1437  // Read in the grid proper.
1438  getline( pdfgrid, line);
1439  int nBlk = (nX + 1) * (nT + 1);
1440  int nPts = nBlk * (nfMx + 1 + mxVal);
1441  int nPack = (isPdsGrid) ? 6 : 5;
1442  for (int iRng = 0; iRng < int( (nPts + nPack - 1) / nPack); ++iRng) {
1443  getline( pdfgrid, line);
1444  istringstream is8(line);
1445  for (int i = nPack * iRng + 1; i <= nPack * (iRng + 1); ++i)
1446  if (i <= nPts) is8 >> upd[i];
1447  }
1448 
1449  // Initialize x grid mapped to x^0.3.
1450  xvpow[0] = 0.;
1451  for (int iX = 1; iX <= nX; ++iX) xvpow[iX] = pow(xv[iX], XPOWER);
1452 
1453  // Set x and Q borders with some margin.
1454  xMinEps = xMin * (1. + EPSILON);
1455  xMaxEps = 1. - EPSILON;
1456  qMinEps = qIni * (1. + EPSILON);
1457  qMaxEps = qMax * (1. - EPSILON);
1458 
1459  // Initialize (x, Q) values of previous call.
1460  xLast = 0.;
1461  qLast = 0.;
1462 
1463 }
1464 
1465 //--------------------------------------------------------------------------
1466 
1467 // Update PDF values.
1468 
1469 void CTEQ6pdf::xfUpdate(int , double x, double Q2) {
1470 
1471  // Update using CTEQ6 routine, within allowed (x, q) range.
1472  double xEps = max( xMinEps, x);
1473  double qEps = max( qMinEps, min( qMaxEps, sqrtpos(Q2) ) );
1474 
1475  // Gluon:
1476  double glu = xEps * parton6( 0, xEps, qEps);
1477  // Sea quarks (note wrong order u, d):
1478  double bot = xEps * parton6( 5, xEps, qEps);
1479  double chm = xEps * parton6( 4, xEps, qEps);
1480  double str = xEps * parton6( 3, xEps, qEps);
1481  double usea = xEps * parton6(-1, xEps, qEps);
1482  double dsea = xEps * parton6(-2, xEps, qEps);
1483  // Valence quarks:
1484  double upv = xEps * parton6( 1, xEps, qEps) - usea;
1485  double dnv = xEps * parton6( 2, xEps, qEps) - dsea;
1486 
1487  // Transfer to Pythia notation.
1488  xg = glu;
1489  xu = upv + usea;
1490  xd = dnv + dsea;
1491  xubar = usea;
1492  xdbar = dsea;
1493  xs = str;
1494  xsbar = str;
1495  xc = chm;
1496  xb = bot;
1497  xgamma = 0.;
1498 
1499  // Subdivision of valence and sea.
1500  xuVal = upv;
1501  xuSea = usea;
1502  xdVal = dnv;
1503  xdSea = dsea;
1504 
1505  // idSav = 9 to indicate that all flavours reset.
1506  idSav = 9;
1507 
1508 }
1509 
1510 //--------------------------------------------------------------------------
1511 
1512 // Returns the PDF value for parton of flavour iParton at x, q.
1513 
1514 double CTEQ6pdf::parton6(int iParton, double x, double q) {
1515 
1516  // Put zero for large x. Parton table and interpolation variables.
1517  if (x > xMaxEps) return 0.;
1518  int iP = (iParton > mxVal) ? -iParton : iParton;
1519  double ss = pow( x, XPOWER);
1520  double tt = log( log(q / lambda) );
1521 
1522  // Find location in grid.Skip if same as in latest call.
1523  if (x != xLast || q != qLast) {
1524 
1525  // Binary search in x grid.
1526  iGridX = 0;
1527  iGridLX = -1;
1528  int ju = nX + 1;
1529  int jm = 0;
1530  while (ju - iGridLX > 1 && jm >= 0) {
1531  jm = (ju + iGridLX) / 2;
1532  if (x >= xv[jm]) iGridLX = jm;
1533  else ju = jm;
1534  }
1535 
1536  // Separate acceptable from unacceptable grid points.
1537  if (iGridLX <= -1) return 0.;
1538  else if (iGridLX == 0) iGridX = 0;
1539  else if (iGridLX <= nX - 2) iGridX = iGridLX - 1;
1540  else if (iGridLX == nX - 1) iGridX = iGridLX - 2;
1541  else return 0.;
1542 
1543  // Expressions for interpolation in x Grid.
1544  if (iGridLX > 1 && iGridLX < nX - 1) {
1545  double svec1 = xvpow[iGridX];
1546  double svec2 = xvpow[iGridX+1];
1547  double svec3 = xvpow[iGridX+2];
1548  double svec4 = xvpow[iGridX+3];
1549  double s12 = svec1 - svec2;
1550  double s13 = svec1 - svec3;
1551  xConst[8] = svec2 - svec3;
1552  double s24 = svec2 - svec4;
1553  double s34 = svec3 - svec4;
1554  xConst[6] = ss - svec2;
1555  xConst[7] = ss - svec3;
1556  xConst[0] = s13 / xConst[8];
1557  xConst[1] = s12 / xConst[8];
1558  xConst[2] = s34 / xConst[8];
1559  xConst[3] = s24 / xConst[8];
1560  double s1213 = s12 + s13;
1561  double s2434 = s24 + s34;
1562  double sdet = s12 * s34 - s1213 * s2434;
1563  double tmp = xConst[6] * xConst[7] / sdet;
1564  xConst[4] = (s34 * xConst[6] - s2434 * xConst[7]) * tmp / s12;
1565  xConst[5] = (s1213 * xConst[6] - s12 * xConst[7]) * tmp / s34;
1566  }
1567 
1568  // Binary search in Q grid.
1569  iGridQ = 0;
1570  iGridLQ = -1;
1571  ju = nT + 1;
1572  jm = 0;
1573  while (ju - iGridLQ > 1 && jm >= 0) {
1574  jm = (ju + iGridLQ) / 2;
1575  if (tt >= tv[jm]) iGridLQ = jm;
1576  else ju = jm;
1577  }
1578  if (iGridLQ == 0) iGridQ = 0;
1579  else if (iGridLQ <= nT - 2) iGridQ = iGridLQ - 1;
1580  else iGridQ = nT - 3;
1581 
1582  // Expressions for interpolation in Q Grid.
1583  if (iGridLQ > 0 && iGridLQ < nT - 1) {
1584  double tvec1 = tv[iGridQ];
1585  double tvec2 = tv[iGridQ+1];
1586  double tvec3 = tv[iGridQ+2];
1587  double tvec4 = tv[iGridQ+3];
1588  double t12 = tvec1 - tvec2;
1589  double t13 = tvec1 - tvec3;
1590  tConst[8] = tvec2 - tvec3;
1591  double t24 = tvec2 - tvec4;
1592  double t34 = tvec3 - tvec4;
1593  tConst[6] = tt - tvec2;
1594  tConst[7] = tt - tvec3;
1595  double tmp1 = t12 + t13;
1596  double tmp2 = t24 + t34;
1597  double tdet = t12 * t34 - tmp1 * tmp2;
1598  tConst[0] = t13 / tConst[8];
1599  tConst[1] = t12 / tConst[8];
1600  tConst[2] = t34 / tConst[8];
1601  tConst[3] = t24 / tConst[8];
1602  tConst[4] = (t34 * tConst[6] - tmp2 * tConst[7]) / t12
1603  * tConst[6] * tConst[7] / tdet;
1604  tConst[5] = (tmp1 * tConst[6] - t12 * tConst[7]) / t34
1605  * tConst[6] * tConst[7] / tdet;
1606  }
1607 
1608  // Save x and q values so do not have to redo same again.
1609  xLast = x;
1610  qLast = q;
1611  }
1612 
1613  // Jump to here if x and q are the same as for the last call.
1614  int jtmp = ( (iP + nfMx) * (nT + 1) + (iGridQ - 1) ) * (nX + 1) + iGridX + 1;
1615 
1616  // Interpolate in x space for four different q values.
1617  for(int it = 1; it <= 4; ++it) {
1618  int j1 = jtmp + it * (nX + 1);
1619  if (iGridX == 0) {
1620  double fij[5];
1621  fij[1] = 0.;
1622  fij[2] = upd[j1+1] * pow2(xv[1]);
1623  fij[3] = upd[j1+2] * pow2(xv[2]);
1624  fij[4] = upd[j1+3] * pow2(xv[3]);
1625  double fX = polint4F( &xvpow[0], &fij[1], ss);
1626  fVec[it] = (x > 0.) ? fX / pow2(x) : 0.;
1627  } else if (iGridLX==nX-1) {
1628  fVec[it] = polint4F( &xvpow[nX-3], &upd[j1], ss);
1629  } else {
1630  double sf2 = upd[j1+1];
1631  double sf3 = upd[j1+2];
1632  double g1 = sf2 * xConst[0] - sf3 * xConst[1];
1633  double g4 = -sf2 * xConst[2] + sf3 * xConst[3];
1634  fVec[it] = (xConst[4] * (upd[j1] - g1) + xConst[5] * (upd[j1+3] - g4)
1635  + sf2 * xConst[7] - sf3 * xConst[6]) / xConst[8];
1636  }
1637  }
1638 
1639  // Interpolate in q space for x-interpolated values found above.
1640  double ff;
1641  if( iGridLQ <= 0 ) {
1642  ff = polint4F( &tv[0], &fVec[1], tt);
1643  } else if (iGridLQ >= nT - 1) {
1644  ff=polint4F( &tv[nT-3], &fVec[1], tt);
1645  } else {
1646  double tf2 = fVec[2];
1647  double tf3 = fVec[3];
1648  double g1 = tf2 * tConst[0] - tf3 * tConst[1];
1649  double g4 = -tf2 * tConst[2] + tf3 * tConst[3];
1650  ff = (tConst[4] * (fVec[1] - g1) + tConst[5] * (fVec[4] - g4)
1651  + tf2 * tConst[7] - tf3 * tConst[6]) / tConst[8];
1652  }
1653 
1654  // Done.
1655  return ff;
1656 }
1657 
1658 //--------------------------------------------------------------------------
1659 
1660 // The POLINT4 routine is based on the POLINT routine from "Numerical Recipes",
1661 // but assuming N=4, and ignoring the error estimation.
1662 // Suggested by Z. Sullivan.
1663 
1664 double CTEQ6pdf::polint4F(double xa[],double ya[],double x) {
1665 
1666  double y, h1, h2, h3, h4, w, den, d1, c1, d2, c2, d3, c3, cd1, cc1,
1667  cd2, cc2, dd1, dc1;
1668 
1669  h1 = xa[0] - x;
1670  h2 = xa[1] - x;
1671  h3 = xa[2] - x;
1672  h4 = xa[3] - x;
1673 
1674  w = ya[1] - ya[0];
1675  den = w / (h1 - h2);
1676  d1 = h2 * den;
1677  c1 = h1 * den;
1678 
1679  w = ya[2] - ya[1];
1680  den = w / (h2 - h3);
1681  d2 = h3 * den;
1682  c2 = h2 * den;
1683 
1684  w = ya[3] - ya[2];
1685  den = w / (h3 - h4);
1686  d3 = h4 * den;
1687  c3 = h3 * den;
1688 
1689  w = c2 - d1;
1690  den = w / (h1 - h3);
1691  cd1 = h3 * den;
1692  cc1 = h1 * den;
1693 
1694  w = c3 - d2;
1695  den = w / (h2 - h4);
1696  cd2 = h4 * den;
1697  cc2 = h2 * den;
1698 
1699  w = cc2 - cd1;
1700  den = w / (h1 - h4);
1701  dd1 = h4 * den;
1702  dc1 = h1 * den;
1703 
1704  if (h3 + h4 < 0.) y = ya[3] + d3 + cd2 + dd1;
1705  else if (h2 + h3 < 0.) y = ya[2] + d2 + cd1 + dc1;
1706  else if (h1 + h2 < 0.) y = ya[1] + c2 + cd1 + dc1;
1707  else y = ya[0] + c1 + cc1 + dc1;
1708 
1709  return y;
1710 
1711 }
1712 
1713 //==========================================================================
1714 
1715 // SA Unresolved proton: equivalent photon spectrum from
1716 // V.M. Budnev, I.F. Ginzburg, G.V. Meledin and V.G. Serbo,
1717 // Phys. Rept. 15 (1974/1975) 181.
1718 
1719 // Constants:
1720 const double ProtonPoint::ALPHAEM = 0.00729735;
1721 const double ProtonPoint::Q2MAX = 2.0;
1722 const double ProtonPoint::Q20 = 0.71;
1723 const double ProtonPoint::A = 7.16;
1724 const double ProtonPoint::B = -3.96;
1725 const double ProtonPoint::C = 0.028;
1726 
1727 //--------------------------------------------------------------------------
1728 
1729 // Gives a generic Q2-independent equivalent photon spectrum.
1730 
1731 void ProtonPoint::xfUpdate(int , double x, double /*Q2*/ ) {
1732 
1733  // Photon spectrum
1734  double tmpQ2Min = 0.88 * pow2(x);
1735  double phiMax = phiFunc(x, Q2MAX / Q20);
1736  double phiMin = phiFunc(x, tmpQ2Min / Q20);
1737 
1738  double fgm = 0;
1739  if (phiMax < phiMin && m_infoPtr != 0) {
1740  m_infoPtr->errorMsg("Error from ProtonPoint::xfUpdate: "
1741  "phiMax - phiMin < 0!");
1742  } else {
1743  // Corresponds to: x*f(x)
1744  fgm = (ALPHAEM / M_PI) * (1 - x) * (phiMax - phiMin);
1745  }
1746 
1747  // Update values
1748  xg = 0.;
1749  xu = 0.;
1750  xd = 0.;
1751  xubar = 0.;
1752  xdbar = 0.;
1753  xs = 0.;
1754  xsbar = 0.;
1755  xc = 0.;
1756  xb = 0.;
1757  xgamma = fgm;
1758 
1759  // Subdivision of valence and sea.
1760  xuVal = 0.;
1761  xuSea = 0;
1762  xdVal = 0.;
1763  xdSea = 0;
1764 
1765  // idSav = 9 to indicate that all flavours reset.
1766  idSav = 9;
1767 
1768 }
1769 
1770 //--------------------------------------------------------------------------
1771 
1772 // Function related to Q2 integration.
1773 
1774 double ProtonPoint::phiFunc(double x, double Q) {
1775 
1776  double tmpV = 1. + Q;
1777  double tmpSum1 = 0;
1778  double tmpSum2 = 0;
1779  for (int k=1; k<4; ++k) {
1780  tmpSum1 += 1. / (k * pow(tmpV, k));
1781  tmpSum2 += pow(B, k) / (k * pow(tmpV, k));
1782  }
1783 
1784  double tmpY = pow2(x) / (1 - x);
1785  double funVal = (1 + A * tmpY) * (-1.*log(tmpV / Q) + tmpSum1)
1786  + (1 - B) * tmpY / (4 * Q * pow(tmpV, 3))
1787  + C * (1 + tmpY/4.)* (log((tmpV - B)/tmpV) + tmpSum2);
1788 
1789  return funVal;
1790 
1791 }
1792 
1793 //==========================================================================
1794 
1795 // Gives the GRV 1992 pi+ (leading order) parton distribution function set
1796 // in parametrized form. Authors: Glueck, Reya and Vogt.
1797 // Ref: M. Glueck, E. Reya and A. Vogt, Z. Phys. C53 (1992) 651.
1798 // Allowed variable range: 0.25 GeV^2 < Q^2 < 10^8 GeV^2 and 10^-5 < x < 1.
1799 
1800 void GRVpiL::xfUpdate(int , double x, double Q2) {
1801 
1802  // Common expressions. Constrain Q2 for which parametrization is valid.
1803  double mu2 = 0.25;
1804  double lam2 = 0.232 * 0.232;
1805  double s = (Q2 > mu2) ? log( log(Q2/lam2) / log(mu2/lam2) ) : 0.;
1806  double s2 = s * s;
1807  double x1 = 1. - x;
1808  double xL = -log(x);
1809  double xS = sqrt(x);
1810 
1811  // uv, dbarv.
1812  double uv = (0.519 + 0.180 * s - 0.011 * s2) * pow(x, 0.499 - 0.027 * s)
1813  * (1. + (0.381 - 0.419 * s) * xS) * pow(x1, 0.367 + 0.563 * s);
1814 
1815  // g.
1816  double gl = ( pow(x, 0.482 + 0.341 * sqrt(s))
1817  * ( (0.678 + 0.877 * s - 0.175 * s2) + (0.338 - 1.597 * s) * xS
1818  + (-0.233 * s + 0.406 * s2) * x) + pow(s, 0.599)
1819  * exp(-(0.618 + 2.070 * s) + sqrt(3.676 * pow(s, 1.263) * xL) ) )
1820  * pow(x1, 0.390 + 1.053 * s);
1821 
1822  // sea: u, d, s.
1823  double ub = pow(s, 0.55) * (1. - 0.748 * xS + (0.313 + 0.935 * s) * x)
1824  * pow(x1, 3.359) * exp(-(4.433 + 1.301 * s) + sqrt((9.30 - 0.887 * s)
1825  * pow(s, 0.56) * xL) ) / pow(xL, 2.538 - 0.763 * s);
1826 
1827  // c.
1828  double chm = (s < 0.888) ? 0. : pow(s - 0.888, 1.02) * (1. + 1.008 * x)
1829  * pow(x1, 1.208 + 0.771 * s) * exp(-(4.40 + 1.493 * s)
1830  + sqrt( (2.032 + 1.901 * s) * pow(s, 0.39) * xL) );
1831 
1832  // b.
1833  double bot = (s < 1.351) ? 0. : pow(s - 1.351, 1.03)
1834  * pow(x1, 0.697 + 0.855 * s) * exp(-(4.51 + 1.490 * s)
1835  + sqrt( (3.056 + 1.694 * s) * pow(s, 0.39) * xL) );
1836 
1837  // Update values.
1838  xg = gl;
1839  xu = uv + ub;
1840  xd = ub;
1841  xubar = ub;
1842  xdbar = uv + ub;
1843  xs = ub;
1844  xsbar = ub;
1845  xc = chm;
1846  xb = bot;
1847 
1848  // Subdivision of valence and sea.
1849  xuVal = uv;
1850  xuSea = ub;
1851  xdVal = uv;
1852  xdSea = ub;
1853 
1854  // idSav = 9 to indicate that all flavours reset.
1855  idSav = 9;
1856 
1857 }
1858 
1859 //==========================================================================
1860 
1861 // Pomeron PDF: simple Q2-independent parametrizations N x^a (1 - x)^b.
1862 
1863 //--------------------------------------------------------------------------
1864 
1865 // Calculate normalization factors once and for all.
1866 
1867 void PomFix::init() {
1868 
1869  normGluon = GammaReal(PomGluonA + PomGluonB + 2.)
1870  / (GammaReal(PomGluonA + 1.) * GammaReal(PomGluonB + 1.));
1871  normQuark = GammaReal(PomQuarkA + PomQuarkB + 2.)
1872  / (GammaReal(PomQuarkA + 1.) * GammaReal(PomQuarkB + 1.));
1873 
1874 }
1875 
1876 //--------------------------------------------------------------------------
1877 
1878 // Gives a generic Q2-independent Pomeron PDF.
1879 
1880 void PomFix::xfUpdate(int , double x, double) {
1881 
1882  // Gluon and quark distributions.
1883  double gl = normGluon * pow(x, PomGluonA) * pow( (1. - x), PomGluonB);
1884  double qu = normQuark * pow(x, PomQuarkA) * pow( (1. - x), PomQuarkB);
1885 
1886  // Update values
1887  xg = (1. - PomQuarkFrac) * gl;
1888  xu = (PomQuarkFrac / (4. + 2. * PomStrangeSupp) ) * qu;
1889  xd = xu;
1890  xubar = xu;
1891  xdbar = xu;
1892  xs = PomStrangeSupp * xu;
1893  xsbar = xs;
1894  xc = 0.;
1895  xb = 0.;
1896 
1897  // Subdivision of valence and sea.
1898  xuVal = 0.;
1899  xuSea = xu;
1900  xdVal = 0.;
1901  xdSea = xd;
1902 
1903  // idSav = 9 to indicate that all flavours reset.
1904  idSav = 9;
1905 
1906 }
1907 
1908 //==========================================================================
1909 
1910 // Pomeron PDF: the H1 2006 Fit A and Fit B Q2-dependent parametrizations.
1911 
1912 //--------------------------------------------------------------------------
1913 
1914 void PomH1FitAB::init( int iFit, string xmlPath, Info* infoPtr) {
1915 
1916  // Open files from which grids should be read in.
1917  if (xmlPath[ xmlPath.length() - 1 ] != '/') xmlPath += "/";
1918  string dataFile = "pomH1FitBlo.data";
1919  if (iFit == 1) dataFile = "pomH1FitA.data";
1920  if (iFit == 2) dataFile = "pomH1FitB.data";
1921  ifstream is( (xmlPath + dataFile).c_str() );
1922  if (!is.good()) {
1923  if (infoPtr != 0) infoPtr->errorMsg("Error from PomH1FitAB::init: "
1924  "the H1 Pomeron parametrization file was not found");
1925  else cout << " Error from PomH1FitAB::init: "
1926  << "the H1 Pomeron parametrization file was not found" << endl;
1927  isSet = false;
1928  return;
1929  }
1930 
1931  // Lower and upper bounds. Bin widths for logarithmic spacing.
1932  nx = 100;
1933  xlow = 0.001;
1934  xupp = 0.99;
1935  dx = log(xupp / xlow) / (nx - 1.);
1936  nQ2 = 30;
1937  Q2low = 1.0;
1938  Q2upp = 30000.;
1939  dQ2 = log(Q2upp / Q2low) / (nQ2 - 1.);
1940 
1941  // Read in quark data grid.
1942  for (int i = 0; i < nx; ++i)
1943  for (int j = 0; j < nQ2; ++j)
1944  is >> quarkGrid[i][j];
1945 
1946  // Read in gluon data grid.
1947  for (int i = 0; i < nx; ++i)
1948  for (int j = 0; j < nQ2; ++j)
1949  is >> gluonGrid[i][j];
1950 
1951  // Check for errors during read-in of file.
1952  if (!is) {
1953  if (infoPtr != 0) infoPtr->errorMsg("Error from PomH1FitAB::init: "
1954  "the H1 Pomeron parametrization files could not be read");
1955  else cout << " Error from PomH1FitAB::init: "
1956  << "the H1 Pomeron parametrization files could not be read" << endl;
1957  isSet = false;
1958  return;
1959  }
1960 
1961  // Done.
1962  isSet = true;
1963  return;
1964 }
1965 
1966 //--------------------------------------------------------------------------
1967 
1968 void PomH1FitAB::xfUpdate(int , double x, double Q2) {
1969 
1970  // Retrict input to validity range.
1971  double xt = min( xupp, max( xlow, x) );
1972  double Q2t = min( Q2upp, max( Q2low, Q2) );
1973 
1974  // Lower grid point and distance above it.
1975  double dlx = log( xt / xlow) / dx;
1976  int i = min( nx - 2, int(dlx) );
1977  dlx -= i;
1978  double dlQ2 = log( Q2t / Q2low) / dQ2;
1979  int j = min( nQ2 - 2, int(dlQ2) );
1980  dlQ2 -= j;
1981 
1982  // Interpolate to derive quark PDF.
1983  double qu = (1. - dlx) * (1. - dlQ2) * quarkGrid[i][j]
1984  + dlx * (1. - dlQ2) * quarkGrid[i + 1][j]
1985  + (1. - dlx) * dlQ2 * quarkGrid[i][j + 1]
1986  + dlx * dlQ2 * quarkGrid[i + 1][j + 1];
1987 
1988  // Interpolate to derive gluon PDF.
1989  double gl = (1. - dlx) * (1. - dlQ2) * gluonGrid[i][j]
1990  + dlx * (1. - dlQ2) * gluonGrid[i + 1][j]
1991  + (1. - dlx) * dlQ2 * gluonGrid[i][j + 1]
1992  + dlx * dlQ2 * gluonGrid[i + 1][j + 1];
1993 
1994  // Update values.
1995  xg = rescale * gl;
1996  xu = rescale * qu;
1997  xd = xu;
1998  xubar = xu;
1999  xdbar = xu;
2000  xs = xu;
2001  xsbar = xu;
2002  xc = 0.;
2003  xb = 0.;
2004 
2005  // Subdivision of valence and sea.
2006  xuVal = 0.;
2007  xuSea = xu;
2008  xdVal = 0.;
2009  xdSea = xu;
2010 
2011  // idSav = 9 to indicate that all flavours reset.
2012  idSav = 9;
2013 
2014 }
2015 
2016 //==========================================================================
2017 
2018 // Pomeron PDF: the H1 2007 Jets Q2-dependent parametrization.
2019 
2020 //--------------------------------------------------------------------------
2021 
2022 void PomH1Jets::init( string xmlPath, Info* infoPtr) {
2023 
2024  // Open files from which grids should be read in.
2025  if (xmlPath[ xmlPath.length() - 1 ] != '/') xmlPath += "/";
2026  ifstream isg( (xmlPath + "pomH1JetsGluon.data").c_str() );
2027  ifstream isq( (xmlPath + "pomH1JetsSinglet.data").c_str() );
2028  ifstream isc( (xmlPath + "pomH1JetsCharm.data").c_str() );
2029  if (!isg.good() || !isq.good() || !isc.good()) {
2030  if (infoPtr != 0) infoPtr->errorMsg("Error from PomH1Jets::init: "
2031  "the H1 Pomeron parametrization files were not found");
2032  else cout << " Error from PomH1Jets::init: "
2033  << "the H1 Pomeron parametrization files were not found" << endl;
2034  isSet = false;
2035  return;
2036  }
2037 
2038  // Read in x and Q grids. Do interpolation logarithmically in Q2.
2039  for (int i = 0; i < 100; ++i) {
2040  isg >> setw(13) >> xGrid[i];
2041  }
2042  for (int j = 0; j < 88; ++j) {
2043  isg >> setw(13) >> Q2Grid[j];
2044  Q2Grid[j] = log( Q2Grid[j] );
2045  }
2046 
2047  // Read in gluon data grid.
2048  for (int j = 0; j < 88; ++j) {
2049  for (int i = 0; i < 100; ++i) {
2050  isg >> setw(13) >> gluonGrid[i][j];
2051  }
2052  }
2053 
2054  // Identical x and Q2 grid for singlet, so skip ahead.
2055  double dummy;
2056  for (int i = 0; i < 188; ++i) isq >> setw(13) >> dummy;
2057 
2058  // Read in singlet data grid.
2059  for (int j = 0; j < 88; ++j) {
2060  for (int i = 0; i < 100; ++i) {
2061  isq >> setw(13) >> singletGrid[i][j];
2062  }
2063  }
2064 
2065  // Identical x and Q2 grid for charm, so skip ahead.
2066  for (int i = 0; i < 188; ++i) isc >> setw(13) >> dummy;
2067 
2068  // Read in charm data grid.
2069  for (int j = 0; j < 88; ++j) {
2070  for (int i = 0; i < 100; ++i) {
2071  isc >> setw(13) >> charmGrid[i][j];
2072  }
2073  }
2074 
2075  // Check for errors during read-in of files.
2076  if (!isg || !isq || !isc) {
2077  if (infoPtr != 0) infoPtr->errorMsg("Error from PomH1Jets::init: "
2078  "the H1 Pomeron parametrization files could not be read");
2079  else cout << " Error from PomH1Jets::init: "
2080  << "the H1 Pomeron parametrization files could not be read" << endl;
2081  isSet = false;
2082  return;
2083  }
2084 
2085  // Done.
2086  isSet = true;
2087  return;
2088 }
2089 
2090 //--------------------------------------------------------------------------
2091 
2092 void PomH1Jets::xfUpdate(int , double x, double Q2) {
2093 
2094  // Find position in x array.
2095  double xLog = log(x);
2096  int i = 0;
2097  double dx = 0.;
2098  if (xLog <= xGrid[0]);
2099  else if (xLog >= xGrid[99]) {
2100  i = 98;
2101  dx = 1.;
2102  } else {
2103  while (xLog > xGrid[i]) ++i;
2104  --i;
2105  dx = (xLog - xGrid[i]) / (xGrid[i + 1] - xGrid[i]);
2106  }
2107 
2108  // Find position in y array.
2109  double Q2Log = log(Q2);
2110  int j = 0;
2111  double dQ2 = 0.;
2112  if (Q2Log <= Q2Grid[0]);
2113  else if (Q2Log >= Q2Grid[87]) {
2114  j = 86;
2115  dQ2 = 1.;
2116  } else {
2117  while (Q2Log > Q2Grid[j]) ++j;
2118  --j;
2119  dQ2 = (Q2Log - Q2Grid[j]) / (Q2Grid[j + 1] - Q2Grid[j]);
2120  }
2121 
2122  // Interpolate to derive gluon PDF.
2123  double gl = (1. - dx) * (1. - dQ2) * gluonGrid[i][j]
2124  + dx * (1. - dQ2) * gluonGrid[i + 1][j]
2125  + (1. - dx) * dQ2 * gluonGrid[i][j + 1]
2126  + dx * dQ2 * gluonGrid[i + 1][j + 1];
2127 
2128  // Interpolate to derive singlet PDF. (Sum of u, d, s, ubar, dbar, sbar.)
2129  double sn = (1. - dx) * (1. - dQ2) * singletGrid[i][j]
2130  + dx * (1. - dQ2) * singletGrid[i + 1][j]
2131  + (1. - dx) * dQ2 * singletGrid[i][j + 1]
2132  + dx * dQ2 * singletGrid[i + 1][j + 1];
2133 
2134  // Interpolate to derive charm PDF. (Charge-square times c and cbar.)
2135  double ch = (1. - dx) * (1. - dQ2) * charmGrid[i][j]
2136  + dx * (1. - dQ2) * charmGrid[i + 1][j]
2137  + (1. - dx) * dQ2 * charmGrid[i][j + 1]
2138  + dx * dQ2 * charmGrid[i + 1][j + 1];
2139 
2140  // Update values.
2141  xg = rescale * gl;
2142  xu = rescale * sn / 6.;
2143  xd = xu;
2144  xubar = xu;
2145  xdbar = xu;
2146  xs = xu;
2147  xsbar = xu;
2148  xc = rescale * ch * 9./8.;
2149  xb = 0.;
2150 
2151  // Subdivision of valence and sea.
2152  xuVal = 0.;
2153  xuSea = xu;
2154  xdVal = 0.;
2155  xdSea = xd;
2156 
2157  // idSav = 9 to indicate that all flavours reset.
2158  idSav = 9;
2159 
2160 }
2161 
2162 //==========================================================================
2163 
2164 // Gives electron (or muon, or tau) parton distribution.
2165 
2166 // Constants: alphaEM(0), m_e, m_mu, m_tau.
2167 const double Lepton::ALPHAEM = 0.00729735;
2168 const double Lepton::ME = 0.0005109989;
2169 const double Lepton::MMU = 0.10566;
2170 const double Lepton::MTAU = 1.77699;
2171 
2172 void Lepton::xfUpdate(int id, double x, double Q2) {
2173 
2174  // Squared mass of lepton species: electron, muon, tau.
2175  if (!isInit) {
2176  double mLep = ME;
2177  if (abs(id) == 13) mLep = MMU;
2178  if (abs(id) == 15) mLep = MTAU;
2179  m2Lep = pow2( mLep );
2180  isInit = true;
2181  }
2182 
2183  // Electron inside electron, see R. Kleiss et al., in Z physics at
2184  // LEP 1, CERN 89-08, p. 34
2185  double xLog = log(max(1e-10,x));
2186  double xMinusLog = log( max(1e-10, 1. - x) );
2187  double Q2Log = log( max(3., Q2/m2Lep) );
2188  double beta = (ALPHAEM / M_PI) * (Q2Log - 1.);
2189  double delta = 1. + (ALPHAEM / M_PI) * (1.5 * Q2Log + 1.289868)
2190  + pow2(ALPHAEM / M_PI) * (-2.164868 * Q2Log*Q2Log
2191  + 9.840808 * Q2Log - 10.130464);
2192  double fPrel = beta * pow(1. - x, beta - 1.) * sqrtpos( delta )
2193  - 0.5 * beta * (1. + x) + 0.125 * beta*beta * ( (1. + x)
2194  * (-4. * xMinusLog + 3. * xLog) - 4. * xLog / (1. - x) - 5. - x);
2195 
2196  // Zero distribution for very large x and rescale it for intermediate.
2197  if (x > 1. - 1e-10) fPrel = 0.;
2198  else if (x > 1. - 1e-7) fPrel *= pow(1000.,beta) / (pow(1000.,beta) - 1.);
2199  xlepton = x * fPrel;
2200 
2201  // Photon inside electron (one possible scheme - primitive).
2202  xgamma = (0.5 * ALPHAEM / M_PI) * Q2Log * (1. + pow2(1. - x));
2203 
2204  // idSav = 9 to indicate that all flavours reset.
2205  idSav = 9;
2206 
2207 }
2208 
2209 //==========================================================================
2210 
2211 // The NNPDF class.
2212 // Code for handling NNPDF2.3 QCD+QED LO
2213 // Code provided by Juan Rojo and Stefano Carrazza.
2214 
2215 //--------------------------------------------------------------------------
2216 
2217 // Freeze PDFs below XMINGRID
2218 const double NNPDF::fXMINGRID = 1e-9;
2219 
2220 //--------------------------------------------------------------------------
2221 
2222 // Initialize PDF: read in data grid from file.
2223 
2224 void NNPDF::init(int iFitIn, string xmlPath, Info* infoPtr) {
2225 
2226  // Choice of fit among possibilities.
2227  iFit = iFitIn;
2228 
2229  // Select which data file to read for current fit.
2230  if (xmlPath[ xmlPath.length() - 1 ] != '/') xmlPath += "/";
2231  string fileName = " ";
2232  // NNPDF2.3 LO QCD+QED, for two values of alphas
2233  if (iFit == 1) fileName = "NNPDF23_lo_as_0130_qed_mem0.grid";
2234  if (iFit == 2) fileName = "NNPDF23_lo_as_0119_qed_mem0.grid";
2235  // NNPDF2.3 NLO QCD+QED
2236  if (iFit == 3) fileName = "NNPDF23_nlo_as_0119_qed_mc_mem0.grid";
2237  // NNPDF2.4 NLO QCD+QED
2238  if (iFit == 4) fileName = "NNPDF23_nnlo_as_0119_qed_mc_mem0.grid";
2239 
2240  // Open data file.
2241  fstream f;
2242  f.open( (xmlPath + fileName).c_str(),ios::in);
2243  if (f.fail()) {
2244  if (infoPtr != 0) infoPtr->errorMsg("Error from NNPDF::init: "
2245  "did not find data file ", fileName);
2246  else cout << "Error: cannot open file " << (xmlPath + fileName) << endl;
2247  isSet = false;
2248  return;
2249  }
2250 
2251  // Reading grid: removing header.
2252  string tmp;
2253  for (;;) {
2254  getline(f,tmp);
2255  if (tmp.find("NNPDF20intqed") != string::npos) {
2256  getline(f,tmp);
2257  break;
2258  }
2259  }
2260 
2261  // Get nx and x grid.
2262  f >> fNX;
2263  fXGrid = new double[fNX];
2264  for (int ix = 0; ix < fNX; ix++) f >> fXGrid[ix];
2265  fLogXGrid = new double[fNX];
2266  for (int ix = 0; ix < fNX; ix++) fLogXGrid[ix] = log(fXGrid[ix]);
2267 
2268  // Get nQ2 and Q2 grid (ignorming first value).
2269  f >> fNQ2;
2270  f >> tmp;
2271  fQ2Grid = new double[fNQ2];
2272  for (int iq = 0; iq < fNQ2; iq++) f >> fQ2Grid[iq];
2273  fLogQ2Grid = new double[fNQ2];
2274  for (int iq = 0; iq < fNQ2; iq++) fLogQ2Grid[iq] = log(fQ2Grid[iq]);
2275 
2276  // Prepare grid array.
2277  fPDFGrid = new double**[fNFL];
2278  for (int i = 0; i < fNFL; i++) {
2279  fPDFGrid[i] = new double*[fNX];
2280  for (int j = 0; j < fNX; j++) {
2281  fPDFGrid[i][j] = new double[fNQ2];
2282  for (int z = 0; z < fNQ2; z++) fPDFGrid[i][j][z] = 0.0;
2283  }
2284  }
2285 
2286  // Check values of number of grid entries.
2287  if (fNX<= 0 || fNX>100 || fNQ2<=0 || fNQ2>50) {
2288  cout << "Error in NNPDF::init, Invalid grid values" << endl
2289  << "fNX = " << fNX << endl << "fNQ2 = " << fNQ2 << endl
2290  << "fNFL = " <<fNFL << endl;
2291  isSet = false;
2292  return;
2293  }
2294 
2295  // Ignore replica number. Read PDF grid points.
2296  f >> tmp;
2297  for (int ix = 0; ix < fNX; ix++)
2298  for (int iq = 0; iq < fNQ2; iq++)
2299  for (int fl = 0; fl < fNFL; fl++)
2300  f >> fPDFGrid[fl][ix][iq];
2301  f.close();
2302 
2303  // Other vectors.
2304  fRes = new double[fNFL];
2305 
2306 }
2307 
2308 //--------------------------------------------------------------------------
2309 
2310 void NNPDF::xfUpdate(int , double x, double Q2) {
2311 
2312  // Update using NNPDF routine, within allowed (x, q) range.
2313  xfxevolve(x,Q2);
2314 
2315  // Then transfer to Pythia8 notation.
2316  xg = fRes[6];
2317  xu = fRes[8];
2318  xd = fRes[7];
2319  xubar = fRes[4];
2320  xdbar = fRes[5];
2321  xs = fRes[9];
2322  xsbar = fRes[3];
2323  xc = fRes[10];
2324  xb = fRes[11];
2325  xgamma = fRes[13];
2326 
2327  // Subdivision of valence and sea.
2328  xuVal = xu - xubar;
2329  xuSea = xubar;
2330  xdVal = xd - xdbar;
2331  xdSea = xdbar;
2332 
2333  // idSav = 9 to indicate that all flavours reset.
2334  idSav = 9;
2335 
2336 }
2337 
2338 //--------------------------------------------------------------------------
2339 
2340 void NNPDF::xfxevolve(double x, double Q2) {
2341 
2342  // Freeze outside x-Q2 grid.
2343  if (x < fXMINGRID || x > fXGrid[fNX-1]) {
2344  if (x < fXMINGRID) x = fXMINGRID;
2345  if (x > fXGrid[fNX-1]) x = fXGrid[fNX-1];
2346  }
2347  if (Q2 < fQ2Grid[0] || Q2 > fQ2Grid[fNQ2-1]) {
2348  if (Q2 < fQ2Grid[0]) Q2 = fQ2Grid[0];
2349  if (Q2 > fQ2Grid[fNQ2-1]) Q2 = fQ2Grid[fNQ2-1];
2350  }
2351 
2352  // Find nearest points in the x-Q2 grid.
2353  int minx = 0;
2354  int maxx = fNX;
2355  while (maxx-minx > 1) {
2356  int midx = (minx+maxx)/2;
2357  if (x < fXGrid[midx]) maxx = midx;
2358  else minx = midx;
2359  }
2360  int ix = minx;
2361  int minq = 0;
2362  int maxq = fNQ2;
2363  while (maxq-minq > 1) {
2364  int midq = (minq+maxq)/2;
2365  if (Q2 < fQ2Grid[midq]) maxq = midq;
2366  else minq = midq;
2367  }
2368  int iq2 = minq;
2369 
2370  // Assign grid for interpolation. M,N -> order of polyN interpolation.
2371  int ix1a[fM], ix2a[fN];
2372  double x1a[fM], x2a[fN];
2373  double ya[fM][fN];
2374 
2375  for (int i = 0; i < fM; i++) {
2376  if (ix+1 >= fM/2 && ix+1 <= (fNX-fM/2)) ix1a[i] = ix+1 - fM/2 + i;
2377  if (ix+1 < fM/2) ix1a[i] = i;
2378  if (ix+1 > (fNX-fM/2)) ix1a[i] = (fNX-fM) + i;
2379  // Check grids.
2380  if (ix1a[i] < 0 || ix1a[i] >= fNX) {
2381  cout << "Error in grids! i, ixia[i] = " << i << "\t" << ix1a[i] << endl;
2382  return;
2383  }
2384  }
2385 
2386  for (int j = 0; j < fN; j++) {
2387  if (iq2+1 >= fN/2 && iq2+1 <= (fNQ2-fN/2)) ix2a[j] = iq2+1 - fN/2 + j;
2388  if (iq2+1 < fN/2) ix2a[j] = j;
2389  if (iq2+1 > (fNQ2-fN/2)) ix2a[j] = (fNQ2-fN) + j;
2390  // Check grids.
2391  if (ix2a[j] < 0 || ix2a[j] >= fNQ2) {
2392  cout << "Error in grids! j, ix2a[j] = " << j << "\t" << ix2a[j] << endl;
2393  return;
2394  }
2395  }
2396 
2397  const double xch = 1e-1;
2398  double x1;
2399  if (x < xch) x1 = log(x);
2400  else x1 = x;
2401  double x2 = log(Q2);
2402 
2403  for (int ipdf = 0; ipdf < fNFL; ipdf++) {
2404  fRes[ipdf] = 0.0;
2405  for (int i = 0; i < fM; i++) {
2406  if (x < xch) x1a[i] = fLogXGrid[ix1a[i]];
2407  else x1a[i] = fXGrid[ix1a[i]];
2408 
2409  for (int j = 0; j < fN; j++) {
2410  x2a[j] = fLogQ2Grid[ix2a[j]];
2411  ya[i][j] = fPDFGrid[ipdf][ix1a[i]][ix2a[j]];
2412  }
2413  }
2414 
2415  // 2D polynomial interpolation.
2416  double y = 0, dy = 0;
2417  polin2(x1a,x2a,ya,x1,x2,y,dy);
2418  fRes[ipdf] = y;
2419  }
2420 
2421 }
2422 
2423 //--------------------------------------------------------------------------
2424 
2425 // 1D polynomial interpolation.
2426 
2427 void NNPDF::polint(double xa[], double yal[], int n, double x,
2428  double& y, double& dy) {
2429 
2430  int ns = 0;
2431  double dif = abs(x-xa[0]);
2432  double c[fM > fN ? fM : fN];
2433  double d[fM > fN ? fM : fN];
2434 
2435  for (int i = 0; i < n; i++) {
2436  double dift = abs(x-xa[i]);
2437  if (dift < dif) {
2438  ns = i;
2439  dif = dift;
2440  }
2441  c[i] = yal[i];
2442  d[i] = yal[i];
2443  }
2444  y = yal[ns];
2445  ns--;
2446  for (int m = 1; m < n; m++) {
2447  for (int i = 0; i < n-m; i++) {
2448  double ho = xa[i]-x;
2449  double hp = xa[i+m]-x;
2450  double w = c[i+1]-d[i];
2451  double den = ho-hp;
2452  if (den == 0) {
2453  cout << "NNPDF::polint, failure" << endl;
2454  return;
2455  }
2456  den = w/den;
2457  d[i] = hp*den;
2458  c[i] = ho*den;
2459  }
2460  if (2*(ns+1) < n-m) dy = c[ns+1];
2461  else {
2462  dy = d[ns];
2463  ns--;
2464  }
2465  y+=dy;
2466  }
2467 }
2468 
2469 //--------------------------------------------------------------------------
2470 
2471 // 2D polynomial interpolation.
2472 
2473 void NNPDF::polin2(double x1al[], double x2al[], double yal[][fN],
2474  double x1, double x2, double& y, double& dy) {
2475 
2476  double yntmp[fN];
2477  double ymtmp[fM];
2478 
2479  for (int j = 0; j < fM; j++) {
2480  for (int k = 0; k < fN; k++) yntmp[k] = yal[j][k];
2481  polint(x2al,yntmp,fN,x2,ymtmp[j],dy);
2482  }
2483  polint(x1al,ymtmp,fM,x1,y,dy);
2484 
2485 }
2486 
2487 //==========================================================================
2488 
2489 } // end namespace Pythia8
void ae(int tracks=-1, int hits=-1)
This function is to search for the next non-empty event and draw it by looping over StBFChain (readin...
Definition: Ed.C:102