Belle II Software  release-08-00-10
BabayagaNLO.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <generators/babayaganlo/BabayagaNLO.h>
10 #include <framework/gearbox/Unit.h>
11 #include <framework/logging/Logger.h>
12 #include <framework/dataobjects/EventMetaData.h>
13 #include <framework/dataobjects/EventExtraInfo.h>
14 
15 #include <TDatabasePDG.h>
16 #include <TRandom3.h>
17 
18 #include <generators/utilities/InitialParticleGeneration.h>
19 
20 using namespace std;
21 using namespace Belle2;
22 
23 extern "C" {
24 
25  extern struct {
26  double bweight;
27  double bp1[4];
28  double bq1[4];
29  double bp2[4];
30  double bq2[4];
31  double bphot[4][100];
32  int bnphot;
33  } momset_;
34 
35  extern struct {
36  double bprescale;
37  } prescale_;
38 
39  //results for cross section and photon multiplicity
40  extern struct {
41  double rescross;
42  double rescrosserr;
43  double rescrossphot[40];
44  double rescrossphoterr[40];
45  double rescrossphotfrac[40];
46  double resnphmax;
47  } bresults_;
48 
49  //results and statistics for hit/miss
50  extern struct {
51  double hnmcross;
52  double hnmcrosserr;
53  double hnmeff;
54  double hnmsdifmax;
55  double hnmfmax;
56  double hnmmaxtriallimit;
57  double hnmmaxtrial;
58  } bhitnmiss_;
59 
60  //bias for hit/miss
61  extern struct {
62  double biashit;
63  double biashitpmiss;
64  double biasneghit;
65  double biasneghitmiss;
66  double sezover;
67  double errsezover;
68  double sezneg;
69  double errsezneg;
70  double nover;
71  double nneg;
72  } bbias_;
73 
74  //monitoring
75  extern struct {
76  double monsdif;
77  } bmonitoring_;
78 
80  double babayaganlo_rndm_(int*)
81  {
82  double r = gRandom->Rndm();
83  return r;
84  }
85 
87  double babayaganlo_getrandomcmsenergy_()
88  {
89  B2FATAL("babayaganlo_getrandomcmsenergy() is not implmented");
90  }
91 
93 // void main_belle2_(int* mode, double* xpar, int* npar, double *ecm);
94  void main_belle2_(int* mode, double* ecm, double* xpar, int* npar);
95 
97  void babayaga_setvpolnsk_(const char* vpolnskfilename, size_t* length);
98 
100  void babayaganlo_warning_overweight_(const double* weight, const double* max)
101  {
102  B2WARNING("Babayaga.NLO: Maximum weight " << *max << " to small, increase fmax to at least " << *weight);
103  }
104 
106  void babayaganlo_error_rejection_(const double* ratio)
107  {
108  B2ERROR("Babayaga.NLO: Event rejected! Ratio of cross section error increase too large: " << *ratio);
109  }
110 
112  void babayaganlo_error_negative_(const double* weight)
113  {
114  B2ERROR("Babayaga.NLO: Event has negative weight: " << *weight);
115  }
116 
118  void babayaganlo_result_nominalcmsenergy_(const double* energy)
119  {
120  B2RESULT("Babayaga.NLO: Nominal CMS energy (GeV): " << *energy);
121  }
122 
123  void babayaganlo_result_weightedxsec_(const double* xsec, const double* xsecerr)
124  {
125  B2RESULT("Babayaga.NLO: Weighted cross section (nb): " << *xsec << " +/- " << *xsecerr);
126  }
127 
128  void babayaganlo_result_unweightedxsec_(const double* xsec, const double* xsecerr)
129  {
130  B2RESULT("Babayaga.NLO: Unweighted cross section (nb): " << *xsec << " +/- " << *xsecerr);
131  }
132 
133  void babayaganlo_result_unweightedxsec_biascorrected_(const double* xsec, const double* xsecerr)
134  {
135  B2RESULT("Babayaga.NLO: Unweighted cross section, bias corrected (nb): " << *xsec << " +/- " << *xsecerr);
136  }
137 
138  void babayaganlo_result_unweightedxsec_overweight_(const double* xsec, const double* xsecerr)
139  {
140  B2RESULT("Babayaga.NLO: Unweighted cross section overweight (nb): " << *xsec << " +/- " << *xsecerr);
141  }
142 
143  void babayaganlo_result_unweightedxsec_underweight_(const double* xsec, const double* xsecerr)
144  {
145  B2RESULT("Babayaga.NLO: Unweighted cross section underweight (nb): " << -*xsec << " +/- " << *xsecerr);
146  }
147 
148  void babayaganlo_result_hitormisseff_(const double* eff)
149  {
150  B2RESULT("Babayaga.NLO: Hit or miss efficiency: " << *eff * 100. << " % ");
151  }
152 
153  void babayaganlo_result_nover_(const int* nover)
154  {
155  B2RESULT("Babayaga.NLO: Points with w > fmax (bias): " << *nover);
156  }
157 
158  void babayaganlo_result_biashit_(const double* biashit)
159  {
160  B2RESULT("Babayaga.NLO: Bias/hit: " << *biashit * 100. << " % ");
161  }
162 
163  void babayaganlo_result_biashitpmiss_(const double* biashitpmiss)
164  {
165  B2RESULT("Babayaga.NLO: Bias/(hit+missed): " << *biashitpmiss * 100. << " % ");
166  }
167 
168  void babayaganlo_result_nneg_(const int* nneg)
169  {
170  B2RESULT("Babayaga.NLO: Points with w > fmax (bias): " << *nneg);
171  }
172 
173  void babayaganlo_result_biasneghit_(const double* biasneghit)
174  {
175  B2RESULT("Babayaga.NLO: Neg. bias/hit: " << *biasneghit * 100. << " % ");
176  }
177 
178  void babayaganlo_result_biasneghitmiss_(const double* biasneghitmiss)
179  {
180  B2RESULT("Babayaga.NLO: Neg. bias/(hit+missed): " << *biasneghitmiss * 100. << " % ");
181  }
182 
183  void babayaganlo_result_maxweight_(const double* sdifmax, const double* fmax)
184  {
185  B2RESULT("Babayaga.NLO: Maximum weight (sdifmax): " << *sdifmax << ", user maximum weight(fmax): " << *fmax);
186  }
187 
188  void babayaganlo_result_vpmin_(const double* xsec, const double* xsecerr, const double* frac)
189  {
190  B2RESULT("Babayaga.NLO: VP Uncertainty, minimum (nb): " << *xsec << " +/- " << *xsecerr << " (" << *frac << " %)");
191  }
192 
193  void babayaganlo_result_vpcentral_(const double* xsec, const double* xsecerr)
194  {
195  B2RESULT("Babayaga.NLO: VP Uncertainty, central (nb): " << *xsec << " +/- " << *xsecerr);
196  }
197 
198  void babayaganlo_result_vpmax_(const double* xsec, const double* xsecerr, const double* frac)
199  {
200  B2RESULT("Babayaga.NLO: VP Uncertainty, maximum (nb): " << *xsec << " +/- " << *xsecerr << " ( " << *frac << " %)");
201  }
202 
203  void babayaganlo_finishedmaxsearch_(const double* fmax)
204  {
205  B2INFO("Babayaga.NLO: Finished maximum search: " << *fmax << ", starting now unweighted generation");
206  }
207 
208  void babayaganlo_fatal_usercuts_()
209  {
210  B2FATAL("Babayaga.NLO: UserMode is selected but wrong user cuts are provided!");
211  }
212 
213  void babayaganlo_fatal_usercutsfs_()
214  {
215  B2FATAL("Babayaga.NLO: UserMode is only possible for ee final states!");
216  }
217 
218  void babayaganlo_fatal_usercutsprescale_()
219  {
220  B2FATAL("Babayaga.NLO: Prescale value must be larger than 0 (zero), hint: ~100 is reasonable!");
221  }
222 
223  void babayaganlo_fatal_weightedprescale_()
224  {
225  B2FATAL("Babayaga.NLO: Generator prescale is not allowed with usermode = weighted");
226  }
227 
228  void babayaganlo_result_weightsum_(const double* wsum)
229  {
230  B2RESULT("Babayaga.NLO: Sum of weights: " << *wsum);
231  }
232 
233  void babayaganlo_result_intlum_(const double* lum, const double* lumerr)
234  {
235  B2RESULT("Babayaga.NLO: Luminosity equivalent (using calc. xsec) (fb-1): " << *lum << " +/- " << *lumerr);
236  }
237 
238  void babayaganlo_warning_prescaleweight_(const double* weight)
239  {
240  B2WARNING("Babayaga.NLO: Prescale of less than one, increase prescale safety margin " << *weight);
241  }
242 
243  void babayaganlo_error_isnan1_(const double* phsp, const double* w)
244  {
245  B2ERROR("Babayaga.NLO: phsp (" << *phsp << ") or w (" << *w << ") are NAN, skipping event (nan1 type)");
246  }
247 
248  void babayaganlo_error_isnan2_(const double* sdif)
249  {
250  B2ERROR("Babayaga.NLO: sdif (" << *sdif << ") is NAN, skipping event (nan2 type)");
251  }
252 
253 
254 
255 }
256 
257 BabayagaNLO::BabayagaNLO()
258 {
259  for (int i = 0; i < 100; ++i) {
260  m_npar[i] = 0;
261  m_xpar[i] = 0.0;
262  }
263 
264  m_sDif = 0.;
265 
266  setDefaultSettings();
267 }
268 
269 BabayagaNLO::~BabayagaNLO()
270 {
271 
272 }
273 
274 void BabayagaNLO::setDefaultSettings()
275 {
276 // m_cmsEnergy = -1.;
277  m_cmsEnergyNominal = -1.;
278 
279  m_applyBoost = true;
280 
281  m_finalState = "ee";
282  m_vacPol = "hlmnt";
283  m_order = "exp";
284  m_model = "matched";
285  m_mode = "unweighted";
286  m_userMode = "NONE";
287 
288  m_pi = 3.1415926535897932384626433832795029;
289  m_conversionFactor = 0.389379660e6;
290  m_alphaQED0 = 1.0 / 137.0359895;
291  m_massElectron = 0.51099906 * Unit::MeV;
292  m_massMuon = 105.65836900 * Unit::MeV;
293  m_massW = 80.385 * Unit::GeV;
294  m_massZ = 91.1882 * Unit::GeV;
295  m_widthZ = 2.4952 * Unit::GeV;
296  m_eMin = 0.1 * Unit::GeV;
297  m_epsilon = 5.e-7;
298  m_maxAcollinearity = 180.0;// * Unit::Deg;
299 
300  m_ScatteringAngleRange = make_pair(15.0, 165.0); //in [deg]
301  m_ScatteringAngleRangePhoton = make_pair(15.0, 165.0); //in [deg] (unused in original babayaga)
302 
303  m_nPhot = -1;
304  m_nSearchMax = 50000;
305  m_fMax = -1.;
306  m_EnergySpread = 5e-3;
307  m_VPUncertainty = false;
308  m_eemin = 0.0;
309  m_temin = 0.0;
310  m_egmin = 0.0;
311  m_tgmin = 0.0;
312  m_eeveto = 0.0;
313  m_teveto = 0.0;
314  m_egveto = 0.0;
315  m_tgveto = 0.0;
316  m_maxprescale = 1.0;
317 }
318 
319 void BabayagaNLO::initExtraInfo()
320 {
321  StoreObjPtr<EventExtraInfo> extrainfo;
322  extrainfo.registerInDataStore();
323 }
324 
325 void BabayagaNLO::init()
326 {
327  applySettings();
328 }
329 
330 
331 void BabayagaNLO::generateEvent(MCParticleGraph& mcGraph, double ecm, ROOT::Math::XYZVector vertex,
332  ROOT::Math::LorentzRotation boost)
333 {
334  //Generate event
335  int mode = 1;
336  main_belle2_(&mode, &ecm, m_xpar, m_npar);
337 
338  //Store the initial particles as initial (non-virtual) particles into the MCParticleGraph
339  storeParticle(mcGraph, momset_.bq1, 11, vertex, boost, false, true, false);
340  storeParticle(mcGraph, momset_.bp1, -11, vertex, boost, false, true, false);
341 
342  //Store the final state fermions or photons (for 'gg') as real particle into the MCParticleGraph
343  int pdg = 11;
344  int antipdg = -11;
345 
346  if (m_finalState == "gg") {
347  pdg = 22;
348  antipdg = 22;
349  } else if (m_finalState == "mm") {
350  pdg = 13;
351  antipdg = -13;
352  }
353 
354  storeParticle(mcGraph, momset_.bq2, pdg, vertex, boost, false, false, false);
355  storeParticle(mcGraph, momset_.bp2, antipdg, vertex, boost, false, false, false);
356 
357  //Store the real ISR and FSR photons into the MCParticleGraph
358  for (int iPhot = 0; iPhot < momset_.bnphot; ++iPhot) {
359  double photMom[4] = {momset_.bphot[0][iPhot], momset_.bphot[1][iPhot], momset_.bphot[2][iPhot], momset_.bphot[3][iPhot]};
360  storeParticle(mcGraph, photMom, 22, vertex, boost, false, false, true);
361  }
362 
363  //set event weight
364  StoreObjPtr<EventMetaData> eventMetaDataPtr("EventMetaData", DataStore::c_Event);
365  eventMetaDataPtr->setGeneratedWeight(momset_.bweight);
366 
367  //set event prescale
368  StoreObjPtr<EventExtraInfo> eventExtraInfo;
369  if (not eventExtraInfo.isValid())
370  eventExtraInfo.create();
371  if (eventExtraInfo->hasExtraInfo("GeneratedPrescale")) {
372  B2WARNING("EventExtraInfo with given name is already set! I won't set it again!");
373  } else {
374  float targetValue = prescale_.bprescale;
375  eventExtraInfo->addExtraInfo("GeneratedPrescale", targetValue);
376  }
377 
378 }
379 
380 
381 void BabayagaNLO::term()
382 {
383 
384  B2RESULT("Babayaga.NLO: Final state: " << m_finalState);
385  B2RESULT("Babayaga.NLO: Mode: " << m_mode);
386  B2RESULT("Babayaga.NLO: Order: " << m_order);
387  B2RESULT("Babayaga.NLO: Model: " << m_model);
388  B2RESULT("Babayaga.NLO: Vac. pol. (VP): " << m_vacPol);
389  B2RESULT("Babayaga.NLO: Usercuts: " << m_userMode);
390 
391  // all other results are displayed from fortran using a callback to C extern logging
392 
393  int mode = 2;
394  double ecm = -1.;
395  main_belle2_(&mode, &ecm, m_xpar, m_npar);
396 
397 }
398 
399 //=========================================================================
400 // Protected methods
401 //=========================================================================
402 
403 void BabayagaNLO::applySettings()
404 {
405  //--------------------
406  // Integer parameters
407  //--------------------
408  m_npar[0] = m_nPhot;
409  m_npar[1] = m_nSearchMax;
410  if (m_VPUncertainty) m_npar[5] = 1;
411  else m_npar[5] = 0;
412 
413  //--------------------
414  // Double parameters
415  //--------------------
416  m_xpar[0] = m_cmsEnergyNominal;
417  m_xpar[1] = m_pi;
418  m_xpar[2] = m_conversionFactor;
419  m_xpar[3] = m_alphaQED0;
420  m_xpar[4] = m_massElectron;
421  m_xpar[5] = m_massMuon;
422  m_xpar[6] = m_massW;
423  m_xpar[7] = m_massZ;
424  m_xpar[8] = m_widthZ;
425  m_xpar[9] = m_eMin;
426  m_xpar[10] = m_maxAcollinearity;
427  m_xpar[11] = m_epsilon;
428  m_xpar[20] = m_ScatteringAngleRange.first;
429  m_xpar[21] = m_ScatteringAngleRange.second;
430  m_xpar[30] = m_fMax;
431  m_xpar[40] = m_EnergySpread; // only for some internal checks, not the actual smaering!
432 
433  //user cuts
434  m_xpar[50] = m_eemin;
435  m_xpar[51] = m_temin;
436  m_xpar[52] = m_egmin;
437  m_xpar[53] = m_tgmin;
438  m_xpar[54] = m_eeveto;
439  m_xpar[55] = m_teveto;
440  m_xpar[56] = m_egveto;
441  m_xpar[57] = m_tgveto;
442  m_xpar[58] = m_maxprescale;
443 
444  //--------------------
445  // string parameters, wrapped to integers
446  //--------------------
447  if (m_finalState == "ee") m_npar[20] = 1;
448  else if (m_finalState == "gg") m_npar[20] = 2;
449  else if (m_finalState == "mm") m_npar[20] = 3;
450  else B2FATAL("Invalid final state: " << m_finalState);
451 
452  if (m_model == "matched") m_npar[21] = 1;
453  else if (m_model == "ps") m_npar[21] = 2;
454  else B2FATAL("Invalid matching model: " << m_model);
455 
456  if (m_order == "born") m_npar[22] = 1;
457  else if (m_order == "alpha") m_npar[22] = 2;
458  else if (m_order == "exp") m_npar[22] = 3;
459  else B2FATAL("Invalid QED order: " << m_order);
460 
461  if (m_vacPol == "off") m_npar[23] = 1;
462  else if (m_vacPol == "hadr5") m_npar[23] = 2;
463  else if (m_vacPol == "hlmnt") m_npar[23] = 3;
464  else B2FATAL("Invalid vacuum polarization code: " << m_vacPol);
465 
466  if (m_mode == "unweighted" || m_mode == "uw") m_npar[24] = 1;
467  else if (m_mode == "weighted" || m_mode == "w") m_npar[24] = 2;
468  else B2FATAL("Invalid mode: " << m_mode);
469 
470  if (m_userMode == "NONE") m_npar[25] = 1;
471  else if (m_userMode == "GAMMA") m_npar[25] = 2;
472  else if (m_userMode == "EGAMMA") m_npar[25] = 3;
473  else if (m_userMode == "ETRON") m_npar[25] = 4;
474  else if (m_userMode == "PRESCALE") m_npar[25] = 5;
475  else B2FATAL("Invalid user mode: " << m_userMode);
476 
477  // set the data file for the novosibirsk routine (not supported yet, but needs to be set)
478  size_t fileLength = m_NSKDataFile.size();
479  babayaga_setvpolnsk_(m_NSKDataFile.c_str(), &fileLength);
480 
481  //use mode to control init/generation/finalize in FORTRAN code
482  int mode = -1;
483  double ecm = -1.;
484  main_belle2_(&mode, &ecm, m_xpar, m_npar);
485 }
486 
487 
488 void BabayagaNLO::storeParticle(MCParticleGraph& mcGraph, const double* mom, int pdg, ROOT::Math::XYZVector vertex,
489  ROOT::Math::LorentzRotation boost, bool isVirtual, bool isInitial, bool isISRFSR)
490 {
491 
492 // Create particle
494  if (isVirtual) {
495  part.setStatus(MCParticle::c_IsVirtual);
496  } else if (isInitial) {
497  part.setStatus(MCParticle::c_Initial);
498  }
499 
500  // all particle of a generator are primary
501  part.addStatus(MCParticle::c_PrimaryParticle);
502 
503  // all particles produced by BABAYAGA are stable
504  part.addStatus(MCParticle::c_StableInGenerator);
505 
506  // add ISR/FSR flags to all photons that are not the primary gg pair
507  if (isISRFSR) {
508  part.addStatus(MCParticle::c_IsISRPhoton);
509  part.addStatus(MCParticle::c_IsFSRPhoton);
510  }
511 
512  part.setPDG(pdg);
513  part.setFirstDaughter(0);
514  part.setLastDaughter(0);
515  part.setMomentum(ROOT::Math::XYZVector(mom[0], mom[1], mom[2]));
516  part.setMass(TDatabasePDG::Instance()->GetParticle(pdg)->Mass());
517  part.setEnergy(mom[3]);
518 
519  //boost
520  ROOT::Math::PxPyPzEVector p4 = part.get4Vector();
521  p4 = boost * p4;
522  part.set4Vector(p4);
523 
524  //set vertex
525  if (!isInitial) {
526  ROOT::Math::XYZVector v3 = part.getProductionVertex();
527  v3 = v3 + vertex;
528  part.setProductionVertex(v3);
529  part.setValidVertex(true);
530  }
531 }
Class to represent Particle data in graph.
Class to build, validate and sort a particle decay chain.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.