Version: SMASH-3.3
hypersurfacecrossingfinder.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2019-2020,2022-2025
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
11 
13 #include "smash/logging.h"
14 
15 namespace smash {
16 static constexpr int LHyperSurfaceCrossing = LogArea::HyperSurfaceCrossing::id;
17 
19  const ParticleList &plist, double dt, const double,
20  const std::vector<FourVector> &beam_momentum) const {
21  ActionList actions;
22 
23  for (const ParticleData &p : plist) {
24  ParticleData pdata_before_propagation = p;
25  ParticleData pdata_after_propagation = p; // Will receive updated position
26  double t0 = p.position().x0();
27  double t_end = t0 + dt; // Time at the end of timestep
28 
29  // We don't want to remove particles before the nuclei have interacted
30  // because those would not yet be part of the newly-created medium.
31  if (t_end < 0.0) {
32  continue;
33  }
34  if (p.is_core()) {
35  continue;
36  }
37 
38  // For frozen Fermi motion:
39  // Fermi momenta are only applied if particles interact. The particle
40  // properties p.velocity() and p.momentum() already contain the values
41  // corrected by Fermi motion, but those particles that have not yet
42  // interacted are propagated along the beam-axis with v = (0, 0, beam_v)
43  // (and not with p.velocity()).
44  // To identify the corresponding hypersurface crossings the finding for
45  // those paricles without prior interactions has to be performed with
46  // v = vbeam instead of p.velocity().
47  // Note: The beam_momentum vector is empty in case frozen Fermi motion is
48  // not applied.
49  const bool no_prior_interactions =
50  (static_cast<uint64_t>(p.id()) < // particle from
51  static_cast<uint64_t>(beam_momentum.size())) && // initial nucleus
52  (p.get_history().collisions_per_particle == 0);
53  ThreeVector v;
54  if (no_prior_interactions) {
55  const FourVector vbeam = beam_momentum[p.id()];
56  v = vbeam.velocity();
57  } else {
58  v = p.velocity();
59  }
60 
61  // propagate particles to position where they would be at the end of the
62  // time step (after dt)
63  const FourVector distance = FourVector(0.0, v * dt);
64  FourVector position = p.position() + distance;
65  position.set_x0(t_end);
66  // update coordinates to the position corresponding to t_end
67  pdata_after_propagation.set_4position(position);
68 
69  bool hypersurface_is_crossed = crosses_hypersurface(
70  pdata_before_propagation, pdata_after_propagation, prop_time_);
71 
72  /*
73  If rapidity or transverse momentum cut is to be employed; check if
74  particles are within the relevant region
75  Implementation explanation: The default for both cuts is 0.0, as a cut at
76  0 implies that not a single particle contributes to the initial
77  conditions. If the user specifies a value of 0.0 in the config, SMASH
78  crashes with a corresponding error message. The same applies to negtive
79  values.
80  */
81  bool is_within_y_cut = true;
82  // Check whether particle is in desired rapidity range
83  if (rap_cut_ > 0.0) {
84  const double rapidity = p.rapidity();
85  if (std::fabs(rapidity) > rap_cut_) {
86  is_within_y_cut = false;
87  }
88  }
89 
90  bool is_within_pT_cut = true;
91  // Check whether particle is in desired pT range
92  if (pT_cut_ > 0.0) {
93  const double transverse_momentum =
94  std::sqrt(p.momentum().x1() * p.momentum().x1() +
95  p.momentum().x2() * p.momentum().x2());
96  if (transverse_momentum > pT_cut_) {
97  is_within_pT_cut = false;
98  }
99  }
100 
101  if (hypersurface_is_crossed && is_within_y_cut && is_within_pT_cut) {
102  // Get exact coordinates where hypersurface is crossed
103  FourVector crossing_position = coordinates_on_hypersurface(
104  pdata_before_propagation, pdata_after_propagation, prop_time_);
105 
106  double time_until_crossing = crossing_position[0] - t0;
107 
108  ParticleData outgoing_particle(p);
109  outgoing_particle.set_4position(crossing_position);
110  ActionPtr action = std::make_unique<FluidizationAction>(
111  p, outgoing_particle, time_until_crossing);
112  actions.emplace_back(std::move(action));
113  }
114  }
115  return actions;
116 }
117 
119  ParticleData &pdata_before_propagation,
120  ParticleData &pdata_after_propagation, const double tau) const {
121  bool hypersurface_is_crossed = false;
122  const bool t_greater_z_before_prop =
123  (std::fabs(pdata_before_propagation.position().x0()) >
124  std::fabs(pdata_before_propagation.position().x3())
125  ? true
126  : false);
127  const bool t_greater_z_after_prop =
128  (std::fabs(pdata_after_propagation.position().x0()) >
129  std::fabs(pdata_after_propagation.position().x3())
130  ? true
131  : false);
132 
133  if (t_greater_z_before_prop && t_greater_z_after_prop) {
134  // proper time before and after propagation
135  const double tau_before = pdata_before_propagation.hyperbolic_time();
136  const double tau_after = pdata_after_propagation.hyperbolic_time();
137 
138  if (tau_before <= tau && tau <= tau_after) {
139  hypersurface_is_crossed = true;
140  }
141  } else if (!t_greater_z_before_prop && t_greater_z_after_prop) {
142  // proper time after propagation
143  const double tau_after = pdata_after_propagation.hyperbolic_time();
144  if (tau_after >= tau) {
145  hypersurface_is_crossed = true;
146  }
147  }
148 
149  return hypersurface_is_crossed;
150 }
151 
153  ParticleData &pdata_before_propagation,
154  ParticleData &pdata_after_propagation, const double tau) const {
155  // find t and z at start of propagation
156  const double t1 = pdata_before_propagation.position().x0();
157  const double z1 = pdata_before_propagation.position().x3();
158 
159  // find t and z after propagation
160  const double t2 = pdata_after_propagation.position().x0();
161  const double z2 = pdata_after_propagation.position().x3();
162 
163  // find slope and intercept of linear function that describes propagation on
164  // straight line
165  const double m = (z2 - z1) / (t2 - t1);
166  const double n = z1 - m * t1;
167 
168  // The equation to solve is a quadratic equation which provides two solutions,
169  // the latter is usually out of the t-interval we are looking at.
170  const double sol1 = n * m / (1 - m * m) +
171  std::sqrt((1 - m * m) * tau * tau + n * n) / (1 - m * m);
172  [[maybe_unused]] const double sol2 = // only used in DEBUG output
173  n * m / (1 - m * m) -
174  std::sqrt((1 - m * m) * tau * tau + n * n) / (1 - m * m);
175 
176  assert((sol1 >= t1 && sol1 <= t2));
177  assert(!(sol2 >= t1 && sol2 <= t2));
178 
179  // Propagate to point where hypersurface is crossed
180  const ThreeVector v = pdata_before_propagation.velocity();
181  const FourVector distance = FourVector(0.0, v * (sol1 - t1));
182  FourVector crossing_position = pdata_before_propagation.position() + distance;
183  crossing_position.set_x0(sol1);
184 
185  return crossing_position;
186 }
187 
189  const size_t number_of_particles, bool impose_kinematic_cut) {
190  if (number_of_particles != 0 && !impose_kinematic_cut) {
192  "End time might be too small for initial conditions output. "
193  "Hypersurface has not yet been crossed by ",
194  number_of_particles, " particle(s).");
195  }
196 }
197 
198 } // namespace smash
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
double x3() const
Definition: fourvector.h:325
double x0() const
Definition: fourvector.h:313
ThreeVector velocity() const
Get the velocity (3-vector divided by zero component).
Definition: fourvector.h:333
void set_x0(double t)
Definition: fourvector.h:315
const double prop_time_
Proper time of the hypersurface in fm.
FourVector coordinates_on_hypersurface(ParticleData &pdata_before_propagation, ParticleData &pdata_after_propagation, const double tau) const
Find the coordinates where particle crosses hypersurface.
const double rap_cut_
Rapidity (momentum space) cut for the particles contributing to the initial conditions for hydrodynam...
static void warn_if_some_particles_did_not_cross(const size_t number_of_particles, bool impose_kinematic_cut)
Gives a warning if number_of_particles is not 0 and there are no kinematic cuts.
const double pT_cut_
Transverse momentum cut for the particles contributing to the initial conditions for hydrodynamics.
ActionList find_actions_in_cell(const ParticleList &plist, double dt, const double, const std::vector< FourVector > &beam_momentum) const override
Find the next hypersurface crossings for each particle that occur within the timestepless propagation...
bool crosses_hypersurface(ParticleData &pdata_before_propagation, ParticleData &pdata_after_propagation, const double tau) const
Determine whether particle crosses hypersurface within next timestep during propagation.
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:59
void set_4position(const FourVector &pos)
Set the particle's 4-position directly.
Definition: particledata.h:222
double hyperbolic_time() const
Particle (hyperbolic time)
Definition: particledata.h:404
ThreeVector velocity() const
Get the velocity 3-vector.
Definition: particledata.h:321
const FourVector & position() const
Get the particle's position in Minkowski space.
Definition: particledata.h:217
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:40
constexpr int p
Proton.
constexpr int n
Neutron.
Definition: action.h:24
static constexpr int LHyperSurfaceCrossing