Version: SMASH-1.5
propagation.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2013-2018
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/propagation.h"
11 
12 #include "smash/boxmodus.h"
13 #include "smash/collidermodus.h"
14 #include "smash/listmodus.h"
15 #include "smash/logging.h"
16 #include "smash/spheremodus.h"
17 
18 namespace smash {
19 
20 double calc_hubble(double time, const ExpansionProperties &metric) {
21  double h; // Hubble parameter
22 
23  switch (metric.mode_) {
25  h = 0.;
26  break;
28  h = metric.b_ / (2 * (metric.b_ * time + 1));
29  break;
31  h = 2 * metric.b_ / (3 * (metric.b_ * time + 1));
32  break;
34  h = metric.b_ * time;
35  break;
36  default:
37  h = 0.;
38  }
39 
40  return h;
41 }
42 
43 double propagate_straight_line(Particles *particles, double to_time,
44  const std::vector<FourVector> &beam_momentum) {
45  const auto &log = logger<LogArea::Propagation>();
46  bool negative_dt_error = false;
47  double dt = 0.0;
48  for (ParticleData &data : *particles) {
49  const double t0 = data.position().x0();
50  dt = to_time - t0;
51  if (dt < 0.0 && !negative_dt_error) {
52  // Print error message once, not for every particle
53  negative_dt_error = true;
54  log.error("propagate_straight_line - negative dt = ", dt);
55  }
56  assert(dt >= 0.0);
57  /* "Frozen Fermi motion": Fermi momenta are only used for collisions,
58  * but not for propagation. This is done to avoid nucleus flying apart
59  * even if potentials are off. Initial nucleons before the first collision
60  * are propagated only according to beam momentum.
61  * Initial nucleons are distinguished by data.id() < the size of
62  * beam_momentum, which is by default zero except for the collider modus
63  * with the fermi motion == frozen.
64  * todo(m. mayer): improve this condition (see comment #11 issue #4213)*/
65  assert(data.id() >= 0);
66  const bool avoid_fermi_motion =
67  (static_cast<uint64_t>(data.id()) <
68  static_cast<uint64_t>(beam_momentum.size())) &&
69  (data.get_history().collisions_per_particle == 0);
70  ThreeVector v;
71  if (avoid_fermi_motion) {
72  const FourVector vbeam = beam_momentum[data.id()];
73  v = vbeam.velocity();
74  } else {
75  v = data.velocity();
76  }
77  const FourVector distance = FourVector(0.0, v * dt);
78  log.debug("Particle ", data, " motion: ", distance);
79  FourVector position = data.position() + distance;
80  position.set_x0(to_time);
81  data.set_4position(position);
82  }
83  return dt;
84 }
85 
86 void expand_space_time(Particles *particles,
87  const ExperimentParameters &parameters,
88  const ExpansionProperties &metric) {
89  const auto &log = logger<LogArea::Propagation>();
90  const double dt = parameters.labclock.timestep_duration();
91  for (ParticleData &data : *particles) {
92  // Momentum and position modification to ensure appropriate expansion
93  const double h = calc_hubble(parameters.labclock.current_time(), metric);
94  FourVector delta_mom = FourVector(0.0, h * data.momentum().threevec() * dt);
95  FourVector expan_dist =
96  FourVector(0.0, h * data.position().threevec() * dt);
97 
98  log.debug("Particle ", data, " expansion motion: ", expan_dist);
99  // New position and momentum
100  FourVector position = data.position() + expan_dist;
101  FourVector momentum = data.momentum() - delta_mom;
102 
103  // set the new momentum and position variables
104  data.set_4position(position);
105  data.set_4momentum(momentum);
106  // force the on shell condition to ensure correct energy
107  data.set_4momentum(data.pole_mass(), data.momentum().threevec());
108  }
109 }
110 
112  Particles *particles, double dt, const Potentials &pot,
113  RectangularLattice<std::pair<ThreeVector, ThreeVector>> *FB_lat,
114  RectangularLattice<std::pair<ThreeVector, ThreeVector>> *FI3_lat) {
115  // Copy particles before propagation to calculate potentials from them
116  const ParticleList plist = particles->copy_to_vector();
117 
118  const auto &log = logger<LogArea::Propagation>();
119  bool possibly_use_lattice =
120  (pot.use_skyrme() ? (FB_lat != nullptr) : true) &&
121  (pot.use_symmetry() ? (FI3_lat != nullptr) : true);
122  std::pair<ThreeVector, ThreeVector> FB, FI3;
123  double min_time_scale = std::numeric_limits<double>::infinity();
124 
125  for (ParticleData &data : *particles) {
126  // Only baryons will be affected by the potentials
127  if (!data.is_baryon()) {
128  continue;
129  }
130  const auto scale = pot.force_scale(data.type());
131  const ThreeVector r = data.position().threevec();
132  /* Lattices can be used for calculation if 1-2 are fulfilled:
133  * 1) Required lattices are not nullptr - possibly_use_lattice
134  * 2) r is not out of required lattices */
135  const bool use_lattice =
136  possibly_use_lattice &&
137  (pot.use_skyrme() ? FB_lat->value_at(r, FB) : true) &&
138  (pot.use_symmetry() ? FI3_lat->value_at(r, FI3) : true);
139  if (!pot.use_skyrme()) {
140  FB = std::make_pair(ThreeVector(0., 0., 0.), ThreeVector(0., 0., 0.));
141  }
142  if (!pot.use_symmetry()) {
143  FI3 = std::make_pair(ThreeVector(0., 0., 0.), ThreeVector(0., 0., 0.));
144  }
145  if (!use_lattice) {
146  const auto tmp = pot.all_forces(r, plist);
147  FB = std::make_pair(std::get<0>(tmp), std::get<1>(tmp));
148  FI3 = std::make_pair(std::get<2>(tmp), std::get<3>(tmp));
149  }
150  const ThreeVector Force =
151  scale.first *
152  (FB.first + data.momentum().velocity().CrossProduct(FB.second)) +
153  scale.second * data.type().isospin3_rel() *
154  (FI3.first + data.momentum().velocity().CrossProduct(FI3.second));
155  log.debug("Update momenta: F [GeV/fm] = ", Force);
156  data.set_4momentum(data.effective_mass(),
157  data.momentum().threevec() + Force * dt);
158 
159  // calculate the time scale of the change in momentum
160  const double Force_abs = Force.abs();
161  if (Force_abs < really_small) {
162  continue;
163  }
164  const double time_scale = data.momentum().x0() / Force_abs;
165  if (time_scale < min_time_scale) {
166  min_time_scale = time_scale;
167  }
168  }
169 
170  // warn if the time step is too big
171  constexpr double safety_factor = 0.1;
172  if (dt > safety_factor * min_time_scale) {
173  log.warn() << "The time step size is too large for an accurate propagation "
174  << "with potentials. Maximum safe value: "
175  << safety_factor * min_time_scale << " fm/c.";
176  }
177 }
178 
179 } // namespace smash
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:30
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
double propagate_straight_line(Particles *particles, double to_time, const std::vector< FourVector > &beam_momentum)
Propagates the positions of all particles on a straight line to a given moment.
Definition: propagation.cc:43
ThreeVector velocity() const
Get the velocity (3-vector divided by zero component).
Definition: fourvector.h:310
double timestep_duration() const
Definition: clock.h:128
void update_momenta(Particles *particles, double dt, const Potentials &pot, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *FB_lat, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *FI3_lat)
Updates the momenta of all particles at the current time step according to the equations of motion: ...
Definition: propagation.cc:111
Clock labclock
System clock (for simulation time keeping in the computational frame)
bool use_skyrme() const
Definition: potentials.h:164
std::pair< double, int > force_scale(const ParticleType &data) const
Evaluates the scaling factor of the forces acting on the particles.
Definition: potentials.cc:135
double abs() const
Definition: threevector.h:251
A container class to hold all the arrays on the lattice and access them.
Definition: lattice.h:46
void set_x0(double t)
Definition: fourvector.h:292
ParticleList copy_to_vector() const
Definition: particles.h:44
std::tuple< ThreeVector, ThreeVector, ThreeVector, ThreeVector > all_forces(const ThreeVector &r, const ParticleList &plist) const
Evaluates the electrical and magnetic components of the forces at point r.
Definition: potentials.cc:181
ExpansionMode mode_
Type of metric used.
Definition: propagation.h:27
bool use_symmetry() const
Definition: potentials.h:166
A class that stores parameters of potentials, calculates potentials and their gradients.
Definition: potentials.h:31
void expand_space_time(Particles *particles, const ExperimentParameters &parameters, const ExpansionProperties &metric)
Modifies positions and momentum of all particles to account for space-time deformation.
Definition: propagation.cc:86
double calc_hubble(double time, const ExpansionProperties &metric)
Calculate the Hubble parameter , which describes how large the expansion flow is. ...
Definition: propagation.cc:20
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
double current_time() const
Definition: clock.h:110
double b_
Expansion parameter in the metric (faster expansion for larger values)
Definition: propagation.h:29
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:32
Struct containing the type of the metric and the expansion parameter of the metric.
Definition: propagation.h:25
Helper structure for Experiment.
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:52
Definition: action.h:24