OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
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 "Utilities/GSLCompat.h"
31
33
34namespace endfieldmodel {
35
36 // Use
37 // d^n E/dx^n = a_n1m1 F(n1) g(m1) + a_n2m1m2 F(n2) g(m1)g(m2)+...
38 // where
39 double Enge::getEnge(double x, int n) const {
40 std::vector<std::vector<int> > qt = getQIndex(n);
41 std::vector<double> g;
42 double e(0.);
43 for (size_t i = 0; i < qt.size(); ++i) {
44 double ei(qt[i][0]);
45 for (size_t j = 1; j < qt[i].size(); ++j) {
46 if (j > g.size()) g.push_back(gN(x, j - 1));
47 ei *= gsl_sf_pow_int(g[j - 1], qt[i][j]);
48 }
49 if (ei != ei) ei = 0; // div 0, usually g == 0 and index < 0
50 e += ei;
51 }
52 return e;
53 }
54
55 // h = a_0+a_1 (x/w)+a_2 (x/w)^2+a_3 (x/w)^3+...+a_m (x/w)^m
56 // h^(n) = d^nh/dx^n = sum^m_{i=n} a_i x^{i-n}/w^i i!/n!
57 double Enge::hN(double x, int n) const {
58 double hn = 0;
59 // optimise by precalculating factor
60 for (unsigned int i = n; i < _a.size(); i++)
61 hn += _a[i] / gsl_sf_pow_int(_lambda, i) * gsl_sf_pow_int(x, i - n) * gsl_sf_fact(i)
62 / gsl_sf_fact(i - n);
63 return hn;
64 }
65
66 // g = 1+exp(h)
67 // g^(n) = d^ng/dx^n
68 double Enge::gN(double x, int n) const {
69 if (n == 0) return 1 + exp(hN(x, 0)); // special case
70 std::vector<double> hn(n + 1);
71 for (int i = 0; i <= n; i++)
72 hn[i] = hN(x, i);
73 double exp_h0 = exp(hn[0]);
74 double gn = 0;
75 for (size_t i = 0; i < _h[n].size(); ++i) {
76 double gnj = _h[n][i][0] * exp_h0;
77 for (size_t j = 1; j < _h[n][i].size(); ++j)
78 gnj *= gsl_sf_pow_int(hn[j], _h[n][i][j]);
79 gn += gnj;
80 }
81 return gn;
82 }
83
84 // _q[i][j][k]; urk, 3d vector
85 // i indexes the derivative of f;
86 // j indexes the element in f derivative
87 // k indexes the derivative of g
88 // this will quickly become grotesque
89 std::vector<std::vector<std::vector<int> > > Enge::_q;
90 std::vector<std::vector<std::vector<int> > > Enge::_h;
91 void Enge::setEngeDiffIndices(size_t n) {
92 if (_q.size() == 0) {
93 _q.push_back(std::vector<std::vector<int> >(1, std::vector<int>(3)));
94 _q[0][0][0] = +1; // f_0 = 1*g^(-1)
95 _q[0][0][1] = -1;
96 _q[0][0][2] = 0;
97 }
98
99 for (size_t i = _q.size(); i < n + 1; ++i) {
100 _q.push_back(std::vector<std::vector<int> >());
101 for (size_t j = 0; j < _q[i - 1].size(); ++j) {
102 size_t k_max = _q[i - 1][j].size();
103 std::vector<int> new_vec(_q[i - 1][j]);
104 // derivative of g^-n0 = -n0*g^(-n0-1)*g(1)
105 new_vec[0] *= new_vec[1]; // alpha *= g(0) power
106 new_vec[1] -= 1; // g(0) power -= 1
107 new_vec[2] += 1; // g(1) power += 1
108 _q[i].push_back(new_vec);
109 for (size_t k = 2; k < k_max; ++k) { // 0 is alpha; 1 is g(0)
110 // derivative of g(k)^nk = nk g(k+1) g(k)^(nk-1)
111 if (_q[i - 1][j][k] > 0) {
112 std::vector<int> new_vec(_q[i - 1][j]);
113 if (k == k_max - 1) new_vec.push_back(0); // need enough coefficients
114 new_vec[0] *= new_vec[k];
115 new_vec[k] -= 1;
116 new_vec[k + 1] += 1;
117 _q[i].push_back(new_vec);
118 }
119 }
120 }
121 }
122
123 if (_h.size() == 0) {
124 // first one is special case (1+e^h dealt with explicitly)
125 _h.push_back(std::vector<std::vector<int> >());
126 // second is (1*e^h h'^1)
127 _h.push_back(std::vector<std::vector<int> >());
128 _h[1].push_back(std::vector<int>(2, 1));
129 }
130 for (size_t i = _h.size(); i < n + 1; ++i) {
131 _h.push_back(std::vector<std::vector<int> >());
132 for (size_t j = 0; j < _h[i - 1].size(); ++j) {
133 // d/dx k0 e^g g(1)^k1 ... g(n)^kn ... = k0 e^g g(1)^(k1+1) ... g(n)^kn
134 // + SUM_n k0 kn e^g ... g(n)^(kn-1) g(n-1)
135 std::vector<int> new_vec(_h[i - 1][j]);
136 new_vec[1] += 1;
137 _h[i].push_back(new_vec);
138 for (size_t k = 1; k < _h[i - 1][j].size(); ++k) {
139 if (_h[i - 1][j][k] > 0) {
140 std::vector<int> new_vec(_h[i - 1][j]);
141 if (k == _h[i - 1][j].size() - 1) new_vec.push_back(0);
142 new_vec[0] *= new_vec[k];
143 new_vec[k] -= 1;
144 new_vec[k + 1] += 1;
145 _h[i].push_back(new_vec);
146 }
147 }
148 }
149 _h[i] = CompactVector(_h[i]);
150 }
151 }
152
153 Enge::Enge(const std::vector<double> a, double x0, double lambda)
154 : _a(a), _lambda(lambda), _x0(x0) {}
155
156 Enge* Enge::clone() const {
157 Enge* myclone = new Enge(_a, _x0, _lambda);
158 return myclone;
159 }
160
161 void Enge::rescale(double scaleFactor) {
162 _x0 *= scaleFactor;
163 _lambda *= scaleFactor;
164 }
165
166 std::ostream& Enge::print(std::ostream& out) const {
167 out << "Enge function l=" << _lambda << " x0=" << _x0 << " c=";
168 for (auto ai : _a) {
169 out << ai << " ";
170 }
171 return out;
172 }
173} // namespace endfieldmodel
double gsl_sf_fact(unsigned int n)
Factorial (computed via for large ).
Definition GSLCompat.h:69
double gsl_sf_pow_int(double x, int n)
Integer power .
Definition GSLCompat.h:57
void rescale(double scaleFactor)
Definition Enge.cpp:161
Enge * clone() const
Definition Enge.cpp:156
std::vector< double > _a
Definition Enge.h:143
static std::vector< std::vector< std::vector< int > > > _h
Definition Enge.h:149
static std::vector< std::vector< std::vector< int > > > _q
Definition Enge.h:147
double gN(double x, int n) const
Definition Enge.cpp:68
static void setEngeDiffIndices(size_t n)
Definition Enge.cpp:91
static std::vector< std::vector< int > > getQIndex(int n)
Definition Enge.h:156
double hN(double x, int n) const
Definition Enge.cpp:57
double getEnge(double x, int n) const
Definition Enge.cpp:39
std::ostream & print(std::ostream &out) const
Definition Enge.cpp:166
std::vector< std::vector< int > > CompactVector(std::vector< std::vector< int > > vec)