OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
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 
42 namespace interpolation {
43 
45 std::vector< std::vector< std::vector<int> > > SquarePolynomialVector::_polyKeyByPower;
46 std::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 
59 SquarePolynomialVector::SquarePolynomialVector(int numberOfInputVariables, MMatrix<double> polynomialCoefficients)
60  : _pointDim(numberOfInputVariables), _polyCoeffs(polynomialCoefficients) {
61  SetCoefficients(numberOfInputVariables, polynomialCoefficients);
62 }
63 
64 SquarePolynomialVector::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 
77 void 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.);
90  if (int(_polyKeyByVector.size()) < _pointDim || _polyKeyByVector[_pointDim-1].size() < _polyCoeffs.num_col())
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 
109 void 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 
139 double* 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 
151 void 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 
164 std::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}
188 std::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 
206 unsigned 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 
213 std::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 
220 void SquarePolynomialVector::PrintHeader(std::ostream& out, char int_separator, char str_separator, int length, bool pad_at_start) const
221 {
222  if(_polyKeyByPower[_pointDim-1].size() > 0) 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 
228 template <class Container >
229 void 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 == NULL) {
262  "SquarePolynomialVector::Deriv",
263  "Derivative points to NULL"
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)
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)
MMatrix< double > GetCoefficientsAsMatrix() const
Definition: Vec.h:22