27     AmplEntry AmplTriplet::resolvePurePS(
bool parentPS, 
bool daughterPS)
 const {
 
   28         int switchVal = (parent == 
nullptr ? 0 : 1) * 8 + (daughter == 
nullptr ? 0 : 1) * 4 + (parentPS ? 1 : 0) * 2 +
 
   30         if (switchVal % 4 == 0) { 
 
   31             return AmplEntry{edge, AmplType::FULLEDGE};
 
   33         if (switchVal % 4 == 3) { 
 
   34             return AmplEntry{
nullptr, AmplType::FULLEDGE};
 
   36         if ((abs(switchVal - 3) == 2)) { 
 
   37             MSG_ERROR(
"Daughter of an edge declared PS with undeclared parent. You can't touch this!");
 
   38             return AmplEntry{edge, AmplType::FULLEDGE};
 
   40         if ((abs(switchVal - 6) == 4)) { 
 
   41             MSG_ERROR(
"Parent of an edge declared PS with undeclared daughter. You can't touch this!");
 
   42             return AmplEntry{edge, AmplType::FULLEDGE};
 
   44         if ((abs(switchVal - 11) == 2)) { 
 
   45             return AmplEntry{parent, AmplType::PARENTEDGE};
 
   47         if ((abs(switchVal - 10) == 4)) { 
 
   48             return AmplEntry{daughter, AmplType::DAUGHTEREDGE};
 
   51         return AmplEntry{edge, AmplType::FULLEDGE};
 
   54     Log& AmplTriplet::getLog()
 const {
 
   55         return Log::getLog(
"Hammer.AmplTriplet");
 
   58     ProcGraph::ProcGraph() {
 
   62         _dictionaries = dictionaries;
 
   64         makeDepthMap(_inputs->getFirstVertex(), 0ul);
 
   65         makeVertexEdgeTrees();
 
   70         return _selectedAmplitudes;
 
   73         return _assignedVertices;
 
   77         auto it = _inputs->find(parent);
 
   78         if(it == _inputs->end()){
 
   81             _depthMap.insert({parent, seed});
 
   82             for(
auto& daughter : it->second){
 
   83                 makeDepthMap(daughter, seed + 1ul);    
 
   89     void ProcGraph::makeVertexEdgeTrees() {
 
   90         _implementedVertices.clear();
 
   91         _implementedEdges.clear();
 
   96         for(
auto& elem: *_inputs) {
 
   97             vector<PdgId> daughterPdgs;
 
   98             size_t parWeight = 0ul;
 
   99             for(
auto elem2: elem.second) {
 
  100                 daughterPdgs.push_back(_inputs->getParticle(elem2).pdgId());
 
  103             PdgId pdgParent = _inputs->getParticle(elem.first).pdgId();
 
  104             auto ampl = _dictionaries->providers().getAmplitude(pdgParent, daughterPdgs);
 
  105             auto purePS = _dictionaries->purePSDefs().isPurePhaseSpace(pdgParent, daughterPdgs);
 
  106             if (ampl != 
nullptr) {
 
  108                 _implementedVertices.push_back(amplTupl);
 
  112             for(
auto elem2: elem.second) {
 
  113                 auto it = _inputs->find(elem2);
 
  114                 if (it != _inputs->end()) {
 
  115                     size_t edgeWeight = parWeight;
 
  116                     vector<PdgId> granddaughterPdgs;
 
  118                     for(
auto elem3: it->second) {
 
  119                         PdgId pdgCodeGrandDaughter = _inputs->getParticle(elem3).pdgId();
 
  120                         granddaughterPdgs.push_back(pdgCodeGrandDaughter);
 
  122                     auto edgeAmpl = _dictionaries->providers().getAmplitude(pdgParent, daughterPdgs, granddaughterPdgs);
 
  123                     if (edgeAmpl != 
nullptr) {
 
  125                         PdgId pdgCodeDaughter = _inputs->getParticle(elem2).pdgId();
 
  126                         auto daughterAmpl = _dictionaries->providers().getAmplitude(pdgCodeDaughter, granddaughterPdgs);
 
  127                         auto daughterPurePS = _dictionaries->purePSDefs().isPurePhaseSpace(pdgCodeDaughter, granddaughterPdgs);
 
  128                         if (daughterAmpl != 
nullptr) {
 
  131                         AmplTriplet amplTriplet{ampl, daughterAmpl, edgeAmpl};
 
  132                         EdgeEntry edgeTupl{elem.first, elem2, amplTriplet, purePS, daughterPurePS};
 
  133                         _implementedEdges[edgeWeight][_depthMap.find(elem2)->second].push_back(edgeTupl);
 
  141         return _assignedVertices.find(index) != _assignedVertices.end();
 
  144     void ProcGraph::selectEdgeVertices() {
 
  145         _assignedVertices.clear();
 
  146         _selectedAmplitudes.clear();
 
  147         for(
auto& edgeWeight : _implementedEdges) {
 
  148             for(
auto& depthLevel : edgeWeight.second) { 
 
  149                 for(
auto& amplTuple : depthLevel.second) {
 
  150                     if (!isAssignedVertex(amplTuple.parentIdx) && !isAssignedVertex(amplTuple.daughterIdx)) {
 
  152                         AmplEntry numAmpl = amplTriplet.resolvePurePS(amplTuple.parentPSFlags.numerator,
 
  153                                                                       amplTuple.daughterPSFlags.numerator);
 
  154                         AmplEntry denAmpl = amplTriplet.resolvePurePS(amplTuple.parentPSFlags.denominator,
 
  155                                                                       amplTuple.daughterPSFlags.denominator);
 
  157                         _selectedAmplitudes.insert({amplTuple.parentIdx, tmpampl});
 
  158                         _assignedVertices.insert(amplTuple.parentIdx);
 
  159                         _assignedVertices.insert(amplTuple.daughterIdx);
 
  164         for(
auto& amplTuple : _implementedVertices) {
 
  165             if (!isAssignedVertex(amplTuple.parentIdx)) {
 
  166                 AmplEntry numAmpl{amplTuple.parentPSFlags.numerator ? 
nullptr : amplTuple.amplitude, AmplType::VERTEX};
 
  167                 AmplEntry denAmpl{amplTuple.parentPSFlags.denominator ? 
nullptr : amplTuple.amplitude, AmplType::VERTEX};
 
  169                 _selectedAmplitudes.insert({amplTuple.parentIdx, tmpampl});
 
  170                 _assignedVertices.insert(amplTuple.parentIdx);
 
  177         if (!_inputs->isParent(parent) || !_inputs->isParent(daughter)) {
 
  178             MSG_ERROR(
"Something really stinky just happened in CalcAmplitudes. Can you smell it?");
 
  181         case AmplType::VERTEX: {
 
  182             return tuple<Particle, ParticleList, ParticleList>{
 
  183                 _inputs->getParticle(parent), _inputs->getDaughters(parent, 
true), _inputs->getSiblings(parent, 
true)};
 
  185         case AmplType::FULLEDGE: {
 
  186             auto daughters = _inputs->getDaughters(parent, 
true);
 
  187             auto tmp = _inputs->getDaughters(daughter, 
true);
 
  188             daughters.insert(daughters.end(), tmp.begin(), tmp.end());
 
  189             return tuple<Particle, ParticleList, ParticleList>{_inputs->getParticle(parent), daughters,
 
  190                                                                _inputs->getSiblings(parent, 
true)};
 
  192         case AmplType::PARENTEDGE: {
 
  193             return tuple<Particle, ParticleList, ParticleList>{
 
  194                 _inputs->getParticle(parent), _inputs->getDaughters(parent, 
true), _inputs->getSiblings(parent, 
true)};
 
  196         case AmplType::DAUGHTEREDGE: {
 
  197             return tuple<Particle, ParticleList, ParticleList>{_inputs->getParticle(daughter),
 
  198                                                                _inputs->getDaughters(daughter, 
true),
 
  199                                                                _inputs->getSiblings(daughter, 
true)};
 
  202         MSG_ERROR(
"Something really stinky just happened in CalcAmplitudes. Can you smell it?");
 
  203         return tuple<Particle, ParticleList, ParticleList>{
 
  204             _inputs->getParticle(parent), _inputs->getDaughters(parent, 
true), _inputs->getSiblings(parent, 
true)};
 
  208         if (!_inputs->isParent(parent) || !_inputs->isParent(daughter)) {
 
  209             MSG_ERROR(
"Something really stinky just happened in getMassFactor. Can you smell it?");
 
  211         auto pmass = _inputs->getParticle(parent).p().mass();
 
  212         auto dsize = 
static_cast<double>(_inputs->getDaughters(parent).size());
 
  214         case AmplType::VERTEX: {
 
  215             if (ampl.
ptr == 
nullptr) { 
 
  216                 return pow(pmass, 6. - 2. * dsize);
 
  220         case AmplType::FULLEDGE: {
 
  221             if (ampl.
ptr == 
nullptr) { 
 
  222                 auto dmass = _inputs->getParticle(daughter).p().mass();
 
  223                 auto gdsize = 
static_cast<double>(_inputs->getDaughters(daughter).size());
 
  224                 return pow(pmass, 6. - 2. * dsize) * pow(dmass, 6. - 2. * gdsize);
 
  228         case AmplType::PARENTEDGE: {
 
  229             auto dmass = _inputs->getParticle(daughter).p().mass();
 
  230             auto gdsize = 
static_cast<double>(_inputs->getDaughters(daughter).size());
 
  231             return pow(dmass, 6. - 2. * gdsize);
 
  233         case AmplType::DAUGHTEREDGE: {
 
  234             return pow(pmass, 6. - 2. * dsize);
 
  240     double ProcGraph::getMultFactor(
AmplEntry ampl, 
AmplEntry ancestorAmpl, 
bool isAncestorGrandparent)
 const {
 
  242         if (ampl.
type == AmplType::DAUGHTEREDGE) { 
 
  246         if (isAncestorGrandparent) { 
 
  247             if (ancestorAmpl.
ptr == 
nullptr || ancestorAmpl.
type == AmplType::PARENTEDGE) {
 
  251             if (ancestorAmpl.
ptr == 
nullptr || ancestorAmpl.
type == AmplType::DAUGHTEREDGE) {
 
  258     Log& ProcGraph::getLog()
 const {
 
  259         return Log::getLog(
"Hammer.ProcGraph");
 
PDG codes to UID functions. 
 
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. 
 
Container class for pure phase space vertices definitions. 
 
VertexDict< SelectedAmplEntry > SelAmplitudeDict
 
size_t multiplicityFactor() const 
 
std::set< ParticleIndex > UniqueParticleIndices
 
Global container class for amplitudes, rates, FFs, data.