OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
SquarePolynomialVector.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, 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
29#include <algorithm>
30#include <cmath>
31#include <iomanip>
32#include <sstream>
33
34#include "gsl/gsl_sf_gamma.h"
35
37
41
42namespace interpolation {
43
45std::vector< std::vector< std::vector<int> > > SquarePolynomialVector::_polyKeyByPower;
46std::vector< std::vector< std::vector<int> > > SquarePolynomialVector::_polyKeyByVector;
47
49 : _pointDim(0), _polyCoeffs() {
50}
51
53 : _pointDim(pv._pointDim),
54 _polyCoeffs(pv._polyCoeffs.num_row(), pv._polyCoeffs.num_col(), 0.) {
56}
57
58
59SquarePolynomialVector::SquarePolynomialVector(int numberOfInputVariables, MMatrix<double> polynomialCoefficients)
60 : _pointDim(numberOfInputVariables), _polyCoeffs(polynomialCoefficients) {
61 SetCoefficients(numberOfInputVariables, polynomialCoefficients);
62}
63
64SquarePolynomialVector::SquarePolynomialVector(std::vector<PolynomialCoefficient> coefficients)
65 : _pointDim(0), _polyCoeffs() {
66 SetCoefficients(coefficients);
67}
68
70 _pointDim = pointDim;
71 _polyCoeffs = coeff;
72
73 if (int(_polyKeyByVector.size()) < pointDim || _polyKeyByVector[pointDim-1].size() < coeff.num_col())
74 IndexByVector(coeff.num_col(), pointDim); // sets _polyKeyByVector and _polyKeyByPower
75}
76
77void SquarePolynomialVector::SetCoefficients(std::vector<PolynomialCoefficient> coeff) {
78 _pointDim = 0;
79 int maxPolyOrder = 0;
80 int valueDim = 0;
81 for(unsigned int i=0; i<coeff.size(); i++) {
82 int polyOrder = coeff[i].InVariables().size();
83 for(unsigned int j=0; j<coeff[i].InVariables().size(); j++)
84 if(coeff[i].InVariables()[j] > _pointDim) _pointDim = coeff[i].InVariables()[j];
85 if(coeff[i].OutVariable() > valueDim) valueDim = coeff[i].OutVariable();
86 if(polyOrder > maxPolyOrder) maxPolyOrder = polyOrder;
87 }
88 _pointDim++; //PointDim indexes from 0
89 _polyCoeffs = MMatrix<double>(valueDim+1, NumberOfPolynomialCoefficients(_pointDim, maxPolyOrder+1), 0.);
91 IndexByVector(_polyCoeffs.num_col(), _pointDim); // sets _polyKeyByVector and _polyKeyByPower
92
93 for(size_t i=0; i<_polyCoeffs.num_col(); i++) {
94 for(unsigned int j=0; j<coeff.size(); j++)
95 if(coeff[j].InVariables() == _polyKeyByVector[_pointDim-1].back()) {
96 int dim = coeff[j].OutVariable();
97 _polyCoeffs(dim+1,i+1) = coeff[j].Coefficient();
98 }
99 }
100}
101
103{
104 for(size_t i=0; i<coeff.num_row() && i<_polyCoeffs.num_row(); i++)
105 for(size_t j=0; j<coeff.num_col() && j<_polyCoeffs.num_col(); j++)
106 _polyCoeffs(i+1,j+1) = coeff(i+1,j+1);
107}
108
109void SquarePolynomialVector::F(const double* point, double* value) const
110{
111 MVector<double> pointV(PointDimension(), 1), valueV(ValueDimension(), 1);
112 for(unsigned int i=0; i<PointDimension(); i++) pointV(i+1) = point[i];
113 F(pointV, valueV);
114 for(unsigned int i=0; i<ValueDimension(); i++) value[i] = valueV(i+1);
115}
116
118 MVector<double>& value) const
119{
120 MVector<double> polyVector(_polyCoeffs.num_col(), 1);
121 MakePolyVector(point, polyVector);
122 MVector<double> answer = _polyCoeffs*polyVector;
123 for(unsigned int i=0; i<ValueDimension(); i++) value(i+1) = answer(i+1);
124}
125
126
128 const MVector<double>& point,
129 MVector<double>& polyVector) const
130{
131 for(unsigned int i=0; i<_polyCoeffs.num_col(); i++) {
132 polyVector(i+1) = 1.;
133 for(unsigned int j=0; j<_polyKeyByVector[_pointDim-1][i].size(); j++)
134 polyVector(i+1) *= point( _polyKeyByVector[_pointDim-1][i][j]+1 );
135 }
136 return polyVector;
137}
138
139double* SquarePolynomialVector::MakePolyVector(const double* point, double* polyVector) const
140{
141 for(unsigned int i=0; i<_polyCoeffs.num_col(); i++)
142 {
143 polyVector[i] = 1.;
144 for(unsigned int j=0; j<_polyKeyByVector[i].size(); j++)
145 polyVector[i] *= point[_polyKeyByVector[_pointDim-1][i][j] ];
146 }
147 return polyVector;
148}
149
150
151void SquarePolynomialVector::IndexByPowerRecursive(std::vector<int> check, size_t check_index, size_t poly_power, std::vector<std::vector<int> >& nearby_points) {
152 check[check_index] = poly_power;
153 nearby_points.push_back(check);
154 if (check_index+1 == check.size())
155 return;
156 for (int i = 1; i < int(poly_power); ++i)
157 IndexByPowerRecursive(check, check_index+1, i, nearby_points);
158 for (int i = 0; i <= int(poly_power); ++i) {
159 check[check_index] = i;
160 IndexByPowerRecursive(check, check_index+1, poly_power, nearby_points);
161 }
162}
163
164std::vector<int> SquarePolynomialVector::IndexByPower(int index, int point_dim) {
165 if (point_dim < 1)
167 "SquarePolynomialVector::IndexByPower",
168 "Point dimension must be > 0"
169 ));
170 while (int(_polyKeyByPower.size()) < point_dim)
171 _polyKeyByPower.push_back(std::vector< std::vector<int> >());
172 if (index < int(_polyKeyByPower[point_dim-1].size()))
173 return _polyKeyByPower[point_dim-1][index];
174 // poly_order 0 means constant term
175 std::vector<std::vector<int> > nearby_points(1, std::vector<int>(point_dim, 0));
176 // poly_order > 0 means corresponding poly terms (1 is linear, 2 is quadratic...)
177 int this_poly_order = 0;
178 while (int(nearby_points.size()) < index+1) {
179 IndexByPowerRecursive(nearby_points[0], 0, this_poly_order+1, nearby_points);
180 this_poly_order += 1;
181 }
182 _polyKeyByPower[point_dim-1] = nearby_points;
183 return _polyKeyByPower[point_dim-1][index];
184}
185
186//Turn int index into an index for element of polynomial
187// e.g. x_1^4 x_2^3 = {1,1,1,1,2,2,2}
188std::vector<int> SquarePolynomialVector::IndexByVector(int index, int point_dim) {
189 while (int(_polyKeyByVector.size()) < point_dim)
190 _polyKeyByVector.push_back(std::vector< std::vector<int> >());
191 // if _polyKeyByVector is big enough, just return the value
192 if (index < int(_polyKeyByVector[point_dim-1].size()))
193 return _polyKeyByVector[point_dim-1][index];
194 // make sure _polyKeyByPower is big enough
195 IndexByPower(index, point_dim);
196 // update _polyKeyByVector with values from _polyKeyByPower
197 for (size_t i = _polyKeyByVector[point_dim-1].size(); i < _polyKeyByPower[point_dim-1].size(); ++i) {
198 _polyKeyByVector[point_dim-1].push_back(std::vector<int>());
199 for (size_t j = 0; j < _polyKeyByPower[point_dim-1][i].size(); ++j)
200 for (int k = 0; k < _polyKeyByPower[point_dim-1][i][j]; ++k)
201 _polyKeyByVector[point_dim-1][i].push_back(j);
202 }
203 return _polyKeyByVector[point_dim-1][index];
204}
205
206unsigned int SquarePolynomialVector::NumberOfPolynomialCoefficients(int pointDimension, int order) {
207 int number = 1;
208 for (int i = 0; i < pointDimension; ++i)
209 number *= order+1;
210 return number;
211}
212
213std::ostream& operator<<(std::ostream& out, const SquarePolynomialVector& spv)
214{
215 if(SquarePolynomialVector::_printHeaders) spv.PrintHeader(out, '.', ' ', 14, true);
216 out << '\n' << spv.GetCoefficientsAsMatrix();
217 return out;
218}
219
220void SquarePolynomialVector::PrintHeader(std::ostream& out, char int_separator, char str_separator, int length, bool pad_at_start) const
221{
222 if(!_polyKeyByPower[_pointDim-1].empty()) PrintContainer< std::vector<int> >(out, _polyKeyByPower[_pointDim-1][0], int_separator, str_separator, length-1, pad_at_start);
223 for(unsigned int i=1; i<_polyCoeffs.num_col(); ++i)
224 PrintContainer<std::vector<int> >(out, _polyKeyByPower[_pointDim-1][i], int_separator, str_separator, length, pad_at_start);
225}
226
227
228template <class Container >
229void SquarePolynomialVector::PrintContainer(std::ostream& out, const Container& container, char T_separator, char str_separator, int length, bool pad_at_start)
230{
231// class Container::iterator it;
232 std::stringstream strstr1("");
233 std::stringstream strstr2("");
234 typename Container::const_iterator it1 = container.begin();
235 typename Container::const_iterator it2 = it1;
236 while(it1!=container.end())
237 {
238 it2++;
239 if(it1 != container.end() && it2 != container.end())
240 strstr1 << (*it1) << T_separator;
241 else strstr1 << (*it1);
242 it1++;
243 }
244
245 if(int(strstr1.str().size()) > length && length > 0) strstr2 << strstr1.str().substr(1, length);
246 else strstr2 << strstr1.str();
247
248 if(!pad_at_start) out << strstr2.str();
249 for(int i=0; i<length - int(strstr2.str().size()); i++) out << str_separator;
250 if(pad_at_start) out << strstr2.str();
251}
252
254 std::vector<int> index = IndexByPower(_polyCoeffs.num_col(), _pointDim);
255 size_t maxPower = *std::max_element(index.begin(), index.end());
256 return maxPower;
257}
258
260 if (derivPower == nullptr) {
262 "SquarePolynomialVector::Deriv",
263 "Derivative points to nullptr"
264 ));
265 }
266 MMatrix<double> newPolyCoeffs(_polyCoeffs.num_row(), _polyCoeffs.num_col(), 0.);
267 std::vector< std::vector<int> > powerKey = _polyKeyByPower[_pointDim-1];
268 for (size_t j = 0; j < _polyCoeffs.num_col(); ++j) {
269 std::vector<int> thisPower = powerKey[j];
270 std::vector<int> newPower(_pointDim);
271 // f(x) = Product(x_i^t_i)
272 // d^n f(x) / Product(d x_j^d_j) =
273 // t_i >= d_j ... Product(x_i^(t_i - d_j) * t_i!/(t_i-d_j)!
274 // t_i < d_j ... 0
275 double newCoeff = 1.;
276 // calculate the coefficient
277 for (size_t k = 0; k < thisPower.size(); ++k) {
278 newPower[k] = thisPower[k] - derivPower[k];
279 if (newPower[k] < 0) {
280 newCoeff = 0.;
281 break;
282 }
283 newCoeff *= gsl_sf_fact(thisPower[k])/gsl_sf_fact(newPower[k]);
284 }
285 // put it in the matrix of coefficients
286 for (size_t k = 0; k < powerKey.size(); ++k) {
287 bool match = true;
288 for (size_t l = 0; l < powerKey[k].size(); ++l) {
289 if (powerKey[k][l] != newPower[l]) {
290 match = false;
291 break;
292 }
293 }
294 if (match) {
295 for (size_t i = 0; i < _polyCoeffs.num_row(); ++i) {
296 newPolyCoeffs(i+1, k+1) = newCoeff*_polyCoeffs(i+1, j+1);
297 }
298 }
299 }
300 }
301 SquarePolynomialVector vec(_pointDim, newPolyCoeffs);
302 return vec;
303}
304
305}
std::ostream & operator<<(std::ostream &out, const Mesh::Iterator &it)
Definition: Mesh.cpp:33
size_t num_col() const
returns number of columns in the matrix
size_t num_row() const
returns number of rows in the matrix
SquarePolynomialVector describes a vector of multivariate polynomials.
static std::vector< std::vector< std::vector< int > > > _polyKeyByVector
static unsigned int NumberOfPolynomialCoefficients(int pointDimension, int order)
void SetCoefficients(int pointDim, MMatrix< double > coeff)
MVector< double > & MakePolyVector(const MVector< double > &point, MVector< double > &polyVector) const
static std::vector< std::vector< std::vector< int > > > _polyKeyByPower
static std::vector< int > IndexByPower(int index, int nInputVariables)
static void PrintContainer(std::ostream &out, const Container &container, char T_separator, char str_separator, int length, bool pad_at_start)
MMatrix< double > GetCoefficientsAsMatrix() const
SquarePolynomialVector Deriv(const int *derivPower) const
void PrintHeader(std::ostream &out, char int_separator='.', char str_separator=' ', int length=14, bool pad_at_start=true) const
void F(const double *point, double *value) const
static std::vector< int > IndexByVector(int index, int nInputVariables)
static void IndexByPowerRecursive(std::vector< int > check, size_t check_index, size_t poly_power, std::vector< std::vector< int > > &nearby_points)
Definition: Vec.h:22