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.