Version: SMASH-2.2
hepmcinterface.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2021 Christian Holm Christensen
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/hepmcinterface.h"
11 #include "smash/config.h"
12 #include "smash/experiment.h"
13 
14 #include "HepMC3/GenRunInfo.h"
15 #include "HepMC3/Print.h"
16 #include "HepMC3/Setup.h"
17 #include "smash/logging.h"
18 
19 namespace smash {
20 
21 HepMcInterface::HepMcInterface(const std::string& name, const bool full_event)
22  : OutputInterface(name),
23  event_(HepMC3::Units::GEV, HepMC3::Units::MM),
24  ion_(),
25  xs_(),
26  ip_(),
27  full_event_(full_event) {
28  logg[LOutput].debug() << "Name of output: " << name << " "
29  << (full_event_ ? "full event" : "final state only")
30  << " output" << std::endl;
31  ion_ = std::make_shared<HepMC3::GenHeavyIon>();
32  ion_->set(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1.0, -1.0, -1.0, -1.0, -1.0,
33  -1.0);
34 
35  xs_ = std::make_shared<HepMC3::GenCrossSection>();
36  // GenRunInfo: HepMC3 class to store run-related information
37  std::shared_ptr<HepMC3::GenRunInfo> run_info =
38  std::make_shared<HepMC3::GenRunInfo>();
39  std::vector<std::string> weightnames;
40  weightnames.push_back("Default");
41  run_info->set_weight_names(weightnames);
42  HepMC3::GenRunInfo::ToolInfo tool;
43  tool.name = "SMASH";
44  tool.version = SMASH_VERSION;
45 #ifdef GIT_BRANCH
46  tool.version = tool.version + GIT_BRANCH;
47 #endif
48  tool.description = "";
49  run_info->tools().push_back(tool);
50  event_.set_run_info(run_info);
51  HepMC3::Setup::set_debug_level(logg[LOutput].isEnabled<einhard::DEBUG>() ? 5
52  : 0);
53 }
54 
56  const int event_number,
57  const EventInfo& event) {
58  // Clear event and mapping and set event number
59  clear();
60 
61  // Set header stuff on event
62  ion_->impact_parameter = event.impact_parameter;
63  xs_->set_cross_section(1, 1); // Dummy values
64  event_.set_event_number(event_number);
65  event_.set_heavy_ion(ion_);
66 
67  // Create IP only if final state
68  ip_ = std::make_shared<HepMC3::GenVertex>();
69  event_.add_vertex(ip_);
70 
71  // Count up projectile and target
72  smash::FourVector p_proj;
73  smash::FourVector p_targ;
74  AZ az_proj{0, 0};
75  AZ az_targ{0, 0};
76  bool is_coll = (event.impact_parameter >= 0.0);
77 
78  for (auto& data : particles) {
79  if (is_coll) {
80  if (!data.is_neutron() && !data.is_proton()) {
81  throw std::runtime_error(
82  "Particle of PID=" + std::to_string(data.pdgcode().get_decimal()) +
83  " is not a valid HepMC beam particle!");
84  }
85 
86  if (data.belongs_to() == BelongsTo::Projectile) {
87  p_proj += data.momentum();
88  az_proj.first++;
89  az_proj.second += data.type().charge();
90  } else if (data.belongs_to() == BelongsTo::Target) {
91  p_targ += data.momentum();
92  az_targ.first++;
93  az_targ.second += data.type().charge();
94  }
95  }
96 
97  if (!full_event_ && is_coll) {
98  continue;
99  }
100 
101  // If we are not only adding final state particles, but all
102  // interactions, or not in collider modus, then we add all the
103  // incoming particles as outgoing (incoming for non-collider
104  // modus) of the vertex. In that way, we will keep track of
105  // participants and spectators as well as make the event
106  // structure consistent.
107  auto op = make_register(data, Status::fnal);
108  if (is_coll) {
109  ip_->add_particle_out(op);
110  } else {
111  ip_->add_particle_in(op);
112  }
113  }
114 
115  coll_.resize(az_proj.first + az_targ.first);
116  // Make beam particles
117  if (is_coll) {
118  auto proj = make_gen(ion_pdg(az_proj), Status::beam, p_proj);
119  auto targ = make_gen(ion_pdg(az_targ), Status::beam, p_targ);
120 
121  // Add to interaction point if we need to
122  ip_->add_particle_in(proj);
123  ip_->add_particle_in(targ);
124  }
125 }
126 
128  const double /* density */) {
129  HepMC3::GenVertexPtr vp;
130  auto type = action.get_type();
131  int status = get_status(type);
132 
133  if (full_event_) {
134  FourVector v = action.get_interaction_point();
135  vp = std::make_shared<HepMC3::GenVertex>(
136  HepMC3::FourVector(v.x1(), v.x2(), v.x3(), v.x0()));
137  event_.add_vertex(vp);
138  vp->add_attribute("weight", std::make_shared<HepMC3::FloatAttribute>(
139  action.get_total_weight()));
140  vp->add_attribute(
141  "partial_weight",
142  std::make_shared<HepMC3::FloatAttribute>(action.get_partial_weight()));
143  }
144 
145  // Now mark participants
146  if (full_event_) {
147  for (auto& i : action.incoming_particles()) {
148  // Create tree
149  HepMC3::GenParticlePtr ip = find_or_make(i, status);
150  ip->set_status(status);
151  vp->add_particle_in(ip);
152  }
153  } else {
154  return;
155  }
156 
157  // Add outgoing particles
158  for (auto& o : action.outgoing_particles()) {
159  vp->add_particle_out(make_register(o, Status::fnal));
160  }
161 }
162 
164  const int32_t /*event_number*/,
165  const EventInfo& event) {
166  // We evaluate if it is a heavy ion collision event
167  bool is_coll = (event.impact_parameter >= 0.0);
168  // In case this was an empty event
169  if (event.empty_event && is_coll) {
170  clear();
171  return;
172  }
173  // Set the weights
174  event_.weights() = std::vector<double>(1, 1);
175  /* since the number of collisions is not an experimental obervable, we set it
176  * to -1.
177  */
178  ion_->Ncoll_hard = -1;
179  ion_->Ncoll = -1;
180  /* This should be the number of participants in the projectile nucleus.
181  * However, to avoid confusion with the Glauber model, we prefer to set it -1.
182  */
183  ion_->Npart_proj = -1;
184  /* This should be the number of participants in the target nucleus.
185  * However, to avoid confusion with the Glauber model, we prefer to set it -1.
186  */
187  ion_->Npart_targ = -1;
188  // If we only do final state events, then take particle
189  // Note, we should already have the particles if not only final
190  // state
191  // Take all passed particles and add as outgoing particles to event
192  for (auto& p : particles) {
193  if (!full_event_) {
194  auto h = make_register(p, Status::fnal);
195  ip_->add_particle_out(h);
196  } else if (map_.find(p.id()) == map_.end()) {
197  throw std::runtime_error("Dangling particle " + std::to_string(p.id()));
198  }
199  }
200 }
201 
203  event_.clear();
204  map_.clear();
205  ip_ = 0;
206  coll_ = 0;
207  ncoll_ = 0;
208  ncoll_hard_ = 0;
209 }
210 
212  if (t == ProcessType::Decay)
213  return Status::dcy;
214 
215  // Make all other codes SMASH specific
216  return static_cast<int>(t) + static_cast<int>(Status::off);
217 }
218 
219 HepMC3::GenParticlePtr HepMcInterface::make_gen(int pid, int status,
220  const smash::FourVector& mom,
221  double mass) {
222  auto p = std::make_shared<HepMC3::GenParticle>(
223  HepMC3::FourVector(mom.x1(), mom.x2(), mom.x3(), mom.x0()), pid, status);
224  if (mass > 0)
225  p->set_generated_mass(mass);
226  return p;
227 }
228 
229 HepMC3::GenParticlePtr HepMcInterface::make_register(const ParticleData& p,
230  int status) {
231  int id = p.id();
232  auto h = make_gen(p.pdgcode().get_decimal(), status, p.momentum(),
233  p.type().mass());
234  map_[id] = h;
235 
236  return h;
237 }
238 
239 HepMC3::GenParticlePtr HepMcInterface::find_or_make(const ParticleData& p,
240  int status,
241  bool force_new) {
242  int id = p.id();
243  if (!force_new) {
244  auto it = map_.find(id);
245  if (it != map_.end()) {
246  return it->second;
247  }
248  }
249 
250  return make_register(p, status);
251 }
252 
253 int HepMcInterface::ion_pdg(const AZ& az) const {
254  if (az.second == 1 && az.first == 1)
255  return 2212; // Proton
256  if (az.second == 1 && az.first == 0)
257  return 2112; // Neutron
258 
259  return 1000 * 1000 * 1000 + az.second * 10 * 1000 + az.first * 10;
260 }
261 } // namespace smash
Action is the base class for a generic process that takes a number of incoming particles and transfor...
Definition: action.h:35
virtual ProcessType get_type() const
Get the process type.
Definition: action.h:131
virtual double get_total_weight() const =0
Return the total weight value, which is mainly used for the weight output entry.
const ParticleList & incoming_particles() const
Get the list of particles that go into the action.
Definition: action.cc:57
virtual double get_partial_weight() const =0
Return the specific weight for the chosen outgoing channel, which is mainly used for the partial weig...
FourVector get_interaction_point() const
Get the interaction point.
Definition: action.cc:67
const ParticleList & outgoing_particles() const
Get the list of particles that resulted from the action.
Definition: action.h:245
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
double x3() const
Definition: fourvector.h:320
double x2() const
Definition: fourvector.h:316
double x0() const
Definition: fourvector.h:308
double x1() const
Definition: fourvector.h:312
std::pair< int, int > AZ
Pair of Atomic weight and number.
HepMC3::GenVertexPtr ip_
The interaction point.
int ncoll_
counter of binary collisions (e.g., where both incoming particles are from the beams.
bool full_event_
Whether the full event or only final-state particles are in the output.
HepMC3::GenParticlePtr make_gen(int pid, int status, const smash::FourVector &mom, double mass=-1)
Make an HepMC particle.
int ion_pdg(const AZ &az) const
Encode ion PDG.
int get_status(const ProcessType &t) const
Convert SMASH process type to HepMC status.
HepMC3::GenParticlePtr make_register(const ParticleData &p, int status=Status::fnal)
Find particle in mapping or generate it.
int ncoll_hard_
counter of hard binary collisions (e.g., where both incoming particles are from the beams.
void at_eventend(const Particles &particles, const int32_t event_number, const EventInfo &event) override
Add the final particles information of an event to the central vertex.
void clear()
Clear before an event.
IdMap map_
Mapping from ID to particle.
void at_interaction(const Action &action, const double density) override
Writes collisions to event.
HepMC3::GenParticlePtr find_or_make(const ParticleData &p, int status=Status::fnal, bool force_new=false)
Find particle in mapping or generate it.
HepMC3::GenEvent event_
The event.
void at_eventstart(const Particles &particles, const int event_number, const EventInfo &event) override
Add the initial particles information of an event to the central vertex.
HepMC3::GenHeavyIonPtr ion_
The heavy-ion structure.
CollCounter coll_
Collision counter.
HepMcInterface(const std::string &name, const bool full_event)
Create HepMC particle event in memory.
HepMC3::GenCrossSectionPtr xs_
Dummy cross-section.
Abstraction of generic output.
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:58
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
constexpr int p
Proton.
Definition: action.h:24
ProcessType
Process Types are used to identify the type of the process.
Definition: processbranch.h:25
@ Decay
resonance decay
static constexpr int LOutput
Structure to contain custom data for output.
bool empty_event
True if no collisions happened.