Version: SMASH-1.5
energymomentumtensor.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2015-2018
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
11 
12 #include <iomanip>
13 #include <iostream>
14 
15 #include <Eigen/Dense> // NOLINT(build/include_order)
16 
17 #include "smash/logging.h"
18 #include "smash/numerics.h"
19 
20 namespace smash {
21 
23  using Eigen::Matrix4d;
24  using Eigen::Vector4d;
25  const auto &log = logger<LogArea::Tmn>();
26  /* We want to solve the generalized eigenvalue problem
27  T^{\mu \nu} h_{nu} = \lambda g^{\mu \nu} h_{nu}, or in the other way
28  T_{\mu}^{\nu} h_{nu} = \lambda h_{mu}. The eigenvector
29  corresponding to the largest (and the only positive) eigenvalue is
30  proportional to 4-velocity of the Landau frame.
31  Denote T^{\mu}_{\nu} as A and g^{\mu \nu} as B.
32  A is symmetric and positive semi-definite. B is symmetric.
33  A x = \lambda B x. I have to solve generalized eigenvalue
34  problem, because A can be not positively definite (e.g. if
35  energy-momentum tensor is computed for particles with momenta lying
36  in one plane). For positively definite A a more efficient solution
37  is possible, but I (oliiny) do not consider it, until it becomes
38  important for SMASH performance.
39  */
40  Matrix4d A;
41  // A = T_{\mu}^{\nu} = g_{\mu \mu'} T^{\mu' \nu}
42  // clang-format off
43  A << Tmn_[0], Tmn_[1], Tmn_[2], Tmn_[3],
44  -Tmn_[1], -Tmn_[4], -Tmn_[5], -Tmn_[6],
45  -Tmn_[2], -Tmn_[5], -Tmn_[7], -Tmn_[8],
46  -Tmn_[3], -Tmn_[6], -Tmn_[8], -Tmn_[9];
47  // clang-format on
48 
49  log.debug("Looking for Landau frame for T_{mu}^{nu} ", A);
50  Eigen::EigenSolver<Matrix4d> es(A);
51 
52 // Eigen values should be strictly real and non-negative.
53 
54 /* Here and further I assume that eigenvalues are given in
55  * descending order.
56  *
57  * \todo(oliiny): check Eigen documentation
58  * to make sure this is always true.*/
59 #ifndef NDEBUG
60  Vector4d eig_im = es.eigenvalues().imag();
61  Vector4d eig_re = es.eigenvalues().real();
62  for (size_t i = 0; i < 4; i++) {
63  assert(std::abs(eig_im(i)) < really_small);
64  if (i == 0) {
65  assert(eig_re(i) > -really_small);
66  } else {
67  assert(eig_re(i) < really_small);
68  }
69  }
70  // Make sure that 0th eigenvalue is really the largest one
71  assert(eig_re(0) >= eig_re(1));
72  assert(eig_re(0) >= eig_re(2));
73  assert(eig_re(0) >= eig_re(3));
74  log.debug("eigenvalues: ", eig_re);
75 #endif
76 
77  Vector4d tmp = es.eigenvectors().col(0).real();
78  // Choose sign so that zeroth component is positive
79  if (tmp(0) < 0.0) {
80  tmp = -tmp;
81  }
82 
83  FourVector u(tmp(0), tmp(1), tmp(2), tmp(3));
84  const double u_sqr = u.sqr();
85  if (u_sqr > really_small) {
86  u /= std::sqrt(u_sqr);
87  } else {
88  log.error("Landau frame is not defined.", " Eigen vector", u, " of ", A,
89  " is not time-like and",
90  " cannot be 4-velocity. This may happen if energy-momentum",
91  " tensor was constructed for a massless particle.");
92  u = FourVector(1., 0., 0., 0.);
93  }
94  return u;
95 }
96 
98  using Eigen::Matrix4d;
99  Matrix4d A, L, R;
100  // Energy-momentum tensor
101  // clang-format off
102  A << Tmn_[0], Tmn_[1], Tmn_[2], Tmn_[3],
103  Tmn_[1], Tmn_[4], Tmn_[5], Tmn_[6],
104  Tmn_[2], Tmn_[5], Tmn_[7], Tmn_[8],
105  Tmn_[3], Tmn_[6], Tmn_[8], Tmn_[9];
106  // clang-format on
107  // Compute Lorentz matrix of boost
108  const ThreeVector tmp = u.threevec() / (1.0 + u[0]);
109  // clang-format off
110  L << u[0], u[1], u[2], u[3],
111  u[1], u[1] * tmp.x1() + 1.0, u[2] * tmp.x1(), u[3] * tmp.x1(),
112  u[2], u[1] * tmp.x2(), u[2] * tmp.x2() + 1.0, u[3] * tmp.x2(),
113  u[3], u[1] * tmp.x3(), u[2] * tmp.x3(), u[3] * tmp.x3() + 1.0;
114  // clang-format on
115  // Boost
116  R = L * A * L;
117  // clang-format off
118  return EnergyMomentumTensor({R(0, 0), R(0, 1), R(0, 2), R(0, 3),
119  R(1, 1), R(1, 2), R(1, 3),
120  R(2, 2), R(2, 3),
121  R(3, 3)});
122  // clang-format on
123 }
124 
126  const ThreeVector tmp = mom.threevec() / mom[0];
127  Tmn_[0] += mom[0];
128  Tmn_[1] += mom[1];
129  Tmn_[2] += mom[2];
130  Tmn_[3] += mom[3];
131  Tmn_[4] += mom[1] * tmp.x1();
132  Tmn_[5] += mom[1] * tmp.x2();
133  Tmn_[6] += mom[1] * tmp.x3();
134  Tmn_[7] += mom[2] * tmp.x2();
135  Tmn_[8] += mom[2] * tmp.x3();
136  Tmn_[9] += mom[3] * tmp.x3();
137 }
138 
139 void EnergyMomentumTensor::add_particle(const ParticleData &p, double factor) {
140  add_particle(p.momentum() * factor);
141 }
142 
143 std::ostream &operator<<(std::ostream &out, const EnergyMomentumTensor &Tmn) {
144  out.width(12);
145  for (size_t mu = 0; mu < 4; mu++) {
146  for (size_t nu = 0; nu < 4; nu++) {
147  out << std::setprecision(3) << std::setw(12) << std::fixed
149  }
150  out << std::endl;
151  }
152  return out;
153 }
154 
155 } // namespace smash
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:30
double x3() const
Definition: threevector.h:163
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
static std::int8_t tmn_index(std::int8_t mu, std::int8_t nu)
Access the index of component .
double x1() const
Definition: threevector.h:155
EnergyMomentumTensor()
Default constructor (nulls all components)
EnergyMomentumTensor boosted(const FourVector &u) const
Boost to a given 4-velocity.
Generic numerical functions.
double sqr() const
calculate the square of the vector (which is a scalar)
Definition: fourvector.h:437
ThreeVector threevec() const
Definition: fourvector.h:306
FourVector landau_frame_4velocity() const
Find the Landau frame 4-velocity from energy-momentum tensor.
The EnergyMomentumTensor class represents a symmetric positive semi-definite energy-momentum tensor ...
constexpr int p
Proton.
void add_particle(const FourVector &mom)
Given momentum of the particle adds to the energy momentum tensor.
tmn_type Tmn_
The internal storage of the components.
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
Definition: action.h:457
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:32
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:52
double x2() const
Definition: threevector.h:159
Definition: action.h:24