StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
VinciaWeights.cc
1 // VinciaWeights.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2020 Peter Skands, 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 // Function definitions (not found in the header) for the VinciaWeights class.
7 
8 #include "Pythia8/VinciaWeights.h"
9 
10 namespace Pythia8 {
11 
12 //==========================================================================
13 
14 // The VinciaWeights class.
15 
16 //--------------------------------------------------------------------------
17 
18 // Constants.
19 
20 const double VinciaWeights::TINYANT = 1.0e-10;
21 const double VinciaWeights::PACCEPTVARMAX = 0.99;
22 const double VinciaWeights::MINVARWEIGHT = 0.01;
23 
24 //--------------------------------------------------------------------------
25 
26 // Initilize pointers.
27 
28 bool VinciaWeights::initPtr(Info* infoPtrIn,
29  VinciaCommon* vinComPtrIn) {
30  infoPtr = infoPtrIn;
31  settingsPtr = infoPtr->settingsPtr;
32  vinComPtr = vinComPtrIn;
33  isInitPtr = true;
34  return true;
35 }
36 
37 //--------------------------------------------------------------------------
38 
39 // Initialize.
40 
41 void VinciaWeights::init() {
42 
43  // Check initPtr.
44  if (!isInitPtr) {
45  printOut("VinciaWeights::init","Error! pointers not initialized");
46  return;
47  }
48  verbose = settingsPtr->mode("Vincia:verbose");
49  // TODO: uncertainty bands are disabled in this version of VINCIA.
50  uncertaintyBands = false;
51  varLabels.resize(0);
52  nWeightsSav = (uncertaintyBands ? 1+varLabels.size() : 1);
53 
54  // List of all keywords.
55  allKeywords.clear(); allKeywords.resize(0);
56  string ffKeys[5] = { ":", ":qqemit:", ":qgemit:", ":ggemit:", ":gxsplit:" };
57  string ifKeys[8] = { ":", ":qqemit:", ":gqemit:", ":ggemit:", ":ggemit:",
58  ":qxsplit:", ":gxconv:", ":xgsplit:" };
59  string iiKeys[6] = { ":", ":qqemit:", ":gqemit:", ":ggemit:", ":qxsplit:",
60  ":gxconv:" };
61  for (int i = 0; i < 5; i++) allKeywords.push_back("ff"+ffKeys[i]+"murfac");
62  for (int i = 0; i < 5; i++) allKeywords.push_back("ff"+ffKeys[i]+"cns");
63  for (int i = 0; i < 8; i++) allKeywords.push_back("if"+ifKeys[i]+"murfac");
64  for (int i = 0; i < 8; i++) allKeywords.push_back("if"+ifKeys[i]+"cns");
65  for (int i = 0; i < 6; i++) allKeywords.push_back("ii"+iiKeys[i]+"murfac");
66  for (int i = 0; i < 6; i++) allKeywords.push_back("ii"+iiKeys[i]+"cns");
67 
68  // Convert iAntPhys to keyword.
69  iAntToKeyFSR.clear();
70  iAntToKeyFSR[iQQemitFF] = "qqemit";
71  iAntToKeyFSR[iQGemitFF] = "qgemit";
72  iAntToKeyFSR[iGQemitFF] = "qgemit";
73  iAntToKeyFSR[iGGemitFF] = "ggemit";
74  iAntToKeyFSR[iGXsplitFF] = "gxsplit";
75  iAntToKeyISR.clear();
76  iAntToKeyISR[iQQemitII] = "qqemit";
77  iAntToKeyISR[iGQemitII] = "gqemit";
78  iAntToKeyISR[iGGemitII] = "ggemit";
79  iAntToKeyISR[iQXsplitII] = "qxsplit";
80  iAntToKeyISR[iGXconvII] = "gxconv";
81  iAntToKeyISR[iQQemitIF] = "qqemit";
82  iAntToKeyISR[iQGemitIF] = "qgemit";
83  iAntToKeyISR[iGQemitIF] = "gqemit";
84  iAntToKeyISR[iGGemitIF] = "ggemit";
85  iAntToKeyISR[iQXsplitIF] = "qxsplit";
86  iAntToKeyISR[iGXconvIF] = "gxconv";
87  iAntToKeyISR[iXGsplitIF] = "xgsplit";
88 
89  // Clean up the names of requested variations.
90  for (int i = 0; i < (int)varLabels.size(); i++) {
91  int strBegin = varLabels[i].find_first_not_of(" ");
92  if ((i == 0) && (varLabels[i].find("{") != string::npos)) strBegin += 1;
93  int strEnd = varLabels[i].find_last_not_of(" ");
94  if ((i == (int)varLabels.size()-1) && (varLabels[i].find("}") !=
95  string::npos)) strEnd -= 1;
96  int strRange = strEnd - strBegin + 1;
97  varLabels[i] = toLower(varLabels[i].substr(strBegin, strRange));
98  }
99 
100  // Parse names of requested variations and check for keywords.
101  varKeys.clear(); varKeys.resize(varLabels.size());
102  varVals.clear(); varVals.resize(varLabels.size());
103  for (int i = 0; i < (int)varLabels.size(); i++) {
104  varKeys[i].clear(); varKeys[i].resize(0);
105  varVals[i].clear(); varVals[i].resize(0);
106  string var = varLabels[i];
107  int iEndName = var.find(" ", 0);
108  string varName = var.substr(0, iEndName);
109  string left = var.substr(iEndName, var.length());
110  left = left.substr(left.find_first_not_of(" "), left.length());
111  varLabels[i] = varName;
112  while (left.length() > 1) {
113  int iEnd = left.find("=", 0);
114  int iAlt = left.find(" ", 0);
115  if ( (iAlt < iEnd) && (iAlt > 0) ) iEnd = iAlt;
116  string key = left.substr(0, iEnd);
117  if (1+key.find_last_not_of(" ") < key.length())
118  key = key.substr(0, 1+key.find_last_not_of(" "));
119  varKeys[i].push_back(key);
120  string val = left.substr(iEnd+1, left.length());
121  val = val.substr(val.find_first_not_of(" "), val.length());
122  val = val.substr(0, val.find_first_of(" "));
123  varVals[i].push_back(atof(val.c_str()));
124  left = left.substr(iEnd+1, left.length());
125  if (left.find_first_of(" ") >= left.length()) break;
126  left = left.substr(left.find_first_of(" "), left.length());
127  if (left.find_first_not_of(" ") >= left.length()) break;
128  left = left.substr(left.find_first_not_of(" "), left.length());
129  }
130  }
131 
132  if (uncertaintyBands && (verbose >= 4)) {
133  printOut("VinciaWeights", "List of variations, keywords and values:");
134  for (int i = 0; i < (int)varLabels.size(); i++) {
135  cout << " " << varLabels[i] << " : ";
136  for (int j=0; j<(int)varVals[i].size(); j++) {
137  cout << " " << varKeys[i][j] << " -> " << varVals[i][j];
138  if (j < (int)varVals[i].size() - 1) cout << ",";
139  }
140  cout << endl;
141  }
142  }
143 
144  // Safety check for non-sensible input.
145  if (uncertaintyBands)
146  for (int i = 0; i < (int)varKeys.size(); i++)
147  for (int j = 0; j < (int)varKeys[i].size(); j++) {
148  // Check input keywords against known ones.
149  bool foundValidKey = false;
150  for (int k = 0; k < (int)allKeywords.size(); k++)
151  if (allKeywords[k] == varKeys[i][j]) {
152  foundValidKey = true;
153  break;
154  }
155  if (!foundValidKey)
156  printOut("VinciaWeights", "Error! Unknown key " +
157  varKeys[i][j] + " found, please check!");
158  }
159 
160  nReportWeight = 5;
161  nReportedWeight = 0;
162 
163  // Resize weight arrays to the relevant number of elements.
164  weightsSav.resize(nWeightsSav);
165  weightsOld.resize(nWeightsSav);
166  weightsMax.resize(nWeightsSav);
167  weightsMin.resize(nWeightsSav);
168  weightSum.resize(nWeightsSav);
169  weightSum2.resize(nWeightsSav);
170  contribSum.resize(nWeightsSav);
171  contribSum2.resize(nWeightsSav);
172 
173  // Initialize counters and flags.
174  nTotWeights = 0;
175  nNonunityWeight = 0;
176  nNegativeWeight = 0;
177  nNonunityInitialWeight = 0;
178  nNegativeInitialWeight = 0;
179  nNonunityWeightNow = 0;
180  nNegativeWeightNow = 0;
181  nNonunityInitialWeightNow = 0;
182  nNegativeInitialWeightNow = 0;
183  didReweight = false;
184  firstCall = false;
185 
186  // Initialize weights to 0 (or 1 respectively).
187  for (int iWeight=0; iWeight<nWeightsSav; iWeight++) {
188  weightsSav[iWeight] = 1.0;
189  weightsOld[iWeight] = 0.0;
190  weightsMax[iWeight] = 0.0;
191  weightsMin[iWeight] = 1.0e10;
192  weightSum[iWeight] = 0.0;
193  weightSum2[iWeight] = 0.0;
194  contribSum[iWeight] = 0.0;
195  contribSum2[iWeight] = 0.0;
196  }
197 
198 }
199 
200 //--------------------------------------------------------------------------
201 
202 // Reset the weights, to be called at the beginning of each event.
203 
204 void VinciaWeights::resetWeights(int nAccepted) {
205 
206  for (int iWeight = 0; iWeight < nWeightsSav; iWeight++) {
207  weightsSav[iWeight] = 1.0;
208  weightsOld[iWeight] = 0.0;
209  }
210 
211  // Next doWeighting call will be the first one.
212  firstCall = true;
213 
214  // No reweighting so far.
215  didReweight = false;
216 
217  // Check if Pythia/Vincia vetoed event, restore counters.
218  if (nAccepted < nTotWeights) {
219  nTotWeights--;
220  nNonunityWeight -= nNonunityWeightNow;
221  nNegativeWeight -= nNegativeWeightNow;
222  nNonunityInitialWeight -= nNonunityInitialWeightNow;
223  nNegativeInitialWeight -= nNegativeInitialWeightNow;
224 
225  for (int iWeight = 0; iWeight < nWeightsSav; iWeight++) {
226  weightSum[iWeight] -= contribSum[iWeight];
227  weightSum2[iWeight] -= contribSum2[iWeight];
228  }
229  }
230  nNonunityWeightNow = 0;
231  nNegativeWeightNow = 0;
232  nNonunityInitialWeightNow = 0;
233  nNegativeInitialWeightNow = 0;
234 
235  for (int iWeight = 0; iWeight<nWeightsSav; iWeight++) {
236  contribSum[iWeight] = 0.0;
237  contribSum2[iWeight] = 0.0;
238  }
239 
240 }
241 
242 //--------------------------------------------------------------------------
243 
244 // Scaling functions.
245 
246 void VinciaWeights::scaleWeightAll(double scaleFacIn) {
247  for (int iWeight=0; iWeight<nWeightsSav; iWeight++)
248  weightsSav[iWeight] *= scaleFacIn;
249 }
250 
251 void VinciaWeights::scaleWeight(double scaleFacIn, int iWeightIn) {
252  if (existsWeight(iWeightIn)) weightsSav[iWeightIn] *= scaleFacIn;
253 }
254 
255 void VinciaWeights::scaleWeightVar(vector<double> pAccept, bool accept,
256  bool isHard) {
257  if (!uncertaintyBands) return;
258  if (nWeightsSav <= 1) return;
259  // Variations only pertain to hard process and resonance decays.
260  if (!isHard) return;
261  if (accept) scaleWeightVarAccept(pAccept);
262  else scaleWeightVarReject(pAccept);
263 }
264 
265 void VinciaWeights::scaleWeightVarAccept(vector<double> pAccept) {
266  for (int iWeight = 1; iWeight<nWeightsSav; iWeight++) {
267  double pAcceptVar = pAccept[iWeight];
268  if (pAcceptVar > PACCEPTVARMAX) pAcceptVar = PACCEPTVARMAX;
269  scaleWeight( pAcceptVar/pAccept[0], iWeight );
270  }
271 }
272 
273 void VinciaWeights::scaleWeightVarReject(vector<double> pAccept) {
274  for (int iWeight = 1; iWeight<nWeightsSav; iWeight++) {
275  double pAcceptVar = pAccept[iWeight];
276  if (pAcceptVar > PACCEPTVARMAX) pAcceptVar = PACCEPTVARMAX;
277  double reWeight = (1.0-pAcceptVar)/(1.0-pAccept[0]);
278  if (reWeight < MINVARWEIGHT) reWeight = MINVARWEIGHT;
279  scaleWeight( reWeight, iWeight );
280  }
281 }
282 
283 void VinciaWeights::scaleWeightEnhanceAccept(double enhanceFac) {
284  if (enhanceFac == 1.0) return;
285  else scaleWeightAll(1./enhanceFac);
286 }
287 
288 void VinciaWeights::scaleWeightEnhanceReject(double pAcceptUnenhanced,
289  double enhanceFac) {
290  if (enhanceFac == 1.0) return;
291  if (enhanceFac > 1.0) {
292  double rRej =
293  (1. - pAcceptUnenhanced/enhanceFac)/(1. - pAcceptUnenhanced);
294  scaleWeightAll(rRej);
295  } else {
296  double rRej =
297  (1. - pAcceptUnenhanced)/(1. - enhanceFac*pAcceptUnenhanced);
298  scaleWeightAll(rRej);
299  }
300 }
301 
302 //--------------------------------------------------------------------------
303 
304 // Helper function for keyword evaluation
305 
306 int VinciaWeights::doVarNow(string keyIn, int iAntPhys, string type) {
307 
308  // Check variation for all branching types.
309  string asKey = ":murfac", nsKey = ":cns";
310  if (type + asKey == keyIn) return 1;
311  if (type + nsKey == keyIn) return 2;
312  // Check variation for specific branching type.
313  map<int,string> keyCvt = (type == "ff" ? iAntToKeyFSR : iAntToKeyISR);
314  if (type + ":" + keyCvt[iAntPhys] + asKey == keyIn) return 1;
315  if (type + ":" + keyCvt[iAntPhys] + nsKey == keyIn) return 2;
316  return -1;
317 
318 }
319 
320 //--------------------------------------------------------------------------
321 
322 // Main function to perform the weighting.
323 
324 void VinciaWeights::doWeighting() {
325 
326  // Check for non-unity and negative initial weights.
327  double inW = 1.0;
328  if (firstCall) {
329  inW = infoPtr->weight();
330  bool report = false;
331  bool isLast = false;
332  if ( (abs(inW-1.0) > TINY) || (inW < 0.0) ) {
333  nReportedWeight++;
334  if (nReportedWeight <= nReportWeight) {
335  report = true;
336  if (nReportedWeight == nReportWeight) isLast = true;
337  }
338  string printMessage = "Nonunity initial weight occurred, w = ";
339  // Updated counters.
340  if (inW < 0.0) {
341  printMessage = "Negative initial weight occurred, w = ";
342  nNegativeInitialWeight++;
343  nNegativeInitialWeightNow++;
344  } else {
345  nNonunityInitialWeight++;
346  nNonunityInitialWeightNow++;
347  }
348  // Always report in debugging mode.
349  if ((report && verbose >= 3) || verbose >= 4)
350  printOut("VinciaWeights", printMessage + num2str(inW) + (isLast ?
351  ": further output suppressed" : ""));
352  }
353  }
354 
355  // Add weight correction to cumulative sum (!= w0 for systems in series).
356  // Take into account Pythia's weight (only != 1 for first time in event).
357  double w0 = inW*weightsSav[0];
358  double wMC0 = weightsSav[0];
359  double wOld = weightsOld[0];
360  weightSum[0] += (w0 - wOld);
361  weightSum2[0] += (pow2(w0) - pow2(wOld));
362  // Contribution of current event
363  contribSum[0] += (w0 - wOld);
364  contribSum2[0] += (pow2(w0) - pow2(wOld));
365 
366  if (firstCall) {
367  firstCall = false;
368  // Add one to number of events.
369  nTotWeights++;
370  }
371 
372  // Check for non-unity and negative weights due to MC violations.
373  bool foundWeightToReport = false;
374  if (abs(wMC0-1.0) > TINY) {
375  // Only check if wOld = 0 or if weight changed.
376  if ( wOld < TINY || (abs(wOld) > TINY && (abs(wOld-w0) > TINY)) ) {
377  didReweight = true;
378  foundWeightToReport = true;
379  // Update counters.
380  nNonunityWeight++;
381  nNonunityWeightNow++;
382  }
383  }
384  if (wMC0 < 0.0 && wOld >= 0.0) {
385  didReweight = true;
386  foundWeightToReport = true;
387  // Update counters.
388  nNegativeWeight++;
389  nNegativeWeightNow++;
390  }
391  bool report = false;
392  bool isLast = false;
393  if ( foundWeightToReport && (nReportedWeight <= nReportWeight) ) {
394  report = true;
395  if (nReportedWeight == nReportWeight) isLast = true;
396  }
397  // Always report in debugging mode.
398  if ((report && verbose >= 3) || verbose >= 4) {
399  string printMessage = (wMC0 > 0.0 ? "Nonunity MC reweight occurred, w = "
400  : "Negative MC reweight occurred, w = ");
401  printOut("VinciaWeights", printMessage + num2str(w0) + (isLast ?
402  ": further output suppressed" : ""));
403  }
404 
405  // Keep track of minimum and maximum weights.
406  weightsMax[0] = max(weightsMax[0], w0);
407  weightsMin[0] = min(weightsMin[0], w0);
408 
409  // Update the old weight.
410  weightsOld[0] = w0;
411 
412  // Save uncertainty band weights.
413  if (nWeightsSav > 1) {
414  for (int iWeight = 1; iWeight < nWeightsSav; iWeight++) {
415  double wVar = inW*weightsSav[iWeight];
416  double wVarOld = weightsOld[iWeight];
417  // Add weight correction to cumulative sum.
418  weightSum[iWeight] += (wVar - wVarOld);
419  weightSum2[iWeight] += (pow2(wVar) - pow2(wVarOld));
420  // Contribution of current event.
421  contribSum[iWeight] += (wVar - wVarOld);
422  contribSum2[iWeight] += (pow2(wVar) - pow2(wVarOld));
423  // Keep track of minimum and maximum weights.
424  weightsMax[iWeight] = max(weightsMax[iWeight], wVar);
425  weightsMin[iWeight] = min(weightsMin[iWeight], wVar);
426  // Update old weight.
427  weightsOld[iWeight] = wVar;
428  }
429  }
430 
431 }
432 
433 //==========================================================================
434 
435 
436 } // end namespace Pythia8