flexiblesusy is hosted by Hepforge, IPPP Durham
FlexibleSUSY
eigen_utils.hpp
Go to the documentation of this file.
1// ====================================================================
2// This file is part of FlexibleSUSY.
3//
4// FlexibleSUSY 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// FlexibleSUSY 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 FlexibleSUSY. If not, see
16// <http://www.gnu.org/licenses/>.
17// ====================================================================
18
19#ifndef EIGEN_UTILS_H
20#define EIGEN_UTILS_H
21
22#include <Eigen/Core>
23#include <algorithm>
24#include <cassert>
25#include <cmath>
26#include <complex>
27#include <limits>
28
29namespace flexiblesusy {
30
31template <typename Derived>
32int closest_index(double mass, const Eigen::ArrayBase<Derived>& v)
33{
34 int pos;
35 typename Derived::PlainObject tmp;
36 tmp.setConstant(mass);
37
38 (v - tmp).abs().minCoeff(&pos);
39
40 return pos;
41}
42
43template <class BinaryOp, class Derived>
44Derived binary_map(
45 const Eigen::DenseBase<Derived>& a, const Eigen::DenseBase<Derived>& b, BinaryOp op)
46{
47 typename Derived::PlainObject result(a.rows(), b.cols());
48
49 assert(a.rows() == b.rows());
50 assert(a.cols() == b.cols());
51
52 for (int k = 0; k < a.cols(); k++)
53 for (int i = 0; i < a.rows(); i++)
54 result(i,k) = op(a(i,k), b(i,k));
55
56 return result;
57}
58
66template <class Derived>
67Derived div_safe(
68 const Eigen::DenseBase<Derived>& a, const Eigen::DenseBase<Derived>& b)
69{
70 using Scalar = typename Derived::Scalar;
71
72 return binary_map(a, b, [](Scalar x, Scalar y){
73 const Scalar q = x / y;
74 return std::isfinite(q) ? q : Scalar{};
75 });
76}
77
88template <class Derived>
89bool is_equal_rel(const Eigen::PlainObjectBase<Derived>& a,
90 const Eigen::PlainObjectBase<Derived>& b, double eps)
91{
92 if (a.rows() != b.rows() || a.cols() != b.cols()) {
93 return false;
94 }
95
96 for (decltype(a.size()) i = 0; i < a.size(); i++) {
97 const auto ai = a.data()[i];
98 const auto bi = b.data()[i];
99 const auto max = std::max(std::abs(ai), std::abs(bi));
100 if (std::abs(ai - bi) >= eps*(1 + max)) {
101 return false;
102 }
103 }
104
105 return true;
106}
107
117template <typename DerivedArray, typename DerivedMatrix>
118void move_goldstone_to(int idx, double mass, Eigen::ArrayBase<DerivedArray>& v,
119 Eigen::MatrixBase<DerivedMatrix>& z)
120{
121 int pos = closest_index(mass, v);
122 if (pos == idx)
123 return;
124
125 const int sign = (idx - pos) < 0 ? -1 : 1;
126 int steps = std::abs(idx - pos);
127
128 // now we shuffle the states
129 while (steps--) {
130 const int new_pos = pos + sign;
131 v.row(new_pos).swap(v.row(pos));
132 z.row(new_pos).swap(z.row(pos));
133 pos = new_pos;
134 }
135}
136
146template <int M, int N>
147void normalize_to_interval(Eigen::Matrix<double,M,N>& m, double min = -1., double max = 1.)
148{
149 auto data = m.data();
150 const auto size = m.size();
151
152 for (int i = 0; i < size; i++) {
153 if (data[i] < min)
154 data[i] = min;
155 else if (data[i] > max)
156 data[i] = max;
157 }
158}
159
169template <int M, int N>
170void normalize_to_interval(Eigen::Matrix<std::complex<double>,M,N>& m, double max_mag = 1.)
171{
172 auto data = m.data();
173 const auto size = m.size();
174
175 for (int i = 0; i < size; i++) {
176 if (std::abs(data[i]) > max_mag)
177 data[i] = std::polar(max_mag, std::arg(data[i]));
178 }
179}
180
181namespace {
182template <class T>
184 bool operator()(T x) const noexcept { return !std::isfinite(x); }
185};
186} // anonymous namespace
187
197template<class Real, int Nsrc, int Ncmp>
198Eigen::Array<Real,Nsrc - Ncmp,1> remove_if_equal(
199 const Eigen::Array<Real,Nsrc,1>& src,
200 const Eigen::Array<Real,Ncmp,1>& cmp)
201{
202 Eigen::Array<Real,Nsrc,1> non_equal(src);
203 Eigen::Array<Real,Nsrc - Ncmp,1> dst;
204
205 for (int i = 0; i < Ncmp; i++) {
206 const int idx = closest_index(cmp(i), non_equal);
207 non_equal(idx) = std::numeric_limits<double>::infinity();
208 }
209
210 std::remove_copy_if(non_equal.data(), non_equal.data() + Nsrc,
211 dst.data(), Is_not_finite<Real>());
212
213 return dst;
214}
215
221template<class Real, int N>
223 Eigen::Array<Real,N,1>& v,
224 const Eigen::Array<Real,N,1>& v2)
225{
226 Eigen::PermutationMatrix<N> p;
227 p.setIdentity();
228 std::sort(p.indices().data(), p.indices().data() + p.indices().size(),
229 [&v2] (int i, int j) { return v2[i] < v2[j]; });
230
231#if EIGEN_VERSION_AT_LEAST(3,1,4)
232 v.matrix().transpose() *= p.inverse();
233#else
234 Eigen::Map<Eigen::Matrix<Real,N,1> >(v.data()).transpose() *= p.inverse();
235#endif
236}
237
245template<class Derived>
247 Eigen::Array<double,Eigen::MatrixBase<Derived>::RowsAtCompileTime,1>& v,
248 const Eigen::MatrixBase<Derived>& matrix)
249{
250 reorder_vector(v, matrix.diagonal().array().cwiseAbs().eval());
251}
252
254template<int N>
255void sort(Eigen::Array<double, N, 1>& v)
256{
257 std::sort(v.data(), v.data() + v.size(),
258 [] (double a, double b) { return std::abs(a) < std::abs(b); });
259}
260
261} // namespace flexiblesusy
262
263#endif
#define M(i)
Definition: defs.h:629
void move_goldstone_to(int idx, double mass, Eigen::ArrayBase< DerivedArray > &v, Eigen::MatrixBase< DerivedMatrix > &z)
void normalize_to_interval(Eigen::Matrix< double, M, N > &m, double min=-1., double max=1.)
double Real
Definition: mathdefs.hpp:12
constexpr T arg(const Complex< T > &z) noexcept
Definition: complex.hpp:42
T sign(T x)
Definition: mathdefs.hpp:65
Derived binary_map(const Eigen::DenseBase< Derived > &a, const Eigen::DenseBase< Derived > &b, BinaryOp op)
Definition: eigen_utils.hpp:44
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
int closest_index(double mass, const Eigen::ArrayBase< Derived > &v)
Definition: eigen_utils.hpp:32
bool is_equal_rel(const Eigen::PlainObjectBase< Derived > &a, const Eigen::PlainObjectBase< Derived > &b, double eps)
Definition: eigen_utils.hpp:89
Derived div_safe(const Eigen::DenseBase< Derived > &a, const Eigen::DenseBase< Derived > &b)
Definition: eigen_utils.hpp:67
Eigen::Array< Real, Nsrc - Ncmp, 1 > remove_if_equal(const Eigen::Array< Real, Nsrc, 1 > &src, const Eigen::Array< Real, Ncmp, 1 > &cmp)
void sort(Eigen::Array< double, N, 1 > &v)
sorts an Eigen array
id steps()
data
Definition: scan_HSSUSY.m:46