OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
Enge.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, Chris Rogers
3  * All rights reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * 1. Redistributions of source code must retain the above copyright notice,
7  * this list of conditions and the following disclaimer.
8  * 2. Redistributions in binary form must reproduce the above copyright notice,
9  * this list of conditions and the following disclaimer in the documentation
10  * and/or other materials provided with the distribution.
11  * 3. Neither the name of STFC nor the names of its contributors may be used to
12  * endorse or promote products derived from this software without specific
13  * prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <cmath>
29 
30 #include "gsl/gsl_sf_gamma.h"
31 #include "gsl/gsl_sf_pow_int.h"
32 
34 
35 namespace endfieldmodel {
36 
37 // Use
38 // d^n E/dx^n = a_n1m1 F(n1) g(m1) + a_n2m1m2 F(n2) g(m1)g(m2)+...
39 // where
40 double Enge::GetEnge(double x, int n) const {
41  std::vector< std::vector<int> > qt = GetQIndex(n);
42  std::vector<double> g;
43  double e(0.);
44  for (size_t i = 0; i < qt.size(); ++i) {
45  double ei(qt[i][0]);
46  for (size_t j = 1; j < qt[i].size(); ++j) {
47  if (j > g.size()) g.push_back(GN(x, j-1));
48  ei *= gsl_sf_pow_int(g[j-1], qt[i][j]);
49  }
50  if (ei != ei) ei = 0; // div 0, usually g == 0 and index < 0
51  e += ei;
52  }
53  return e;
54 }
55 
56 
57 // h = a_0+a_1 (x/w)+a_2 (x/w)^2+a_3 (x/w)^3+...+a_m (x/w)^m
58 // h^(n) = d^nh/dx^n = sum^m_{i=n} a_i x^{i-n}/w^i i!/n!
59 double Enge::HN(double x, int n) const {
60  double hn = 0;
61  // optimise by precalculating factor
62  for (unsigned int i = n; i <_a.size(); i++)
63  hn += _a[i]/gsl_sf_pow_int(_lambda, i)*gsl_sf_pow_int(x, i-n)*
64  static_cast<double>(gsl_sf_fact(i))
65  /static_cast<double>(gsl_sf_fact(i-n));
66  return hn;
67 }
68 
69 // g = 1+exp(h)
70 // g^(n) = d^ng/dx^n
71 double Enge::GN(double x, int n) const {
72  if (n == 0) return 1+exp(HN(x, 0)); // special case
73  std::vector<double> hn(n+1);
74  for (int i = 0; i <= n; i++) hn[i] = HN(x, i);
75  double exp_h0 = exp(hn[0]);
76  double gn = 0;
77  for (size_t i = 0; i < _h[n].size(); ++i) {
78  double gnj = _h[n][i][0]*exp_h0;
79  for (size_t j = 1; j < _h[n][i].size(); ++j)
80  gnj *= gsl_sf_pow_int(hn[j], _h[n][i][j]);
81  gn += gnj;
82  }
83  return gn;
84 }
85 
86 // _q[i][j][k]; urk, 3d vector
87 // i indexes the derivative of f;
88 // j indexes the element in f derivative
89 // k indexes the derivative of g
90 // this will quickly become grotesque
91 std::vector< std::vector< std::vector<int> > > Enge::_q;
92 std::vector< std::vector< std::vector<int> > > Enge::_h;
94  if (_q.size() == 0) {
95  _q.push_back(std::vector< std::vector<int> >(1, std::vector<int>(3)) );
96  _q[0][0][0] = +1; // f_0 = 1*g^(-1)
97  _q[0][0][1] = -1;
98  _q[0][0][2] = 0;
99  }
100 
101  for (size_t i = _q.size(); i < n+1; ++i) {
102  _q.push_back(std::vector< std::vector<int> >() );
103  for (size_t j = 0; j < _q[i-1].size(); ++j) {
104  size_t k_max = _q[i-1][j].size();
105  std::vector<int> new_vec(_q[i-1][j]);
106  // derivative of g^-n0 = -n0*g^(-n0-1)*g(1)
107  new_vec[0] *= new_vec[1]; // alpha *= g(0) power
108  new_vec[1] -= 1; // g(0) power -= 1
109  new_vec[2] += 1; // g(1) power += 1
110  _q[i].push_back(new_vec);
111  for (size_t k = 2; k < k_max; ++k) { // 0 is alpha; 1 is g(0)
112  // derivative of g(k)^nk = nk g(k+1) g(k)^(nk-1)
113  if (_q[i-1][j][k] > 0) {
114  std::vector<int> new_vec(_q[i-1][j]);
115  if ( k == k_max-1 ) new_vec.push_back(0); // need enough coefficients
116  new_vec[0] *= new_vec[k];
117  new_vec[k] -= 1;
118  new_vec[k+1] += 1;
119  _q[i].push_back(new_vec);
120  }
121  }
122  }
123  }
124 
125  if (_h.size() == 0) {
126  // first one is special case (1+e^h dealt with explicitly)
127  _h.push_back(std::vector< std::vector<int> >());
128  // second is (1*e^h h'^1)
129  _h.push_back(std::vector< std::vector<int> >());
130  _h[1].push_back(std::vector<int>(2, 1));
131  }
132  for (size_t i = _h.size(); i < n+1; ++i) {
133  _h.push_back(std::vector< std::vector<int> >());
134  for (size_t j = 0; j < _h[i-1].size(); ++j) {
135  // d/dx k0 e^g g(1)^k1 ... g(n)^kn ... = k0 e^g g(1)^(k1+1) ... g(n)^kn
136  // + SUM_n k0 kn e^g ... g(n)^(kn-1) g(n-1)
137  std::vector<int> new_vec(_h[i-1][j]);
138  new_vec[1] += 1;
139  _h[i].push_back(new_vec);
140  for (size_t k = 1; k <_h[i-1][j].size(); ++k) {
141  if (_h[i-1][j][k] > 0) {
142  std::vector<int> new_vec(_h[i-1][j]);
143  if (k == _h[i-1][j].size()-1) new_vec.push_back(0);
144  new_vec[0] *= new_vec[k];
145  new_vec[k] -= 1;
146  new_vec[k+1] += 1;
147  _h[i].push_back(new_vec);
148  }
149  }
150  }
151  _h[i] = CompactVector(_h[i]);
152  }
153 }
154 
155 }
156 
Tps< T > exp(const Tps< T > &x)
Exponential.
Definition: TpsMath.h:165
std::vector< std::vector< int > > CompactVector(std::vector< std::vector< int > > vec)
constexpr double e
The value of.
Definition: Physics.h:39
double GetEnge(double x, int n) const
Definition: Enge.cpp:40
double _lambda
Definition: Enge.h:112
std::vector< double > _a
Definition: Enge.h:111
double HN(double x, int n) const
Definition: Enge.cpp:59
static std::vector< std::vector< std::vector< int > > > _h
Definition: Enge.h:117
static std::vector< std::vector< std::vector< int > > > _q
Definition: Enge.h:115
double GN(double x, int n) const
Definition: Enge.cpp:71
static std::vector< std::vector< int > > GetQIndex(int n)
Definition: Enge.h:120
static void SetEngeDiffIndices(size_t n)
Definition: Enge.cpp:93