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