OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
RootFinderForCSR.h
Go to the documentation of this file.
1#ifndef ROOTFINDERFORCSR_H
2#define ROOTFINDERFORCSR_H
3
5
6#include <gsl/gsl_errno.h>
7#include <gsl/gsl_math.h>
8#include <gsl/gsl_roots.h>
9
10#include <algorithm>
11#include <cmath>
12#include <complex>
13#include <iostream>
14#include <utility>
15#include <vector>
16
18public:
20 double b,
21 double d,
22 double e):
23 a_m(a),
24 b_m(b),
25 d_m(d),
26 e_m(e),
27 searchRange_m(0.0, 0.0) {
28 deltaZero_m.real(std::pow(3. * b, 2));
29 deltaZero_m.imag(0.0);
30 deltaOne_m.real(2. * std::pow(3. * b, 3) + 27. * std::pow(4. * a, 2) * d);
31 deltaOne_m.imag(0.0);
32 }
33
35 std::complex<double> tmp = std::sqrt(std::pow(deltaOne_m, 2) - 4.0 * std::pow(deltaZero_m, 3));
36 std::complex<double> C1 = std::pow(0.5 * (deltaOne_m + std::copysign(1.0, deltaOne_m.real()) * tmp), 1.0 / 3.0);
37
38 std::complex<double> x1 = -(3.0 * b_m + C1 + deltaZero_m / C1) / (12. * a_m);
39 if (std::abs(x1.imag()) < 1e-9 && x1.real() > 0.0)
40 thirdOrderRoots_m.push_back(x1.real());
41
42 std::complex<double> C2 = C1 * std::complex<double>(-0.5, -0.5 * std::sqrt(3));
43 std::complex<double> x2 = -(3. * b_m + C2 + deltaZero_m / C2) / (12. * a_m);
44 if (std::abs(x2.imag()) < 1e-9 && x2.real() > 0.0)
45 thirdOrderRoots_m.push_back(x2.real());
46
47 std::complex<double> C3 = C1 * std::complex<double>(-0.5, 0.5 * std::sqrt(3));
48 std::complex<double> x3 = -(3. * b_m + C3 + deltaZero_m / C3) / (12. * a_m);
49 if (std::abs(x3.imag()) < 1e-9 && x3.real() > 0.0)
50 thirdOrderRoots_m.push_back(x3.real());
51
52 if (thirdOrderRoots_m.size() == 0) return false;
53
54 std::sort(thirdOrderRoots_m.begin(),
55 thirdOrderRoots_m.end());
56
57 thirdOrderRoots_m.insert(thirdOrderRoots_m.begin(), 0.0);
58
59 double rangeMax = thirdOrderRoots_m.back() + 0.1;
60 while (computeValue(rangeMax) < 0.0) {
61 rangeMax += 0.1;
62 }
63 thirdOrderRoots_m.push_back(rangeMax);
64
65 double oldValue = computeValue(0.0);
66 unsigned int size = thirdOrderRoots_m.size();
67 unsigned int i;
68 for (i = 1; i < size; ++ i) {
69 const double &x = thirdOrderRoots_m[i];
70 double value = computeValue(x);
71
72 if (oldValue * value < 0.0) {
73 searchRange_m.first = thirdOrderRoots_m[i - 1];
74 searchRange_m.second = x;
75
76 return true;
77 }
78
79 oldValue = value;
80 }
81
82 return false;
83 }
84
85 template <class T>
86 T computeValue(const T &x) const {
87 T xcube = std::pow(x, 3);
88
89 return a_m * x * xcube + b_m * xcube + d_m * x + e_m;
90 }
91
92 template <class T>
93 T computeDerivative(T x) const {
94 T xsqr = std::pow(x, 2);
95
96 return 4.0 * a_m * x * xsqr + 3.0 * b_m * xsqr + d_m;
97 }
98
99 double searchRoot(const double &tol) {
100 int status;
101 int iter = 0, max_iter = 100;
102 const gsl_root_fsolver_type *T;
103 gsl_root_fsolver *solver;
104 double root = 0;
105 double x_lo = searchRange_m.first, x_hi = searchRange_m.second;
106 gsl_function F;
107 struct PolyParams params = {a_m, b_m, d_m, e_m};
108
109 F.function = &computeValueGSL;
110 F.params = &params;
111
112 T = gsl_root_fsolver_brent;
113 solver = gsl_root_fsolver_alloc (T);
114 gsl_root_fsolver_set (solver, &F, x_lo, x_hi);
115
116 do
117 {
118 iter++;
119 status = gsl_root_fsolver_iterate (solver);
120 root = gsl_root_fsolver_root (solver);
121 x_lo = gsl_root_fsolver_x_lower (solver);
122 x_hi = gsl_root_fsolver_x_upper (solver);
123 status = gsl_root_test_interval (x_lo, x_hi,
124 0, 0.000001);
125 }
126 while (status == GSL_CONTINUE && iter < max_iter && computeValue(root) > tol);
127
128 gsl_root_fsolver_free (solver);
129
130 return root;
131 }
132
133 std::pair<double, double> getSearchRange() const {
134 return searchRange_m;
135 }
136
137private:
138
139 double a_m; // x^4
140 double b_m; // x^3
141 double d_m; // x
142 double e_m; // 1
143
144 struct PolyParams {
145 double a_m;
146 double b_m;
147 double d_m;
148 double e_m;
149 };
150
151 static
152 double computeValueGSL(double x, void *params) {
153 double xcube = std::pow(x, 3);
154
155 struct PolyParams *p
156 = (struct PolyParams *) params;
157
158 return p->a_m * x * xcube + p->b_m * xcube + p->d_m * x + p->e_m;
159 }
160
161 std::pair<double, double> searchRange_m;
162
163 std::complex<double> deltaZero_m;
164 std::complex<double> deltaOne_m;
165
166 std::vector<double> thirdOrderRoots_m;
167 // double C_m;
168
169};
170
171#endif
#define C1(a, b, c)
Definition fftpack.cpp:274
#define C2(a, b)
Definition fftpack.cpp:275
std::complex< double > a
RootFinderForCSR(double a, double b, double d, double e)
std::vector< double > thirdOrderRoots_m
T computeValue(const T &x) const
std::complex< double > deltaZero_m
std::pair< double, double > getSearchRange() const
T computeDerivative(T x) const
double searchRoot(const double &tol)
std::complex< double > deltaOne_m
std::pair< double, double > searchRange_m
static double computeValueGSL(double x, void *params)