OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
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 #include <math.h>
29 
30 #include <iomanip>
31 #include <sstream>
32 #include <algorithm>
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 {
119  MVector<double> polyVector(_polyCoeffs.num_col(), 1);
120  MakePolyVector(point, polyVector);
121  MVector<double> answer = _polyCoeffs*polyVector;
122  for(unsigned int i=0; i<ValueDimension(); i++) value(i+1) = answer(i+1);
123 }
124 
125 
127 {
128  for(unsigned int i=0; i<_polyCoeffs.num_col(); i++) {
129  polyVector(i+1) = 1.;
130  for(unsigned int j=0; j<_polyKeyByVector[_pointDim-1][i].size(); j++)
131  polyVector(i+1) *= point( _polyKeyByVector[_pointDim-1][i][j]+1 );
132  }
133  return polyVector;
134 }
135 
136 double* SquarePolynomialVector::MakePolyVector(const double* point, double* polyVector) const
137 {
138  for(unsigned int i=0; i<_polyCoeffs.num_col(); i++)
139  {
140  polyVector[i] = 1.;
141  for(unsigned int j=0; j<_polyKeyByVector[i].size(); j++)
142  polyVector[i] *= point[_polyKeyByVector[_pointDim-1][i][j] ];
143  }
144  return polyVector;
145 }
146 
147 
148 void SquarePolynomialVector::IndexByPowerRecursive(std::vector<int> check, size_t check_index, size_t poly_power, std::vector<std::vector<int> >& nearby_points) {
149  check[check_index] = poly_power;
150  nearby_points.push_back(check);
151  if (check_index+1 == check.size())
152  return;
153  for (int i = 1; i < int(poly_power); ++i)
154  IndexByPowerRecursive(check, check_index+1, i, nearby_points);
155  for (int i = 0; i <= int(poly_power); ++i) {
156  check[check_index] = i;
157  IndexByPowerRecursive(check, check_index+1, poly_power, nearby_points);
158  }
159 }
160 
161 std::vector<int> SquarePolynomialVector::IndexByPower(int index, int point_dim) {
162  if (point_dim < 1)
164  "PPSolveFactory::GetNearbyPointsSquares",
165  "Point dimension must be > 0"
166  ));
167  while (int(_polyKeyByPower.size()) < point_dim)
168  _polyKeyByPower.push_back(std::vector< std::vector<int> >());
169  if (index < int(_polyKeyByPower[point_dim-1].size()))
170  return _polyKeyByPower[point_dim-1][index];
171  // poly_order 0 means constant term
172  std::vector<std::vector<int> > nearby_points(1, std::vector<int>(point_dim, 0));
173  // poly_order > 0 means corresponding poly terms (1 is linear, 2 is quadratic...)
174  int this_poly_order = 0;
175  while (int(nearby_points.size()) < index+1) {
176  IndexByPowerRecursive(nearby_points[0], 0, this_poly_order+1, nearby_points);
177  this_poly_order += 1;
178  }
179  _polyKeyByPower[point_dim-1] = nearby_points;
180  return _polyKeyByPower[point_dim-1][index];
181 }
182 
183 //Turn int index into an index for element of polynomial
184 // e.g. x_1^4 x_2^3 = {1,1,1,1,2,2,2}
185 std::vector<int> SquarePolynomialVector::IndexByVector(int index, int point_dim) {
186  while (int(_polyKeyByVector.size()) < point_dim)
187  _polyKeyByVector.push_back(std::vector< std::vector<int> >());
188  // if _polyKeyByVector is big enough, just return the value
189  if (index < int(_polyKeyByVector[point_dim-1].size()))
190  return _polyKeyByVector[point_dim-1][index];
191  // make sure _polyKeyByPower is big enough
192  IndexByPower(index, point_dim);
193  // update _polyKeyByVector with values from _polyKeyByPower
194  for (size_t i = _polyKeyByVector[point_dim-1].size(); i < _polyKeyByPower[point_dim-1].size(); ++i) {
195  _polyKeyByVector[point_dim-1].push_back(std::vector<int>());
196  for (size_t j = 0; j < _polyKeyByPower[point_dim-1][i].size(); ++j)
197  for (int k = 0; k < _polyKeyByPower[point_dim-1][i][j]; ++k)
198  _polyKeyByVector[point_dim-1][i].push_back(j);
199  }
200  return _polyKeyByVector[point_dim-1][index];
201 }
202 
203 unsigned int SquarePolynomialVector::NumberOfPolynomialCoefficients(int pointDimension, int order) {
204  int number = 1;
205  for (int i = 0; i < pointDimension; ++i)
206  number *= order+1;
207  return number;
208 }
209 
210 std::ostream& operator<<(std::ostream& out, const SquarePolynomialVector& spv)
211 {
212  if(SquarePolynomialVector::_printHeaders) spv.PrintHeader(out, '.', ' ', 14, true);
213  out << '\n' << spv.GetCoefficientsAsMatrix();
214  return out;
215 }
216 
217 void SquarePolynomialVector::PrintHeader(std::ostream& out, char int_separator, char str_separator, int length, bool pad_at_start) const
218 {
219  if(_polyKeyByPower[_pointDim-1].size() > 0) PrintContainer< std::vector<int> >(out, _polyKeyByPower[_pointDim-1][0], int_separator, str_separator, length-1, pad_at_start);
220  for(unsigned int i=1; i<_polyCoeffs.num_col(); ++i)
221  PrintContainer<std::vector<int> >(out, _polyKeyByPower[_pointDim-1][i], int_separator, str_separator, length, pad_at_start);
222 }
223 
224 
225 template <class Container >
226 void SquarePolynomialVector::PrintContainer(std::ostream& out, const Container& container, char T_separator, char str_separator, int length, bool pad_at_start)
227 {
228 // class Container::iterator it;
229  std::stringstream strstr1("");
230  std::stringstream strstr2("");
231  typename Container::const_iterator it1 = container.begin();
232  typename Container::const_iterator it2 = it1;
233  while(it1!=container.end())
234  {
235  it2++;
236  if(it1 != container.end() && it2 != container.end())
237  strstr1 << (*it1) << T_separator;
238  else strstr1 << (*it1);
239  it1++;
240  }
241 
242  if(int(strstr1.str().size()) > length && length > 0) strstr2 << strstr1.str().substr(1, length);
243  else strstr2 << strstr1.str();
244 
245  if(!pad_at_start) out << strstr2.str();
246  for(int i=0; i<length - int(strstr2.str().size()); i++) out << str_separator;
247  if(pad_at_start) out << strstr2.str();
248 }
249 
251  std::vector<int> index = IndexByPower(_polyCoeffs.num_col(), _pointDim);
252  size_t maxPower = *std::max_element(index.begin(), index.end());
253  return maxPower;
254 }
255 
256 
257 }
static std::vector< int > IndexByPower(int index, int nInputVariables)
void PrintHeader(std::ostream &out, char int_separator='.', char str_separator=' ', int length=14, bool pad_at_start=true) const
static std::vector< std::vector< std::vector< int > > > _polyKeyByPower
void SetCoefficients(int pointDim, MMatrix< double > coeff)
static void IndexByPowerRecursive(std::vector< int > check, size_t check_index, size_t poly_power, std::vector< std::vector< int > > &nearby_points)
MVector< double > & MakePolyVector(const MVector< double > &point, MVector< double > &polyVector) const
size_t num_col() const
returns number of columns in the matrix
void F(const double *point, double *value) const
static std::vector< std::vector< std::vector< int > > > _polyKeyByVector
static void PrintContainer(std::ostream &out, const Container &container, char T_separator, char str_separator, int length, bool pad_at_start)
SquarePolynomialVector describes a vector of multivariate polynomials.
MMatrix< double > GetCoefficientsAsMatrix() const
static std::vector< int > IndexByVector(int index, int nInputVariables)
static unsigned int NumberOfPolynomialCoefficients(int pointDimension, int order)
std::ostream & operator<<(std::ostream &out, const Mesh::Iterator &it)
Definition: Mesh.cpp:33
size_t num_row() const
returns number of rows in the matrix