Version: SMASH-2.0
energymomentumtensor.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2015-2019
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 static constexpr int LTmn = LogArea::Tmn::id;
22 
24  using Eigen::Matrix4d;
25  using Eigen::Vector4d;
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  logg[LTmn].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  logg[LTmn].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  logg[LTmn].error(
89  "Landau frame is not defined.", " Eigen vector", u, " of ", A,
90  " is not time-like and",
91  " cannot be 4-velocity. This may happen if energy-momentum",
92  " tensor was constructed for a massless particle.");
93  u = FourVector(1., 0., 0., 0.);
94  }
95  return u;
96 }
97 
99  using Eigen::Matrix4d;
100  Matrix4d A, L, R;
101  // Energy-momentum tensor
102  // clang-format off
103  A << Tmn_[0], Tmn_[1], Tmn_[2], Tmn_[3],
104  Tmn_[1], Tmn_[4], Tmn_[5], Tmn_[6],
105  Tmn_[2], Tmn_[5], Tmn_[7], Tmn_[8],
106  Tmn_[3], Tmn_[6], Tmn_[8], Tmn_[9];
107  // clang-format on
108  // Compute Lorentz matrix of boost
109  const ThreeVector tmp = u.threevec() / (1.0 + u[0]);
110  // clang-format off
111  L << u[0], u[1], u[2], u[3],
112  u[1], u[1] * tmp.x1() + 1.0, u[2] * tmp.x1(), u[3] * tmp.x1(),
113  u[2], u[1] * tmp.x2(), u[2] * tmp.x2() + 1.0, u[3] * tmp.x2(),
114  u[3], u[1] * tmp.x3(), u[2] * tmp.x3(), u[3] * tmp.x3() + 1.0;
115  // clang-format on
116  // Boost
117  R = L * A * L;
118  // clang-format off
119  return EnergyMomentumTensor({R(0, 0), R(0, 1), R(0, 2), R(0, 3),
120  R(1, 1), R(1, 2), R(1, 3),
121  R(2, 2), R(2, 3),
122  R(3, 3)});
123  // clang-format on
124 }
125 
127  const ThreeVector tmp = mom.threevec() / mom[0];
128  Tmn_[0] += mom[0];
129  Tmn_[1] += mom[1];
130  Tmn_[2] += mom[2];
131  Tmn_[3] += mom[3];
132  Tmn_[4] += mom[1] * tmp.x1();
133  Tmn_[5] += mom[1] * tmp.x2();
134  Tmn_[6] += mom[1] * tmp.x3();
135  Tmn_[7] += mom[2] * tmp.x2();
136  Tmn_[8] += mom[2] * tmp.x3();
137  Tmn_[9] += mom[3] * tmp.x3();
138 }
139 
140 void EnergyMomentumTensor::add_particle(const ParticleData &p, double factor) {
141  add_particle(p.momentum() * factor);
142 }
143 
144 std::ostream &operator<<(std::ostream &out, const EnergyMomentumTensor &Tmn) {
145  out.width(12);
146  for (size_t mu = 0; mu < 4; mu++) {
147  for (size_t nu = 0; nu < 4; nu++) {
148  out << std::setprecision(3) << std::setw(12) << std::fixed
150  }
151  out << std::endl;
152  }
153  return out;
154 }
155 
156 } // namespace smash
smash
Definition: action.h:24
smash::EnergyMomentumTensor::Tmn_
tmn_type Tmn_
The internal storage of the components.
Definition: energymomentumtensor.h:143
smash::ParticleData
Definition: particledata.h:52
smash::ThreeVector::x3
double x3() const
Definition: threevector.h:173
smash::operator<<
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Definition: action.h:518
smash::EnergyMomentumTensor::tmn_index
static std::int8_t tmn_index(std::int8_t mu, std::int8_t nu)
Access the index of component .
Definition: energymomentumtensor.h:54
energymomentumtensor.h
smash::FourVector::sqr
double sqr() const
calculate the square of the vector (which is a scalar)
Definition: fourvector.h:450
smash::EnergyMomentumTensor::boosted
EnergyMomentumTensor boosted(const FourVector &u) const
Boost to a given 4-velocity.
Definition: energymomentumtensor.cc:98
smash::EnergyMomentumTensor::EnergyMomentumTensor
EnergyMomentumTensor()
Default constructor (nulls all components)
Definition: energymomentumtensor.h:34
smash::logg
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
smash::really_small
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
smash::ThreeVector
Definition: threevector.h:31
smash::LTmn
static constexpr int LTmn
Definition: energymomentumtensor.cc:21
ThermodynamicQuantity::Tmn
smash::ThreeVector::x1
double x1() const
Definition: threevector.h:165
R
#define R(x, n)
Definition: sha256.cc:55
smash::EnergyMomentumTensor::add_particle
void add_particle(const FourVector &mom)
Given momentum of the particle adds to the energy momentum tensor.
Definition: energymomentumtensor.cc:126
smash::EnergyMomentumTensor
Definition: energymomentumtensor.h:29
numerics.h
logging.h
smash::EnergyMomentumTensor::landau_frame_4velocity
FourVector landau_frame_4velocity() const
Find the Landau frame 4-velocity from energy-momentum tensor.
Definition: energymomentumtensor.cc:23
smash::FourVector
Definition: fourvector.h:33
smash::pdg::p
constexpr int p
Proton.
Definition: pdgcode_constants.h:28
smash::FourVector::threevec
ThreeVector threevec() const
Definition: fourvector.h:319
smash::ThreeVector::x2
double x2() const
Definition: threevector.h:169