OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
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 
17 public:
18  RootFinderForCSR(double a,
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>
92  T computeDerivative(T x) const {
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 
136 private:
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
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
constexpr double e
The value of .
Definition: Physics.h:40
Definition: rbendmap.h:8
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
std::pair< double, double > searchRange_m
std::complex< double > deltaZero_m
std::pair< double, double > getSearchRange() const
T computeDerivative(T x) const
std::vector< double > thirdOrderRoots_m
static double computeValueGSL(double x, void *params)
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
RootFinderForCSR(double a, double b, double d, double e)
std::complex< double > deltaOne_m
double searchRoot(const double &tol)
#define C2(a, b)
Definition: fftpack.cpp:276
T computeValue(const T &x) const
#define C1(a, b, c)
Definition: fftpack.cpp:275