Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ProcManager.cc
Go to the documentation of this file.
1 ///
2 /// @file ProcManager.cc
3 /// @brief Container class for all process related data structures
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/ProcManager.hh"
14 #include "Hammer/AmplitudeBase.hh"
15 #include "Hammer/FormFactorBase.hh"
16 #include "Hammer/RateBase.hh"
22 #include "Hammer/ProcRates.hh"
24 #include "Hammer/Tools/Pdg.hh"
25 
26 #include <iostream>
27 
28 using namespace std;
29 
30 namespace Hammer {
31 
32  namespace MD = MultiDimensional;
33 
34  ProcManager::ProcManager(const Process& inputs)
35  : _inputs{new Process{inputs}},
36  _graph{new ProcGraph{}},
37  _reqs{new ProcRequirements{}},
38  _results{new ProcResults{}},
39  _processRates{nullptr},
40  _dictionaries{nullptr} {
41  // initSettings();
42  }
43 
45  }
46 
47  ProcManager::ProcManager(const Serial::FBProcess* msgreader) : ProcManager{Process{}} {
48  read(msgreader, false);
49  }
50 
52  : SettingsConsumer{other}, _inputs{other._inputs.release()},
53  _graph{other._graph.release()},
54  _reqs{other._reqs.release()},
55  _results{other._results.release()},
56  _processRates{other._processRates},
57  _dictionaries{other._dictionaries} {
58  // initSettings();
59  }
60 
61  // ProcManager::~ProcManager() noexcept {
62  // }
63 
66  _results->setSettingsHandler(sh);
67  }
68 
71  _results->setSettingsHandler(sh);
72  }
73 
75  _dictionaries = dict;
76  }
77 
79  setDictionary(dictionaries);
80  if (_inputs->initialize()) {
81  if(_dictionaries->processDefs().isProcessIncluded(_inputs->fullId(), _inputs->getId())) {
82  _graph->initialize(dictionaries,_inputs.get());
83  auto numAmpls = _reqs->initialize(dictionaries, _inputs.get(), _graph.get());
84  if(numAmpls == 0) { //|| _requiredFormFactors.size() == 0 || _requiredRate == nullptr) {
86  _inputs->disable();
87  return;
88  }
89  for(auto& id : _reqs->rateIds()){
91  if(_processRates != nullptr && _processRates->size() == 0) {
92  calcRates(id.first);
93  }
94  }
95  } else {
96  _inputs->disable();
97  return;
98  }
99  }
100  /// @todo what else needs to be done here?
101  //The 'else'. We'll never get that two hours back.
102  }
103 
105  // calc amps & amps^2
106  if(isOn("Amplitudes")) {
107  pair<bool, bool> first{true, true};
108  _results->processAmplitude(WTerm::NUMERATOR) = Tensor{"PurePSNumerator", MD::makeScalar(1.)};
109  _results->processAmplitude(WTerm::DENOMINATOR) = Tensor{"PurePSDenominator", MD::makeScalar(1.)};
110  for (auto& elem : _reqs->amplitudes()) {
111  auto amplNum = elem.second.amplitudes.numerator;
112  auto amplDen = elem.second.amplitudes.denominator;
113  auto numamp = amplNum.ptr;
114  auto denamp = amplDen.ptr;
115  if (numamp != nullptr) {
116  auto particles = _graph->getParticleVectors(amplNum.type, elem.first, elem.second.daughterIdx);
117  numamp->eval(get<0>(particles), get<1>(particles), get<2>(particles));
118  if (first.first) {
119  _results->processAmplitude(WTerm::NUMERATOR) = numamp->getTensor();
120  first.first = false;
121  }
122  else {
123  _results->processAmplitude(WTerm::NUMERATOR).dot(numamp->getTensor());
124  }
125  numamp->addRefs();
126  }
127  if (denamp != nullptr) {
128  if (numamp != denamp) {
129  auto particles = _graph->getParticleVectors(amplDen.type, elem.first, elem.second.daughterIdx);
130  denamp->eval(get<0>(particles), get<1>(particles), get<2>(particles));
131  }
132  if(first.second) {
133  _results->processAmplitude(WTerm::DENOMINATOR) = denamp->getTensor();
134  first.second = false;
135  }
136  else {
137  _results->processAmplitude(WTerm::DENOMINATOR).dot(denamp->getTensor());
138  }
139  denamp->addRefs();
140  }
141  }
142  }
143  if (isOn("SquaredAmplitudes")) { // && _results->processAmplitude(WTerm::NUMERATOR).rank() > 0) {
144  _results->processAmplitudeSquared(WTerm::NUMERATOR) = outerSquare(_results->processAmplitude(WTerm::NUMERATOR));
145  _results->processAmplitudeSquared(WTerm::NUMERATOR).spinSum();
146  _results->processAmplitudeSquared(WTerm::NUMERATOR) *= _reqs->calcCorrectionFactor(WTerm::NUMERATOR);
147  }
148  if(isOn("SquaredAmplitudes")){ // && _results->processAmplitude(WTerm::DENOMINATOR).rank() > 0) {
149  _results->processAmplitudeSquared(WTerm::DENOMINATOR) = outerSquare(_results->processAmplitude(WTerm::DENOMINATOR));
150  _results->processAmplitudeSquared(WTerm::DENOMINATOR).spinSum();
151  _results->processAmplitudeSquared(WTerm::DENOMINATOR) *= _reqs->calcCorrectionFactor(WTerm::DENOMINATOR);
152  }
153  if (isOn("FormFactors")) {
154  // calc ffs
155  _results->clearFormFactors();
156  auto& dict = _dictionaries->schemeDefs().getSchemeDefs();
157  Tensor noFF{"noFF", MD::makeScalar(1.)};
158  for(auto& elem: _reqs->amplitudes()){
159  auto itFF = _reqs->formFactors().find(elem.first);
160  if(itFF != _reqs->formFactors().end()){
161  AmplitudeBase* ampNum = elem.second.amplitudes.numerator.ptr;
162  AmplitudeBase* ampDen = elem.second.amplitudes.denominator.ptr;
163  HashId id = (ampNum != nullptr) ? ampNum->hadronicId() : ampDen->hadronicId(); //num and den cannot both be nullptr in _requiredFormFactors
164  auto it = _inputs->find(elem.first);
165  if(it == _inputs->end()) {
166  MSG_ERROR("Something really stinky just happened in CalcFormFactors. Can you smell it?");
167  return;
168  }
169  auto daughters = _inputs->getDaughters(it->first,true);
170  auto& parent = _inputs->getParticle(it->first);
171  auto siblings = _inputs->getSiblings(it->first, true);
172  for(auto& elemCh: dict) {
173  auto itCh = elemCh.second.find(id);
174  if(itCh != elemCh.second.end()) {
175  auto iFF = itFF->second.find(itCh->second);
176  if(iFF != itFF->second.end()) {
177  if ((elemCh.first == "Denominator" && ampDen == nullptr) || (elemCh.first != "Denominator" && ampNum == nullptr)){
178  _results->appendFormFactor(elemCh.first, noFF);
179  continue;
180  }
181  iFF->second->eval(parent, daughters, siblings);
182  _results->appendFormFactor(elemCh.first, iFF->second->getTensor());
183  iFF->second->addRefs();
184  }
185  }
186  }
187  } else {
188  for(auto& elemCh: dict) {
189  _results->appendFormFactor(elemCh.first, noFF);
190  }
191  }
192  }
193  }
194  if (isOn("Weights")) {
195  // calc denominator
196  Tensor denominator = _results->processAmplitudeSquared(WTerm::DENOMINATOR);
197  if (_results->haveFormFactors()) {
198  if (denominator.hasFFLabels()){
199  auto ffdens = _results->processFormFactors("Denominator");
200  for(auto& elem: ffdens) {
201  Tensor t = elem;
202  t.outerSquare();
203  denominator.dot(t);
204  }
205  }
206  }
207  if (denominator.hasFFVarLabels()){
208  for(auto& elem: _reqs->denominatorFFEigenVectors()) {
209  denominator.dot(elem);
210  }
211  }
212  if (denominator.hasWCLabels()){
213  for(auto& elem: _reqs->denominatorWilsonCoeffs()) {
214  denominator.dot(elem);
215  }
216  }
217  if(denominator.rank() > 0) {
218  MSG_ERROR("Denominator has uncontracted indices, with rank " + to_string(denominator.rank()) + ". There's a monster in the basement! Check FF input scheme has been correctly set.");
219  return;
220  }
221  double denValue = denominator.element().real();
222  // calc weights
223  _results->clearWeights();
224  for (auto& elem : _results->availableSchemes()) {
225  Tensor tbase = _results->processAmplitudeSquared(WTerm::NUMERATOR);
226  //Contract with specialized WCs if any
227  if(tbase.hasWCLabels()){
228  for(auto& elem2: _reqs->specializedWilsonCoeffs()) {
229  tbase.dot(elem2);
230  }
231  }
232  // loop for possible multiple FFs in one process
233  if(tbase.hasFFLabels()){
234  for (auto& elem2 : _results->processFormFactors(elem)) {
235  Tensor t = elem2;
236  t.outerSquare();
237  tbase.dot(t);
238  }
239  }
240  tbase *= 1. / denValue;
241  _results->setProcessWeight(elem, tbase);
242  }
243  }
244  }
245 
247  return *_results;
248  }
249 
250  const Process& ProcManager::inputs() const {
251  return *_inputs;
252  }
253 
255  setPath("ProcessCalc");
256  addSetting<bool>("FormFactors", true);
257  addSetting<bool>("SquaredAmplitudes", true);
258  addSetting<bool>("Amplitudes", true);
259  addSetting<bool>("Rates", true);
260  addSetting<bool>("Weights", true);
261  }
262 
263  void ProcManager::write(flatbuffers::FlatBufferBuilder* msgwriter,
266  _inputs->write(msgwriter, &serialids);
268  _results->write(msgwriter, &serialdata);
269  Serial::FBProcessBuilder serialprocess{*msgwriter};
270  serialprocess.add_ids(serialids);
271  serialprocess.add_data(serialdata);
272  *msg = serialprocess.Finish();
273  }
274 
275  bool ProcManager::read(const Serial::FBProcess* msgreader, bool merge) {
276  if (msgreader != nullptr) {
277  bool res = true;
278  if(!merge) {
279  _inputs->read(msgreader->ids());
280  }
281  if (_dictionaries->processDefs().isProcessIncluded(_inputs->fullId(), _inputs->getId())) {
282  res &= _results->read(msgreader->data(), merge);
283  }
284  return res;
285  }
286  return false;
287  }
288 
290  if (!_inputs->isParent(parent)) {
291  MSG_ERROR("Something really stinky just happened in calcPSTensor. Can you smell it?");
292  }
293  Tensor res{"PS", MD::makeEmptyScalar()};
294  PID& pdg = PID::instance();
295  auto pmassPDG = pdg.getMass(_inputs->getParticle(parent).pdgId());
296  auto daughters = _inputs->getDaughters(parent);
297  vector<double> dmassesPDG;
298  for(auto& elem: daughters){
299  dmassesPDG.push_back(pdg.getMass(elem.pdgId()));
300  }
301  res.element({}) = 0.5*phaseSpaceNBody(pmassPDG, dmassesPDG)*pow(pmassPDG, static_cast<double>(5-2*daughters.size()));
302  return res;
303  }
304 
305  Tensor ProcManager::calcRateTensor(const ParticleIndex& parent, const map<HashId, FFIndex>& ffmaps,
306  const string& scheme) const {
307  auto itr = _reqs->rates().find(parent);
308  if (itr != _reqs->rates().end()){
309  RateBase* rateptr = itr->second;
310  rateptr->calcTensor();
311  Tensor rateT = rateptr->getTensor();
312  auto itf = _reqs->formFactors().find(parent);
313  auto itidx = ffmaps.find(rateptr->hadronicId());
314  if(itf != _reqs->formFactors().end() && itidx != ffmaps.end()){
315  auto itFF = itf->second.find(itidx->second);
316  const auto& points = rateptr->getEvaluationPoints();
317  Tensor rateFF = itFF->second->getFFPSIntegrand(points);
318  rateT.dot(rateFF);
319  }
320  if(rateT.hasFFLabels()) {
321  MSG_ERROR("Unable to contract rate tensor for vertex with parent " + to_string(_inputs->getParticle(parent).pdgId()) + " with scheme " + scheme + ". Eject! Eject!");
322  return Tensor{"EmptyRateTensor", MD::makeEmptyScalar()};
323  }
324  return rateT;
325  } else {
326  auto itpw = _reqs->partialWidths().find(parent);
327  if (itpw != _reqs->partialWidths().end()){
328  Tensor pw{"PW", MD::makeEmptyScalar()};
329  pw.element({}) = *(itpw->second);
330  return pw;
331  }
332  }
333  MSG_ERROR("Unable to compute rate tensor for vertex with parent " + to_string(_inputs->getParticle(parent).pdgId()) + " and scheme "
334  + scheme + ". Pull up! Pull up!");
335  return Tensor{"EmptyRateTensor", MD::makeEmptyScalar()};
336  }
337 
338  void ProcManager::calcRates(const ParticleIndex& parent) const {
339  if(!isOn("Rates")) { return; }
340  auto it = _reqs->amplitudes().find(parent);
341  if (it == _reqs->amplitudes().end()) { return; } //Daughter vertices to be filled with parent
342  auto amplNum = (it->second).amplitudes.numerator;
343  auto amplDen = (it->second).amplitudes.denominator;
344  auto daughter = (it->second).daughterIdx;
346  for(auto& scheme : schemes){
347  auto ampl = (scheme.first == "Denominator") ? amplDen : amplNum;
348  switch (ampl.type) {
349  case AmplType::VERTEX: {
350  if(ampl.ptr == nullptr){
351  _processRates->insert({scheme.first, calcPSTensor(parent)});
352  } else {
353  _processRates->insert({scheme.first, calcRateTensor(parent, scheme.second, scheme.first)});
354  }
355  break;
356  }
357  case AmplType::FULLEDGE: {
358  auto dprocessRates = _dictionaries->rates().getProcessRates(_reqs->rateIds().at(daughter));
359  if (ampl.ptr == nullptr) {
360  _processRates->insert({scheme.first, calcPSTensor(parent)});
361  dprocessRates->insert({scheme.first, calcPSTensor(daughter)});
362  } else {
363  _processRates->insert({scheme.first, calcRateTensor(parent, scheme.second, scheme.first)});
364  dprocessRates->insert({scheme.first, calcRateTensor(daughter, scheme.second, scheme.first)});
365  }
366  break;
367  }
368  case AmplType::PARENTEDGE: {
369  auto dprocessRates = _dictionaries->rates().getProcessRates(_reqs->rateIds().at(daughter));
370  _processRates->insert({scheme.first, calcRateTensor(parent, scheme.second, scheme.first)});
371  dprocessRates->insert({scheme.first, calcPSTensor(daughter)});
372  break;
373  }
374  case AmplType::DAUGHTEREDGE: {
375  auto dprocessRates = _dictionaries->rates().getProcessRates(_reqs->rateIds().at(daughter));
376  _processRates->insert({scheme.first, calcPSTensor(parent)});
377  dprocessRates->insert({scheme.first, calcRateTensor(daughter, scheme.second, scheme.first)});
378  }
379  }
380  }
381  }
382 
383 // NumDenPair<double> ProcessManager::getPSRates() const {
384 // return _processPhaseSpaceRates;
385 // }
386 
388  return Log::getLog("Hammer.ProcManager");
389  }
390 
391 } // namespace Hammer
virtual void defineSettings()
purely virtual function for a class to define new settings
Definition: ProcManager.cc:254
Tensor & outerSquare()
creates a tensor with twice the rank by multiplying the tensor with its hermitean conjugate ...
Definition: Tensor.cc:162
DictionaryManager * _dictionaries
Definition: ProcManager.hh:123
std::complex< double > & element(const IndexList &indices={})
access an element given its indices
Definition: Tensor.cc:67
virtual void forbidProcess(ProcessUID processId) const
Hammer base form factor class.
Base class for amplitudes.
SchemeDict< Tensor > * _processRates
Definition: ProcManager.hh:120
TensorData read(const Serial::FBTensor *msgreader)
Definition: Operations.cc:76
Tensor calcPSTensor(const ParticleIndex &parent) const
Definition: ProcManager.cc:289
virtual void initialize(DictionaryManager *dictionaries)
Definition: ProcManager.cc:78
Tensor outerSquare(const Tensor &first)
creates a tensor with twice the rank by multiplying the tensor with it&#39;s hermitean conjugate ...
Definition: Tensor.cc:316
void write(flatbuffers::FlatBufferBuilder *msgwriter, flatbuffers::Offset< Serial::FBProcess > *msg) const
Definition: ProcManager.cc:263
void calcRates(const ParticleIndex &parent) const
Definition: ProcManager.cc:338
void setPath(const std::string &path)
provide the basic path for the settings defined by this class, as in &quot;&lt;path&gt;:&lt;setting&gt;&quot; ...
Decay process class.
Definition: Process.hh:34
Hammer base rate class.
Container class for storing included/forbidden process info.
virtual const SchemeDict< ProcIdDict< FFIndex > > & getSchemeDefs() const
double phaseSpaceNBody(const double parentMass, const vector< double > &daughterMasses)
Definition: PhaseSpace.cc:52
std::unique_ptr< ProcResults > _results
Definition: ProcManager.hh:119
Hammer base amplitude class.
bool hasFFLabels() const
checks if Tensor has indices in the FF range
Definition: Tensor.cc:92
Decay process class.
Definition: ProcResults.hh:33
std::unique_ptr< ProcRequirements > _reqs
Definition: ProcManager.hh:118
Phase space integrals.
void calcTensor()
evaluates the rate by computing the (rank N) rate tensor at different points using evalAtPSPoint on ...
Definition: RateBase.cc:96
virtual void setSettingsHandler(SettingsHandler &sh)
set link to settings repository handler.
Definition: ProcManager.cc:64
Base class to access the settings repository.
std::unique_ptr< Process > _inputs
Definition: ProcManager.hh:116
virtual bool isProcessIncluded(std::set< HashId > subamplitudes, ProcessUID processId) const
size_t rank() const
rank of the tensor
Definition: Tensor.cc:75
static Log & getLog(const std::string &name)
Get a logger with the given name.
Definition: Logging.cc:139
virtual void setSettingsHandler(SettingsHandler &sh)
set link to settings repository handler.
Tensor calcRateTensor(const ParticleIndex &parent, const ProcIdDict< FFIndex > &ffmaps, const std::string &schemeName) const
Definition: ProcManager.cc:305
HashId hadronicId() const
returns the hadronic unique ID (parent + hadronic daughters) of the current decay signature ...
Definition: ParticleData.cc:40
Decay process class.
Definition: ProcManager.hh:42
void setDictionary(DictionaryManager *dict)
Definition: ProcManager.cc:74
Order-0 tensor data container.
Logging class.
Definition: Logging.hh:33
const Process & inputs() const
Definition: ProcManager.cc:250
Log & getLog() const
logging facility
Definition: ProcManager.cc:387
Hammer class for dealing with particle data.
Definition: Pdg.hh:32
Multidimensional tensor class with complex numbers as elements.
Definition: Tensor.hh:33
Tensor & getTensor()
returns a reference to itself as a Tensor
Definition: RateBase.cc:60
Container class for all process related data structures.
TensorData makeScalar(complex< double > value)
std::unique_ptr< ProcGraph > _graph
Definition: ProcManager.hh:117
virtual const ProcRates & rates() const
static PID & instance()
Definition: Pdg.cc:283
const ProcResults & results() const
Definition: ProcManager.cc:246
Hammer particle data class.
bool read(const Serial::FBProcess *msgreader, bool merge)
Definition: ProcManager.cc:275
Hammer numerical integration classes.
Container class for Scheme Definitions.
Hammer settings manager class.
size_t ParticleIndex
Definition: IndexTypes.hh:27
Decay process class.
Definition: ProcGraph.hh:69
std::map< SchemeName, T > SchemeDict
Definition: IndexTypes.hh:64
Tensor & dot(const Tensor &other, const UniqueLabelsList &indices={})
contract this tensor with another and stores the result in this tensor
Definition: Tensor.cc:114
const EvaluationGrid & getEvaluationPoints() const
Definition: RateBase.cc:92
#define MSG_ERROR(x)
Definition: Logging.hh:367
virtual const SchemeDefinitions & schemeDefs() const
size_t HashId
Definition: IndexTypes.hh:31
bool isOn(const std::string &name) const
method to check a boolean setting defined by this class
Container class for process rate tensors.
virtual SchemeDict< Tensor > * getProcessRates(ProcessUID id)
Definition: ProcRates.cc:45
Serialization related typedefs and includes.
bool hasFFVarLabels() const
checks if Tensor has indices in the FF Var range
Definition: Tensor.cc:97
Base class for rates.
Definition: RateBase.hh:39
virtual const ProcessDefinitions & processDefs() const
double getMass(PdgId id) const
particle mass from a PDG code
Definition: Pdg.cc:62
Global container class for amplitudes, rates, FFs, data.
bool hasWCLabels() const
checks if Tensor has indices in the WC range
Definition: Tensor.cc:87