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