flexiblesusy is hosted by Hepforge, IPPP Durham
FlexibleSUSY
rk.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
28#ifndef RK_H
29#define RK_H
30
31#include <algorithm>
32#include <cmath>
33
34#include "logger.hpp"
35#include "error.hpp"
36
37namespace flexiblesusy {
38
39namespace runge_kutta {
40
41namespace {
43inline double sign(double a, double b) noexcept {
44 return b >= 0 ? std::fabs(a) : -std::fabs(a);
45}
46} // anonymous namespace
47
51template <typename ArrayType, typename Derivs>
52void rungeKuttaStep(const ArrayType& y, const ArrayType& dydx, double x,
53 double h, ArrayType& yout, ArrayType& yerr, Derivs derivs)
54{
55 const double a2 = 0.2;
56 const double a3 = 0.3;
57 const double a4 = 0.6;
58 const double a5 = 1.0;
59 const double a6 = 0.875;
60 const double b21 = 0.2;
61 const double b31 = 3.0 / 40.0;
62 const double b32 = 9.0 / 40.0;
63 const double b41 = 0.3;
64 const double b42 = -0.9;
65 const double b43 = 1.2;
66 const double b51 = -11.0 / 54.0;
67 const double b52 = 2.5;
68 const double b53 = -70.0 / 27.0;
69 const double b54 = 35.0 / 27.0;
70 const double b61 = 1631.0 / 55296.0;
71 const double b62 = 175.0 / 512.0;
72 const double b63 = 575.0 / 13824.0;
73 const double b64 = 44275.0 / 110592.0;
74 const double b65 = 253.0 / 4096.0;
75 const double c1 = 37.0 / 378.0;
76 const double c3 = 250.0 / 621.0;
77 const double c4 = 125.0 / 594.0;
78 const double c6 = 512.0 / 1771.0;
79 const double dc5 = -277.00 / 14336.0;
80 const double dc1 = c1 - 2825.0 / 27648.0;
81 const double dc3 = c3 - 18575.0 / 48384.0;
82 const double dc4 = c4 - 13525.0 / 55296.0;
83 const double dc6 = c6 - 0.25;
84
85 ArrayType ytemp = b21 * h * dydx + y;
86 const ArrayType ak2 = derivs(x + a2 * h, ytemp);
87
88 // Allowing piece-wise calculating of ytemp for speed reasons
89 ytemp = y + h * (b31 * dydx + b32 * ak2);
90 const ArrayType ak3 = derivs(x + a3 * h, ytemp);
91
92 ytemp = y + h * (b41 * dydx + b42 * ak2 + b43 * ak3);
93 const ArrayType ak4 = derivs(x+a4*h,ytemp);
94
95 ytemp = y + h * (b51 * dydx + b52 * ak2 + b53 * ak3 + b54 * ak4);
96 const ArrayType ak5 = derivs(x + a5 * h, ytemp);
97
98 ytemp = y + h * (b61 * dydx + b62 * ak2 + b63 * ak3 + b64 * ak4 + b65 * ak5);
99 const ArrayType ak6 = derivs(x + a6 * h, ytemp);
100
101 yout = y + h * (c1 * dydx + c3 * ak3 + c4 * ak4 + c6 * ak6);
102 yerr = h * (dc1 * dydx + dc3 * ak3 + dc4 * ak4 + dc5 * ak5 + dc6 * ak6);
103}
104
106template <typename ArrayType, typename Derivs>
107double odeStepper(ArrayType& y, const ArrayType& dydx, double& x, double htry,
108 double eps, const ArrayType& yscal, Derivs derivs,
109 int& max_step_dir)
110{
111 const double SAFETY = 0.9;
112 const double PGROW = -0.2;
113 const double PSHRNK = -0.25;
114 const double ERRCON = 1.89e-4;
115 const int n = y.size();
116 double errmax;
117 double h = htry;
118 ArrayType yerr(n);
119 ArrayType ytemp(n);
120
121 for (;;) {
122 rungeKuttaStep(y, dydx, x, h, ytemp, yerr, derivs);
123 errmax = (yerr / yscal).abs().maxCoeff(&max_step_dir);
124 errmax /= eps;
125 if (!std::isfinite(errmax)) {
126#ifdef ENABLE_VERBOSE
127 ERROR("odeStepper: non-perturbative running at Q = "
128 << std::exp(x) << " GeV of parameter y(" << max_step_dir
129 << ") = " << y(max_step_dir) << ", dy(" << max_step_dir
130 << ")/dx = " << dydx(max_step_dir));
131#endif
132 throw NonPerturbativeRunningError(std::exp(x), max_step_dir, y(max_step_dir));
133 }
134 if (errmax <= 1.0) {
135 break;
136 }
137 const double htemp = SAFETY * h * std::pow(errmax, PSHRNK);
138 h = (h >= 0.0 ? std::max(htemp, 0.1 * h) : std::min(htemp, 0.1 * h));
139 if (x + h == x) {
140#ifdef ENABLE_VERBOSE
141 ERROR("At Q = " << std::exp(x) << " GeV "
142 "stepsize underflow in odeStepper in parameter y("
143 << max_step_dir << ") = " << y(max_step_dir) << ", dy("
144 << max_step_dir << ")/dx = " << dydx(max_step_dir));
145#endif
146 throw NonPerturbativeRunningError(std::exp(x), max_step_dir, y(max_step_dir));
147 }
148 }
149 x += h;
150 y = ytemp;
151
152 return errmax > ERRCON ? SAFETY * h * std::pow(errmax,PGROW) : 5.0 * h;
153}
154
156template <typename ArrayType, typename Derivs,
157 typename Stepper = decltype(runge_kutta::odeStepper<ArrayType,Derivs>)>
158void integrateOdes(ArrayType& ystart, double from, double to, double eps,
159 double h1, double hmin, Derivs derivs,
160 Stepper rkqs = runge_kutta::odeStepper<ArrayType,Derivs>, int max_steps = 400)
161{
162 const int nvar = ystart.size();
163 const double TINY = 1.0e-16;
164 double x = from;
165 double h = sign(h1, to - from);
166 ArrayType yscal(nvar);
167 ArrayType y(ystart);
168 ArrayType dydx;
169 int max_step_dir = 0;
170
171 for (int nstp = 0; nstp < max_steps; ++nstp) {
172 dydx = derivs(x, y);
173 yscal = y.abs() + (dydx * h).abs() + TINY;
174 if ((x + h - to) * (x + h - from) > 0.0) {
175 h = to - x;
176 }
177
178 const double hnext = rkqs(y, dydx, x, h, eps, yscal, derivs, max_step_dir);
179
180 if ((x - to) * (to - from) >= 0.0) {
181 ystart = y;
182 return;
183 }
184
185 h = hnext;
186
187 if (std::fabs(hnext) <= hmin) {
188 break;
189 }
190 }
191
192#ifdef ENABLE_VERBOSE
193 ERROR("Bailed out of rk.cpp:too many steps in integrateOdes\n"
194 "********** Q = " << std::exp(x) << " *********");
195 ERROR("max step in direction of " << max_step_dir);
196 for (int i = 0; i < nvar; i++)
197 ERROR("y(" << i << ") = " << y(i) << " dydx(" << i <<
198 ") = " << dydx(i));
199#endif
200
201 throw NonPerturbativeRunningError(std::exp(x), max_step_dir, y(max_step_dir));
202}
203
204} // namespace runge_kutta
205
206} // namespace flexiblesusy
207
208#endif // RK_H
Non-perturbative RG running.
Definition: error.hpp:142
#define ERROR(msg)
Definition: logger.hpp:65
Target to(const Source &arg)
Converts an object of type Source to an object of type Target.
Definition: slhaea.h:50
void integrateOdes(ArrayType &ystart, double from, double to, double eps, double h1, double hmin, Derivs derivs, Stepper rkqs=runge_kutta::odeStepper< ArrayType, Derivs >, int max_steps=400)
Organises integration of 1st order system of ODEs.
Definition: rk.hpp:158
double odeStepper(ArrayType &y, const ArrayType &dydx, double &x, double htry, double eps, const ArrayType &yscal, Derivs derivs, int &max_step_dir)
organises the variable step-size for Runge-Kutta evolution
Definition: rk.hpp:107
void rungeKuttaStep(const ArrayType &y, const ArrayType &dydx, double x, double h, ArrayType &yout, ArrayType &yerr, Derivs derivs)
Definition: rk.hpp:52
T sign(T x)
Definition: mathdefs.hpp:65