GM2Calc 2.3.0
Loading...
Searching...
No Matches
gm2_eigen_utils.hpp
Go to the documentation of this file.
1// ====================================================================
2// This file is part of GM2Calc.
3//
4// GM2Calc is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published
6// by the Free Software Foundation, either version 3 of the License,
7// or (at your option) any later version.
8//
9// GM2Calc is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with GM2Calc. If not, see
16// <http://www.gnu.org/licenses/>.
17// ====================================================================
18
19#ifndef GM2_EIGEN_UTILS_HPP
20#define GM2_EIGEN_UTILS_HPP
21
22#include <algorithm>
23#include <limits>
24#include <Eigen/Core>
25
26namespace gm2calc {
27
28template <typename Derived>
29unsigned closest_index(double mass, const Eigen::ArrayBase<Derived>& v)
30{
31 unsigned pos = 0;
32 typename Derived::PlainObject tmp;
33 tmp.setConstant(mass);
34
35 (v - tmp).abs().minCoeff(&pos);
36
37 return pos;
38}
39
40template <class Derived>
41bool is_equal(const Eigen::ArrayBase<Derived>& a,
42 const Eigen::ArrayBase<Derived>& b,
43 double precision_goal)
44{
45 return (a - b).cwiseAbs().maxCoeff() < precision_goal;
46}
47
48template <class Derived>
49bool is_zero(const Eigen::ArrayBase<Derived>& a, double eps)
50{
51 return a.cwiseAbs().maxCoeff() < eps;
52}
53
54/**
55 * Normalize each element of the given real matrix to be within the
56 * interval [min, max]. Values < min are set to min. Values > max
57 * are set to max.
58 *
59 * @param m matrix
60 * @param min minimum
61 * @param max maximum
62 */
63template <int M, int N>
64void normalize_to_interval(Eigen::Matrix<double,M,N>& m, double min = -1., double max = 1.)
65{
66 auto data = m.data();
67 const auto size = m.size();
68
69 for (int i = 0; i < size; i++) {
70 if (data[i] < min) {
71 data[i] = min;
72 } else if (data[i] > max) {
73 data[i] = max;
74 }
75 }
76}
77
78/**
79 * The element of v, which is closest to mass, is moved to the
80 * position idx.
81 *
82 * @param idx new index of the mass eigenvalue
83 * @param mass mass to compare against
84 * @param v vector of masses
85 * @param z corresponding mixing matrix
86 */
87template <typename DerivedArray, typename DerivedMatrix>
88void move_goldstone_to(int idx, double mass, Eigen::ArrayBase<DerivedArray>& v,
89 Eigen::MatrixBase<DerivedMatrix>& z)
90{
91 int pos = closest_index(mass, v);
92 if (pos == idx) {
93 return;
94 }
95
96 const int sign = (idx - pos) < 0 ? -1 : 1;
97 int steps = std::abs(idx - pos);
98
99 // now we shuffle the states
100 while (steps--) {
101 const int new_pos = pos + sign;
102 v.row(new_pos).swap(v.row(pos));
103 z.row(new_pos).swap(z.row(pos));
104 pos = new_pos;
105 }
106}
107
108/**
109 * Returns all elements from src, which are not close to the elements
110 * in cmp. The returned vector will have the length (src.size() -
111 * cmp.size()).
112 *
113 * @param src source vector
114 * @param cmp vector with elements to compare against
115 * @return vector with elements of src not close to cmp
116 */
117template<class Real, int Nsrc, int Ncmp>
118Eigen::Array<Real,Nsrc - Ncmp,1> remove_if_equal(
119 const Eigen::Array<Real,Nsrc,1>& src,
120 const Eigen::Array<Real,Ncmp,1>& cmp)
121{
122 static_assert(Nsrc > Ncmp, "Error: size of source vector is not greater "
123 "than size of comparison vector.");
124
125 Eigen::Array<Real,Nsrc,1> non_equal(src);
126 Eigen::Array<Real,Nsrc - Ncmp,1> dst;
127
128 for (int i = 0; i < Ncmp; i++) {
129 const int idx = closest_index(cmp(i), non_equal);
130 non_equal(idx) = std::numeric_limits<double>::infinity();
131 }
132
133 std::remove_copy_if(non_equal.data(), non_equal.data() + Nsrc,
134 dst.data(), [] (auto x) { return !std::isfinite(x); });
135
136 return dst;
137}
138
139/**
140 * @brief reorders vector v according to ordering in vector v2
141 * @param v vector with elementes to be reordered
142 * @param v2 vector with reference ordering
143 */
144template<class Real, int N>
146 Eigen::Array<Real,N,1>& v,
147 const Eigen::Array<Real,N,1>& v2)
148{
149 Eigen::PermutationMatrix<N> p;
150 p.setIdentity();
151 std::sort(p.indices().data(), p.indices().data() + p.indices().size(),
152 [&v2] (int i, int j) { return std::abs(v2[i]) < std::abs(v2[j]); });
153
154#if EIGEN_VERSION_AT_LEAST(3,1,4)
155 v.matrix().transpose() *= p.inverse();
156#else
157 Eigen::Map<Eigen::Matrix<Real,N,1> >(v.data()).transpose() *= p.inverse();
158#endif
159}
160
161/**
162 * @brief reorders vector v according to ordering of diagonal elements in mass_matrix
163 * @param v vector with elementes to be reordered
164 * @param matrix matrix with diagonal elements with reference ordering
165 */
166template<class Derived>
168 Eigen::Array<double,Eigen::MatrixBase<Derived>::RowsAtCompileTime,1>& v,
169 const Eigen::MatrixBase<Derived>& matrix)
170{
171 reorder_vector(v, matrix.diagonal().array().eval());
172}
173
174template <typename Derived>
175void symmetrize(Eigen::MatrixBase<Derived>& m)
176{
177 static_assert(Eigen::MatrixBase<Derived>::RowsAtCompileTime ==
178 Eigen::MatrixBase<Derived>::ColsAtCompileTime,
179 "symmetrize is only defined for squared matrices");
180
181 for (int i = 0; i < Eigen::MatrixBase<Derived>::RowsAtCompileTime; i++) {
182 for (int k = 0; k < i; k++) {
183 m(i,k) = m(k,i);
184 }
185 }
186}
187
188} // namespace gm2calc
189
190#endif
double v
void move_goldstone_to(int idx, double mass, Eigen::ArrayBase< DerivedArray > &v, Eigen::MatrixBase< DerivedMatrix > &z)
The element of v, which is closest to mass, is moved to the position idx.
void normalize_to_interval(Eigen::Matrix< double, M, N > &m, double min=-1., double max=1.)
Normalize each element of the given real matrix to be within the interval [min, max].
bool is_zero(const Eigen::ArrayBase< Derived > &a, double eps)
unsigned closest_index(double mass, const Eigen::ArrayBase< Derived > &v)
int sign(double x) noexcept
returns sign of real number
bool is_equal(const Eigen::ArrayBase< Derived > &a, const Eigen::ArrayBase< Derived > &b, double precision_goal)
void reorder_vector(Eigen::Array< Real, N, 1 > &v, const Eigen::Array< Real, N, 1 > &v2)
reorders vector v according to ordering in vector v2
void symmetrize(Eigen::MatrixBase< Derived > &m)
Eigen::Array< Real, Nsrc - Ncmp, 1 > remove_if_equal(const Eigen::Array< Real, Nsrc, 1 > &src, const Eigen::Array< Real, Ncmp, 1 > &cmp)
Returns all elements from src, which are not close to the elements in cmp.