flexiblesusy is hosted by Hepforge, IPPP Durham
FlexibleSUSY
root_finder.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 ROOT_FINDER_H
20#define ROOT_FINDER_H
21
22#include <algorithm>
23#include <cmath>
24#include <string>
25#include <utility>
26#include <Eigen/Core>
27#include <gsl/gsl_vector.h>
28#include <gsl/gsl_multiroots.h>
29
30#include "logger.hpp"
31#include "error.hpp"
32#include "ewsb_solver.hpp"
34#include "gsl_utils.hpp"
35#include "gsl_vector.hpp"
36
37namespace flexiblesusy {
38
63template <std::size_t dimension>
64class Root_finder : public EWSB_solver {
65public:
66 using Vector_t = Eigen::Matrix<double,dimension,1>;
67 using Function_t = std::function<Vector_t(const Vector_t&)>;
69
70 Root_finder() = default;
71 Root_finder(const Function_t&, std::size_t, double, Solver_type solver_type_ = GSLHybrid);
72 virtual ~Root_finder() = default;
73
74 void set_function(const Function_t& f) { function = f; }
75 void set_precision(double p) { precision = p; }
76 void set_max_iterations(std::size_t n) { max_iterations = n; }
78 int find_root(const Vector_t&);
79
80 // EWSB_solver interface methods
81 virtual std::string name() const override { return std::string("Root_finder<") + solver_type_name() + ">"; }
82 virtual int solve(const Eigen::VectorXd&) override;
83 virtual Eigen::VectorXd get_solution() const override { return root; }
84
85private:
86 std::size_t max_iterations{100};
87 double precision{1.e-2};
88 Vector_t root{Vector_t::Zero()};
91
92 const char* solver_type_name() const;
93 const gsl_multiroot_fsolver_type* solver_type_to_gsl_pointer() const;
94 static int gsl_function(const gsl_vector*, void*, gsl_vector*);
95
96 static bool is_finite(const Vector_t& v) {
97 return std::any_of(v.data(), v.data() + v.size(),
98 [](double x) { return std::isfinite(x); });
99 }
100};
101
110template <std::size_t dimension>
112 const Function_t& function_,
113 std::size_t max_iterations_,
114 double precision_,
115 Solver_type solver_type_
116)
117 : max_iterations(max_iterations_)
118 , precision(precision_)
119 , function(function_)
120 , solver_type(solver_type_)
121{
122}
123
131template <std::size_t dimension>
133{
134 if (!function)
135 throw SetupError("Root_finder: function not callable");
136
137 int status;
138 std::size_t iter = 0;
139 void* parameters = &function;
140 gsl_multiroot_function f = {gsl_function, dimension, parameters};
141 GSL_multiroot_fsolver solver(solver_type_to_gsl_pointer(), dimension, &f, to_GSL_vector(start));
142
143#ifndef ENABLE_DEBUG
144 gsl_set_error_handler_off();
145#endif
146
147 do {
148 iter++;
149 status = solver.iterate();
150 solver.print_state(iter);
151
152 if (status) // check if solver is stuck
153 break;
154
155 status = solver.test_residual(precision);
156 } while (status == GSL_CONTINUE && iter < max_iterations);
157
158 VERBOSE_MSG("\t\t\tRoot_finder status = " << gsl_strerror(status));
159
160 root = to_eigen_vector<dimension>(solver.get_root().raw());
161
162 return status;
163}
164
165template <std::size_t dimension>
166int Root_finder<dimension>::gsl_function(const gsl_vector* x, void* params, gsl_vector* f)
167{
168 if (!flexiblesusy::is_finite(x)) {
169 gsl_vector_set_all(f, std::numeric_limits<double>::max());
170 return GSL_EDOM;
171 }
172
173 Function_t* fun = static_cast<Function_t*>(params);
174 int status = GSL_SUCCESS;
175 const Vector_t arg(to_eigen_vector<dimension>(x));
176 Vector_t result;
177 result.setConstant(std::numeric_limits<double>::max());
178
179 try {
180 result = (*fun)(arg);
181 status = is_finite(result) ? GSL_SUCCESS : GSL_EDOM;
182 } catch (const flexiblesusy::Error&) {
183 status = GSL_EDOM;
184 }
185
186 // copy result -> f
187 for (std::size_t i = 0; i < dimension; i++) {
188 gsl_vector_set(f, i, result(i));
189 }
190
191 return status;
192}
193
194template <std::size_t dimension>
196{
197 switch (solver_type) {
198 case GSLHybrid : return "GSLHybrid";
199 case GSLHybridS: return "GSLHybridS";
200 case GSLBroyden: return "GSLBroyden";
201 case GSLNewton : return "GSLNewton";
202 default:
203 throw SetupError("Unknown root solver type: "
204 + std::to_string(solver_type));
205 }
206
207 return "unknown";
208}
209
210template <std::size_t dimension>
211const gsl_multiroot_fsolver_type* Root_finder<dimension>::solver_type_to_gsl_pointer() const
212{
213 switch (solver_type) {
214 case GSLHybrid : return gsl_multiroot_fsolver_hybrid;
215 case GSLHybridS: return gsl_multiroot_fsolver_hybrids;
216 case GSLBroyden: return gsl_multiroot_fsolver_broyden;
217 case GSLNewton : return gsl_multiroot_fsolver_dnewton;
218 default:
219 throw SetupError("Unknown root solver type: "
220 + std::to_string(solver_type));
221 }
222
223 return nullptr;
224}
225
226template <std::size_t dimension>
227int Root_finder<dimension>::solve(const Eigen::VectorXd& start)
228{
229 return (find_root(start) == GSL_SUCCESS ?
231}
232
233} // namespace flexiblesusy
234
235#endif
interface for numeric EWSB solvers
Definition: ewsb_solver.hpp:31
void print_state(std::size_t iteration) const
int test_residual(double precision) const noexcept
const gsl_vector * raw() const noexcept
get raw pointer
Definition: gsl_vector.cpp:191
Function root finder.
Definition: root_finder.hpp:64
static int gsl_function(const gsl_vector *, void *, gsl_vector *)
void set_max_iterations(std::size_t n)
Definition: root_finder.hpp:76
void set_precision(double p)
Definition: root_finder.hpp:75
virtual Eigen::VectorXd get_solution() const override
Definition: root_finder.hpp:83
void set_function(const Function_t &f)
Definition: root_finder.hpp:74
void set_solver_type(Solver_type t)
Definition: root_finder.hpp:77
const char * solver_type_name() const
Vector_t root
the root
Definition: root_finder.hpp:88
virtual int solve(const Eigen::VectorXd &) override
Solver_type solver_type
solver type
Definition: root_finder.hpp:90
Eigen::Matrix< double, dimension, 1 > Vector_t
Definition: root_finder.hpp:66
double precision
precision goal
Definition: root_finder.hpp:87
Function_t function
function to minimize
Definition: root_finder.hpp:89
static bool is_finite(const Vector_t &v)
Definition: root_finder.hpp:96
std::size_t max_iterations
maximum number of iterations
Definition: root_finder.hpp:86
virtual ~Root_finder()=default
virtual std::string name() const override
Definition: root_finder.hpp:81
int find_root(const Vector_t &)
const gsl_multiroot_fsolver_type * solver_type_to_gsl_pointer() const
std::function< Vector_t(const Vector_t &)> Function_t
Definition: root_finder.hpp:67
Spectrum generator was not setup correctly.
Definition: error.hpp:46
v and recompile _everything_ when you do ***this parameter determines how far the scalar npoint functions *will look back to find the same parameters(when lmem is true) *integer memory parameter(memory
#define VERBOSE_MSG(msg)
Definition: logger.hpp:57
std::complex< double > f(double tau) noexcept
constexpr T arg(const Complex< T > &z) noexcept
Definition: complex.hpp:42
std::string to_string(char a)
GSL_vector to_GSL_vector(const Eigen::DenseBase< Derived > &v)
Definition: gsl_utils.hpp:34
bool is_finite(const gsl_vector *x)
Returns true if GSL vector contains only finite elements, false otherwise.
Definition: gsl_utils.cpp:32