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