Version: SMASH-2.2
propagation.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2013-2021
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 static constexpr int LPropagation = LogArea::Propagation::id;
20 
21 double calc_hubble(double time, const ExpansionProperties &metric) {
22  double h; // Hubble parameter
23 
24  switch (metric.mode_) {
26  h = 0.;
27  break;
29  h = metric.b_ / (2 * (metric.b_ * time + 1));
30  break;
32  h = 2 * metric.b_ / (3 * (metric.b_ * time + 1));
33  break;
35  h = metric.b_ * time;
36  break;
37  default:
38  h = 0.;
39  }
40 
41  return h;
42 }
43 
44 double propagate_straight_line(Particles *particles, double to_time,
45  const std::vector<FourVector> &beam_momentum) {
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  logg[LPropagation].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  logg[LPropagation].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 double dt = parameters.labclock->timestep_duration();
90  for (ParticleData &data : *particles) {
91  // Momentum and position modification to ensure appropriate expansion
92  const double h = calc_hubble(parameters.labclock->current_time(), metric);
93  FourVector delta_mom = FourVector(0.0, h * data.momentum().threevec() * dt);
94  FourVector expan_dist =
95  FourVector(0.0, h * data.position().threevec() * dt);
96 
97  logg[LPropagation].debug("Particle ", data,
98  " 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  std::vector<Particles> &ensembles, double dt, const Potentials &pot,
113  RectangularLattice<std::pair<ThreeVector, ThreeVector>> *FB_lat,
114  RectangularLattice<std::pair<ThreeVector, ThreeVector>> *FI3_lat,
115  RectangularLattice<std::pair<ThreeVector, ThreeVector>> *EM_lat) {
116  // Copy particles from ALL ensembles to a single list before propagation
117  // and calculate potentials from this list
118  ParticleList plist;
119  for (Particles &particles : ensembles) {
120  const ParticleList tmp = particles.copy_to_vector();
121  plist.insert(plist.end(), tmp.begin(), tmp.end());
122  }
123 
124  bool possibly_use_lattice =
125  (pot.use_skyrme() ? (FB_lat != nullptr) : true) &&
126  (pot.use_vdf() ? (FB_lat != nullptr) : true) &&
127  (pot.use_symmetry() ? (FI3_lat != nullptr) : true);
128  std::pair<ThreeVector, ThreeVector> FB, FI3, EM_fields;
129  double min_time_scale = std::numeric_limits<double>::infinity();
130 
131  for (Particles &particles : ensembles) {
132  for (ParticleData &data : particles) {
133  // Only baryons and nuclei will be affected by the potentials
134  if (!(data.is_baryon() || data.is_nucleus())) {
135  continue;
136  }
137  const auto scale = pot.force_scale(data.type());
138  const ThreeVector r = data.position().threevec();
139  /* Lattices can be used for calculation if 1-2 are fulfilled:
140  * 1) Required lattices are not nullptr - possibly_use_lattice
141  * 2) r is not out of required lattices */
142  const bool use_lattice =
143  possibly_use_lattice &&
144  (pot.use_skyrme() ? FB_lat->value_at(r, FB) : true) &&
145  (pot.use_vdf() ? FB_lat->value_at(r, FB) : true) &&
146  (pot.use_symmetry() ? FI3_lat->value_at(r, FI3) : true);
147  if (!pot.use_skyrme() && !pot.use_vdf()) {
148  FB = std::make_pair(ThreeVector(0., 0., 0.), ThreeVector(0., 0., 0.));
149  }
150  if (!pot.use_symmetry()) {
151  FI3 = std::make_pair(ThreeVector(0., 0., 0.), ThreeVector(0., 0., 0.));
152  }
153  if (!use_lattice) {
154  const auto tmp = pot.all_forces(r, plist);
155  FB = std::make_pair(std::get<0>(tmp), std::get<1>(tmp));
156  FI3 = std::make_pair(std::get<2>(tmp), std::get<3>(tmp));
157  }
158  ThreeVector Force =
159  scale.first *
160  (FB.first + data.momentum().velocity().cross_product(FB.second)) +
161  scale.second * data.type().isospin3_rel() *
162  (FI3.first +
163  data.momentum().velocity().cross_product(FI3.second));
164  // Potentially add Lorentz force
165  if (pot.use_coulomb() && EM_lat->value_at(r, EM_fields)) {
166  // factor hbar*c to convert fields from 1/fm^2 to GeV/fm
167  Force += hbarc * data.type().charge() * elementary_charge *
168  (EM_fields.first +
169  data.momentum().velocity().cross_product(EM_fields.second));
170  }
171  logg[LPropagation].debug("Update momenta: F [GeV/fm] = ", Force);
172  data.set_4momentum(data.effective_mass(),
173  data.momentum().threevec() + Force * dt);
174 
175  // calculate the time scale of the change in momentum
176  const double Force_abs = Force.abs();
177  if (Force_abs < really_small) {
178  continue;
179  }
180  const double time_scale = data.momentum().x0() / Force_abs;
181  if (time_scale < min_time_scale) {
182  min_time_scale = time_scale;
183  }
184  }
185  }
186  // warn if the time step is too big
187  constexpr double safety_factor = 0.1;
188  if (dt > safety_factor * min_time_scale) {
189  logg[LPropagation].warn()
190  << "The time step size is too large for an accurate propagation "
191  << "with potentials. Maximum safe value: "
192  << safety_factor * min_time_scale << " fm/c.\n"
193  << "In case of Triangular or Discrete smearing you may additionally "
194  << "need to increase the number of ensembles or testparticles.";
195  }
196 }
197 
198 } // namespace smash
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
ThreeVector velocity() const
Get the velocity (3-vector divided by zero component).
Definition: fourvector.h:328
void set_x0(double t)
Definition: fourvector.h:310
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
A class that stores parameters of potentials, calculates potentials and their gradients.
Definition: potentials.h:32
virtual bool use_symmetry() const
Definition: potentials.h:307
virtual bool use_skyrme() const
Definition: potentials.h:305
virtual bool use_coulomb() const
Definition: potentials.h:309
static std::pair< double, int > force_scale(const ParticleType &data)
Evaluates the scaling factor of the forces acting on the particles.
Definition: potentials.cc:318
virtual std::tuple< ThreeVector, ThreeVector, ThreeVector, ThreeVector > all_forces(const ThreeVector &r, const ParticleList &plist) const
Evaluates the electric and magnetic components of the forces at point r.
Definition: potentials.cc:434
virtual bool use_vdf() const
Definition: potentials.h:321
A container class to hold all the arrays on the lattice and access them.
Definition: lattice.h:47
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
double abs() const
Definition: threevector.h:261
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
Definition: action.h:24
void update_momenta(std::vector< Particles > &particles, double dt, const Potentials &pot, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *FB_lat, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *FI3_lat, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *EM_lat)
Updates the momenta of all particles at the current time step according to the equations of motion:
Definition: propagation.cc:111
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 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:44
constexpr double hbarc
GeV <-> fm conversion factor.
Definition: constants.h:25
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
double calc_hubble(double time, const ExpansionProperties &metric)
Calculate the Hubble parameter , which describes how large the expansion flow is.
Definition: propagation.cc:21
static constexpr int LPropagation
Definition: propagation.cc:19
const double elementary_charge
Elementary electric charge in natural units, approximately 0.3.
Definition: constants.h:104
Struct containing the type of the metric and the expansion parameter of the metric.
Definition: propagation.h:26
double b_
Expansion parameter in the metric (faster expansion for larger values)
Definition: propagation.h:30
ExpansionMode mode_
Type of metric used.
Definition: propagation.h:28
Helper structure for Experiment.
std::unique_ptr< Clock > labclock
System clock (for simulation time keeping in the computational frame)