Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ProcRequirements.cc
Go to the documentation of this file.
1 ///
2 /// @file ProcRequirements.cc
3 /// @brief Container class for required ingredients for the process weight calculation
4 ///
5 
6 //**** This file is a part of the HAMMER library
7 //**** Copyright (C) 2016 - 2020 The HAMMER Collaboration
8 //**** HAMMER is licensed under version 3 of the GPL; see COPYING for details
9 //**** Please note the MCnet academic guidelines; see GUIDELINES for details
10 
11 // -*- C++ -*-
13 #include "Hammer/ProcGraph.hh"
14 #include "Hammer/Process.hh"
17 #include "Hammer/ProvidersRepo.hh"
18 #include "Hammer/ExternalData.hh"
19 #include "Hammer/AmplitudeBase.hh"
20 #include "Hammer/FormFactorBase.hh"
21 #include "Hammer/RateBase.hh"
22 #include "Hammer/Tools/Logging.hh"
23 #include "Hammer/Math/Utils.hh"
24 #include "Hammer/Particle.hh"
27 
28 #include <iostream>
29 #include <algorithm>
30 
31 using namespace std;
32 
33 namespace Hammer {
34 
35  ProcRequirements::ProcRequirements() {
36  }
37 
38  // ProcRequirements::~ProcRequirements() {
39  // }
40 
41  size_t ProcRequirements::initialize(const DictionaryManager* dictionaries, const Process* inputs, const ProcGraph* graph) {
42  _dictionaries = dictionaries;
43  _inputs = inputs;
44  _graph = graph;
45  getAmplitudes();
46  getRates();
47  getFormFactors();
48  return _requiredAmplitudes.size();
49  /// @todo what else needs to be done here?
50  //The 'else'. We'll never get that two hours back.
51  }
52 
53  pair<ParticleIndex, bool> ProcRequirements::getAncestorId(ParticleIndex descendant) const {
54  ParticleIndex parent = _inputs->getParentId(descendant);
55  if (_requiredAmplitudes.find(parent) != _requiredAmplitudes.end()) {
56  return {parent, false};
57  }
58  else {
59  ParticleIndex grandparent = _inputs->getParentId(parent);
60  if(grandparent < _inputs->numParticles()) {
61  return {grandparent, true};
62  }
63  return {_inputs->getFirstVertex(), false};
64  }
65  }
66 
67  void ProcRequirements::getAmplitudes() {
68  _requiredAmplitudes.clear();
69  _multPSFactors.clear();
70  _massPSFactors.clear();
71  _denominatorWilsonCoeffs.clear();
72  _specializedWilsonCoeffs.clear();
73  _requiredAmplitudes = _graph->selectedAmplitudes();
74  for(auto& elem: _requiredAmplitudes) {
75  AmplitudeBase* ampl = elem.second.amplitudes.denominator.ptr;
76  if(ampl != nullptr) {
77  auto twcptr = _dictionaries->externalData().getWilsonCoefficients(ampl, WTerm::DENOMINATOR);
78  if (twcptr && twcptr->rank() > 0) {
79  Tensor twc{"WC", {{twcptr, false}, {twcptr, true}}};
80  _denominatorWilsonCoeffs.push_back(move(twc));
81  }
82  }
83  AmplitudeBase* ampln = elem.second.amplitudes.numerator.ptr;
84  if(ampln != nullptr && _dictionaries->externalData().isWCSpecialized(ampln)){
85  auto swcptr = _dictionaries->externalData().getSpecializedWilsonCoefficients(ampln);
86  if (swcptr && swcptr->rank() > 0) {
87  Tensor swc{"WC", {{swcptr, false}, {swcptr, true}}};
88  _specializedWilsonCoeffs.push_back(move(swc));
89  }
90  }
91  }
92  if(_requiredAmplitudes.find(_inputs->getFirstVertex()) == _requiredAmplitudes.end()){
93  MSG_ERROR("An amplitude involving the parent particle is not implemented! 'Oh cock'...in Hungarian! (Check the PDG codes correspond to physical processes)");
94  }
95  //now fill the PS spin multiplicity and mass correction factors on the requiredAmplitudes map
96  for(auto& elem : _requiredAmplitudes) {
97  auto amplNum = elem.second.amplitudes.numerator; //a pair: a pointer and a type
98  auto amplDen = elem.second.amplitudes.denominator;
99  NumDenPair<double> multfact{1.,1.};
100  if (elem.first == _inputs->getFirstVertex()){
101  // VERTEX or FULLEDGE with non nullptr or a PARENTEDGE: usual 1/(2s_parent + 1) prefactor is included as parent vertex is NOT PS
102  // DAUGHTEREDGE: 1/(2s_parent + 1) prefactor is omitted and daughter 1/(s_daughter +1) included
103  // VERTEX or FULLEDGE nullptr: 1/(2s_parent + 1) prefactor is omitted
104  multfact.numerator = (amplNum.ptr != nullptr) ? 1./static_cast<double>(amplNum.ptr->multiplicityFactor()) : 1.;
105  multfact.denominator = (amplDen.ptr != nullptr) ? 1./static_cast<double>(amplDen.ptr->multiplicityFactor()) : 1.;
106  } else {
107  pair<ParticleIndex, bool> ancestor = getAncestorId(elem.first);
108  auto itAncestorAmpl = _requiredAmplitudes.find(get<0>(ancestor));
109  auto ancestorAmplNum = itAncestorAmpl->second.amplitudes.numerator;
110  auto ancestorAmplDen = itAncestorAmpl->second.amplitudes.denominator;
111  multfact.numerator =
112  (amplNum.ptr != nullptr) ? _graph->getMultFactor(amplNum, ancestorAmplNum, get<1>(ancestor)) : 1.;
113  multfact.denominator =
114  (amplDen.ptr != nullptr) ? _graph->getMultFactor(amplDen, ancestorAmplDen, get<1>(ancestor)) : 1.;
115  }
116  _multPSFactors.insert({elem.first, multfact});
117  NumDenPair<double> massfact{1.,1.};
118  massfact.numerator = _graph->getMassFactor(amplNum, elem.first, elem.second.daughterIdx);
119  massfact.denominator = _graph->getMassFactor(amplDen, elem.first, elem.second.daughterIdx);
120  _massPSFactors.insert({elem.first, massfact});
121  }
122  }
123 
124  vector<tuple<ParticleIndex, ParticleIndex, NumDenPair<AmplEntry>, NumDenPair<double>, NumDenPair<double>>>
125  ProcRequirements::generatedAmplsMultsPS() const {
126  vector<tuple<ParticleIndex, ParticleIndex, NumDenPair<AmplEntry>, NumDenPair<double>, NumDenPair<double>>> res;
127  res.clear();
128  for(auto& elem : _requiredAmplitudes){
129  auto corrmult = _multPSFactors.find(elem.first);
130  auto corrmass = _massPSFactors.find(elem.first);
131  tuple<ParticleIndex, ParticleIndex, NumDenPair<AmplEntry>, NumDenPair<double>, NumDenPair<double>> resTuple{elem.first, elem.second.daughterIdx, elem.second.amplitudes, corrmult->second, corrmass->second};
132  res.push_back(resTuple);
133  }
134  return res;
135  }
136 
137  void ProcRequirements::getFormFactors() {
138  _requiredFormFactors.clear();
139  _denominatorFFEigenVectors.clear();
140  for(auto& elem : _requiredAmplitudes) {
141  AmplitudeBase* ampNum = elem.second.amplitudes.numerator.ptr;
142  AmplitudeBase* ampDen = elem.second.amplitudes.denominator.ptr;
143  if (ampNum == nullptr && ampDen == nullptr) continue; //num and den cannot both be PS
144  HashId ffId = (ampNum != nullptr) ? ampNum->hadronicId() : ampDen->hadronicId() ;
145  auto ffs = _dictionaries->providers().getFormFactor(ffId);
146  if(ffs.size() > 0){
147  auto res = _requiredFormFactors.insert({elem.first, map<FFIndex, FormFactorBase*>{}});
148  if(res.second) {
149  auto indices = _dictionaries->schemeDefs().getFormFactorIndices(ffId);
150  auto denidx = _dictionaries->schemeDefs().getDenominatorFormFactor(ffId);
151  for(auto elem2: indices) {
152  res.first->second.insert({elem2, ffs[elem2]});
153  if(elem2 == denidx) {
154  FormFactorBase* pff = ffs[elem2];
155  if(pff != nullptr) {
156  auto tffeptr = _dictionaries->externalData().getFFEigenVectors(pff, "Denominator");
157  if (tffeptr && tffeptr->rank() > 0) {
158  Tensor tfferr{"", {{tffeptr, false}, {tffeptr, false}}};
159  _denominatorFFEigenVectors.push_back(move(tfferr));
160  }
161  }
162  }
163  }
164  }
165  }
166  }
167  }
168 
169  void ProcRequirements::getRates() {
170  for (auto& elem: _graph->assignedVertices()){ //Only seek rates or partial widths for vertices belonging to amplitudes
171  vector<PdgId> daughterPdgs;
172  auto daughters = _inputs->getDaughters(elem);
173  transform(daughters.begin(), daughters.end(), back_inserter(daughterPdgs), [](Particle P){ return P.pdgId(); });
174  auto tmp = combineDaughters(daughterPdgs, {});
175  auto parentPdg = _inputs->getParticle(elem).pdgId();
176  HashId id = processID(parentPdg, tmp);
177  auto rate = _dictionaries->providers().getRate(parentPdg, daughterPdgs);
178  if (rate != nullptr){
179  _requiredRates.insert({elem, rate});
180  _rateIds.insert({elem, id});
181  } else { //If no rate exists, look for a partial width
182  auto pw = _dictionaries->providers().getPartialWidth(parentPdg, daughterPdgs);
183  if (pw != nullptr){
184  _requiredPWs.insert({elem, pw});
185  _rateIds.insert({elem, id});
186  } else {
187  MSG_WARNING("No rate or partial width found for vertex with parent pdg " +
188  to_string(parentPdg) +
189  ". Check rate classes, and/or widths and branching fractions are defined.");
190  }
191  }
192  }
193  }
194 
195  const VertexDict<SelectedAmplEntry>& ProcRequirements::amplitudes() const {
196  return _requiredAmplitudes;
197  }
198 
199  const VertexDict<RateBase*>& ProcRequirements::rates() const {
200  return _requiredRates;
201  }
202 
203  const VertexDict<std::map<FFIndex, FormFactorBase*>>& ProcRequirements::formFactors() const {
204  return _requiredFormFactors;
205  }
206 
207  const std::vector<Tensor>& ProcRequirements::denominatorWilsonCoeffs() const {
208  return _denominatorWilsonCoeffs;
209  }
210 
211  const std::vector<Tensor>& ProcRequirements::denominatorFFEigenVectors() const {
212  return _denominatorFFEigenVectors;
213  }
214 
215  const std::vector<Tensor>& ProcRequirements::specializedWilsonCoeffs() const {
216  return _specializedWilsonCoeffs;
217  }
218 
219  const VertexDict<HashId>& ProcRequirements::rateIds() const {
220  return _rateIds;
221  }
222 
223  const VertexDict<const double*>& ProcRequirements::partialWidths() const {
224  return _requiredPWs;
225  }
226 
227 
228  double ProcRequirements::calcCorrectionFactor(WTerm what) const {
229  double factor = 1.;
230  for(auto& elem: _multPSFactors) {
231  factor *= elem.second.get(what);
232  }
233  for(auto& elem: _massPSFactors) {
234  factor *= elem.second.get(what);
235  }
236  return factor;
237  }
238 
239  Log& ProcRequirements::getLog() const {
240  return Log::getLog("Hammer.ProcRequirements");
241  }
242 
243 } // namespace Hammer
#define MSG_WARNING(x)
Definition: Logging.hh:366
PDG codes to UID functions.
Hammer base form factor class.
Base class for form factors.
Base class for amplitudes.
std::vector< PdgId > combineDaughters(const std::vector< PdgId > &daughters, const std::vector< PdgId > &subDaughters)
combine list of codes of daughters and grandaughters (for processes which parameterise two subsequent...
Container class for values of WC and FF vectors.
Decay process class.
Definition: Process.hh:34
Hammer base rate class.
Container class for required ingredients for the process weight calculation.
Interface class for amplitudes, rates, FFs dictionary container.
Message logging routines.
Hammer base amplitude class.
Container class for process tree structure and its amplitudes associations.
Interface class for tensor container data structure.
HashId hadronicId() const
returns the hadronic unique ID (parent + hadronic daughters) of the current decay signature ...
Definition: ParticleData.cc:40
Hammer process class.
Logging class.
Definition: Logging.hh:33
Particle class.
Definition: Particle.hh:30
Multidimensional tensor class with complex numbers as elements.
Definition: Tensor.hh:33
std::map< ParticleIndex, T > VertexDict
Definition: IndexTypes.hh:45
Container class for Scheme Definitions.
size_t ParticleIndex
Definition: IndexTypes.hh:27
Decay process class.
Definition: ProcGraph.hh:69
#define MSG_ERROR(x)
Definition: Logging.hh:367
HashId processID(PdgId parent, const std::vector< PdgId > &allDaughters)
compute a unique ID for a given process based on the PDG codes of the parent particle and the ordered...
Hammer particle class.
size_t HashId
Definition: IndexTypes.hh:31
Global container class for amplitudes, rates, FFs, data.