TRIQS/triqs_modest 3.3.0
Brillouin zone summation
Loading...
Searching...
No Matches
root_finder.hpp
Go to the documentation of this file.
1// Copyright (c) 2025--present, The Simons Foundation
2// This file is part of TRIQS/modest and is licensed under the terms of GPLv3 or later.
3// SPDX-License-Identifier: GPL-3.0-or-later
4// See LICENSE in the root of this distribution for details.
5
6#pragma once
7#include "utils/defs.hpp"
9namespace triqs {
10
11 using std::abs;
12 //------------------------------------------------------
26 inline std::pair<double, double> find_bounds(std::function<double(double)> f, double x_init, double y_value, double delta_x, double precision,
27 long max_loops = 1000, bool verbosity = false) {
28
29 auto out = ostream_with_verbosity(std::cout, verbosity);
30 double x = x_init;
31 delta_x = abs(delta_x);
32
33 double y1 = f(x);
34 double eps = (y1 - y_value >= 0) ? 1.0 : -1.0;
35
36 double x1 = x;
37 double y2 = y1;
38 double x2 = x1;
39
40 long nbre_loop = 0;
41 for (; nbre_loop <= max_loops && (y2 - y_value) * eps > 0 && abs(y2 - y_value) > precision; ++nbre_loop) {
42 x2 -= eps * delta_x;
43 y2 = f(x2);
44 out << fmt::format("x={}, f(x)= {}\n", x2, y2);
45 }
46
47 if (x1 > x2) {
48 std::swap(x1, x2);
49 std::swap(y1, y2);
50 }
51 return {x1, x2};
52 }
53 //------------------------------------------------------
54
70 inline std::pair<double, double> dichotomy(std::function<double(double)> f, double x_low, double x_high, double y_target, double precision,
71 long max_loops, std::string x_name, std::string y_name, bool verbosity) {
72 auto out = ostream_with_verbosity(std::cout, verbosity);
73
74 auto x1 = x_low;
75 auto x2 = x_high;
76
77 auto y1 = f(x_low);
78 auto y2 = f(x_high);
79
80 out << fmt::format("{} < {} < {}\n", x1, x_name, x2);
81 out << fmt::format("{} < {} < {}\n", y1, y_name, y2);
82
83 double yfound = (abs(y1 - y_target) < abs(y2 - y_target)) ? y1 : y2;
84 double x = (abs(y1 - y_target) < abs(y2 - y_target)) ? x1 : x2;
85
86 long nbre_loop = 0;
87 for (; nbre_loop <= max_loops && abs(yfound - y_target) > precision; ++nbre_loop) {
88 x = x1 + (x2 - x1) * (y_target - y1) / (y2 - y1);
89 yfound = f(x);
90 if ((y1 - y_target) * (yfound - y_target) > 0) {
91 x1 = x;
92 y1 = yfound;
93 } else {
94 x2 = x;
95 y2 = yfound;
96 }
97 out << fmt::format("{} < {} < {}\n", x1, x_name, x2);
98 out << fmt::format("{} < {} < {}\n", y1, y_name, y2);
99 }
100
101 if (std::abs(yfound - y_target) < precision) {
102 out << fmt::format("{} found in {} iterations:\n", x_name, nbre_loop);
103 out << fmt::format("{} = {}; {} = {}\n", y_name, yfound, x_name, x);
104 return {x, yfound};
105 } else {
106 out << fmt::format("FAILURE to adjust {} to the value {} after {} iterations.\n", x_name, y_target, nbre_loop);
107 throw std::runtime_error{fmt::format("Dichotomy adjustment for {} failed after {} iterations", x_name, nbre_loop)};
108 }
109 }
110 //------------------------------------------------------
111
127 inline std::pair<double, double> bisection(std::function<double(double)> f, double x_low, double x_high, double y_target, double precision,
128 long max_loops, std::string x_name, std::string y_name, bool verbosity) {
129
130 auto out = ostream_with_verbosity(std::cout, verbosity);
131
132 auto y_low = f(x_low);
133 auto y_high = f(x_high);
134
135 out << fmt::format("{} < {} < {}\n", x_low, x_name, x_high);
136 out << fmt::format("{} < {} < {}\n", y_low, y_name, y_high);
137
138 for (auto it = 0; it < max_loops; it++) {
139 auto x_mid = (x_high + x_low) / 2.0;
140 auto y_mid = f(x_mid);
141
142 if (abs(y_mid - y_target) <= precision) return {x_mid, y_mid};
143
144 if (y_mid - y_target >= 0) {
145 x_high = x_mid;
146 y_high = y_mid;
147 } else {
148 x_low = x_mid;
149 y_low = y_mid;
150 }
151
152 out << fmt::format("{} < {} < {}\n", x_low, x_name, x_high);
153 out << fmt::format("{} < {} < {}\n", y_low, y_name, y_high);
154 }
155
156 out << fmt::format("FAILURE to adjust {} to the value {} after {} iterations.\n", x_name, y_target, max_loops);
157 throw std::runtime_error{fmt::format("Dichotomy adjustment for {} failed after {} iterations", x_name, max_loops)};
158 }
159 //------------------------------------------------------
160
176 inline std::pair<double, double> root_finder(std::string method, std::function<double(double)> f, double x_init, double y_value, double precision,
177 double delta_x, long max_loops = 1000, std::string x_name = "", std::string y_name = "",
178 bool verbosity = false) {
179
180 auto out = ostream_with_verbosity(std::cout, verbosity);
181
182 out << fmt::format("Root finder search of {} to obtain {} = {} +/- {}\n", x_name, y_name, y_value, precision);
183
184 auto [x1, x2] = find_bounds(f, x_init, y_value, delta_x, precision, max_loops, verbosity);
185
186 if (method == "dichotomy") {
187 return dichotomy(f, x1, x2, y_value, precision, max_loops, x_name, y_name, verbosity);
188 } else if (method == "bisection") {
189 return bisection(f, x1, x2, y_value, precision, max_loops, x_name, y_name, verbosity);
190 } else {
191 throw std::runtime_error("Not a valid choice of root finder method!");
192 }
193 }
194
195} // namespace triqs
FIXME : MERGE : replace triqs::report_steam, -> merge + alias.
Definition streams.hpp:28
std::pair< double, double > find_bounds(std::function< double(double)> f, double x_init, double y_value, double delta_x, double precision, long max_loops=1000, bool verbosity=false)
find upper and lower bounds of f(x)
std::pair< double, double > dichotomy(std::function< double(double)> f, double x_low, double x_high, double y_target, double precision, long max_loops, std::string x_name, std::string y_name, bool verbosity)
dichotomy algorithm
std::pair< double, double > bisection(std::function< double(double)> f, double x_low, double x_high, double y_target, double precision, long max_loops, std::string x_name, std::string y_name, bool verbosity)
bisection algorithm
std::pair< double, double > root_finder(std::string method, std::function< double(double)> f, double x_init, double y_value, double precision, double delta_x, long max_loops=1000, std::string x_name="", std::string y_name="", bool verbosity=false)
Root finder f(x) = 0.