OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
SolveFactory.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 <gsl/gsl_sf_pow_int.h>
29 
31 
34 
35 namespace interpolation {
36 
37 SolveFactory::SolveFactory(int polynomial_order,
38  int smoothing_order,
39  int point_dim,
40  int value_dim,
41  std::vector< std::vector<double> > positions,
42  std::vector< std::vector<double> > deriv_positions,
43  std::vector< std::vector<int> >& deriv_indices)
44 // :FIXME: unused!
45 // : polynomial_order_(polynomial_order), smoothing_order_(smoothing_order)
46 {
48  square_points_ = PPSolveFactory::getNearbyPointsSquares(point_dim, -1, smoothing_order);
50  BuildHInvMatrix(positions, deriv_positions, deriv_indices);
51  MMatrix<double> A_temp(value_dim, n_poly_coeffs_, 0.);
52  square_temp_ = SquarePolynomialVector(point_dim, A_temp);
53 }
54 
56  std::vector< std::vector<double> > positions,
57  std::vector< std::vector<double> > deriv_positions,
58  std::vector< std::vector<int> >& deriv_indices) {
59  int nCoeffs = positions.size();
61  for (int i = 0; i < nCoeffs; ++i) {
62  std::vector<double> poly_vec = MakeSquareVector(positions[i]);
63  for (int j = 0; j < n_poly_coeffs_; ++j) {
64  h_inv_(i+1, j+1) = poly_vec[j];
65  }
66  }
67  for (size_t i = 0; i < deriv_positions.size(); ++i) {
68  std::vector<double> deriv_vec = MakeSquareDerivVector(deriv_positions[i],
69  deriv_indices[i]);
70  for (int j = 0; j < n_poly_coeffs_; ++j) {
71  h_inv_(i+1+nCoeffs, j+1) = deriv_vec[j];
72  }
73  }
74  h_inv_.invert();
75 }
76 
77 std::vector<double> SolveFactory::MakeSquareVector(std::vector<double> x) {
78  std::vector<double> square_vector(square_points_.size(), 1.);
79  for (size_t i = 0; i < square_points_.size(); ++i) {
80  std::vector<int>& point = square_points_[i];
81  for (size_t j = 0; j < point.size(); ++j)
82  square_vector[i] *= gsl_sf_pow_int(x[j], point[j]);
83  }
84  return square_vector;
85 }
86 
87 std::vector<double> SolveFactory::MakeSquareDerivVector(std::vector<double> positions, std::vector<int> deriv_indices) {
88  std::vector<double> deriv_vec(square_deriv_nearby_points_.size(), 1.);
89  int square_deriv_nearby_points_size = square_deriv_nearby_points_.size();
90  int dim = square_deriv_nearby_points_[0].size();
91  for (int i = 0; i < square_deriv_nearby_points_size; ++i) {
92  for (int j = 0; j < dim; ++j) {
93  int power = square_deriv_nearby_points_[i][j] - deriv_indices[j]; // p_j - q_j
94  if (power < 0) {
95  deriv_vec[i] = 0.;
96  break;
97  } else {
98  // x^(p_j-q_j)
99  deriv_vec[i] *= gsl_sf_pow_int(positions[j], power);
100  }
101  // p_j*(p_j-1)*(p_j-2)*...*(p_j-q_j)
102  for (int k = square_deriv_nearby_points_[i][j]; k > power; --k) {
103  deriv_vec[i] *= k;
104  }
105  }
106  }
107  return deriv_vec;
108 }
109 
111  const std::vector< std::vector<double> >& values,
112  const std::vector< std::vector<double> >& deriv_values) {
113  // Algorithm:
114  // define G_i = vector of F_i and d^pF/dF^p with values taken from coeffs
115  // and derivs respectively
116  // define H_ij = vector of f_i and d^pf/df^p)
117  // Then use G = H A => A = H^-1 G
118  // where A is vector of polynomial coefficients
119  // First set up G_i from coeffs and derivs; then calculate H_ij;
120  // then do the matrix inversion
121  // It is an error to include the same polynomial index more than once in
122  // coeffs or derivs or both; any polynomial indices that are missing will be
123  // assigned 0 value; polynomial order will be taken as the maximum
124  // polynomial order from coeffs and derivs.
125  // PointDimension and ValueDimension will be taken from coeffs and derivs;
126  // it is an error if these do not all have the same dimensions.
127 
128  // OPTIMISATION - if we are doing this many times and only changing values,
129  // can reuse H
130  int nCoeffs = values.size();
131  int nDerivs = deriv_values.size();
132  if (values.size()+deriv_values.size() != size_t(n_poly_coeffs_)) {
134  "SolveFactory::PolynomialSolve",
135  "Values and derivatives over or under constrained"
136  );
137  }
138  int valueDim = 0;
139  if (values.size() != 0) {
140  valueDim = values[0].size();
141  } else if (deriv_values.size() != 0) {
142  valueDim = deriv_values[0].size();
143  }
144 
145  MMatrix<double> A(valueDim, n_poly_coeffs_, 0.);
146  for (size_t y_index = 0; y_index < values[0].size(); ++y_index) {
148  // First fill the values
149  for (int i = 0; i < nCoeffs && i < n_poly_coeffs_; ++i) {
150  G(i+1) = values[i][y_index];
151  }
152  // Now fill the derivatives
153  for (int i = 0; i < nDerivs; ++i) {
154  G(i+nCoeffs+1) = deriv_values[i][y_index];
155  }
156  MVector<double> A_vec = h_inv_*G;
157  for (int j = 0; j < n_poly_coeffs_; ++j) {
158  A(y_index+1, j+1) = A_vec(j+1);
159  }
160  }
162  temp->SetCoefficients(A);
163  return temp;
164 }
165 }
166 
SolveFactory(int polynomial_order, int smoothing_order, int point_dim, int value_dim, std::vector< std::vector< double > > positions, std::vector< std::vector< double > > deriv_positions, std::vector< std::vector< int > > &deriv_indices)
std::vector< double > MakeSquareVector(std::vector< double > position)
SquarePolynomialVector * PolynomialSolve(const std::vector< std::vector< double > > &values, const std::vector< std::vector< double > > &deriv_values)
void SetCoefficients(int pointDim, MMatrix< double > coeff)
std::vector< std::vector< int > > square_deriv_nearby_points_
Definition: SolveFactory.h:124
SquarePolynomialVector describes a vector of multivariate polynomials.
std::vector< double > MakeSquareDerivVector(std::vector< double > position, std::vector< int > derivIndices)
std::vector< std::vector< int > > square_points_
Definition: SolveFactory.h:123
SquarePolynomialVector square_temp_
Definition: SolveFactory.h:126
void BuildHInvMatrix(std::vector< std::vector< double > > positions, std::vector< std::vector< double > > deriv_positions, std::vector< std::vector< int > > &deriv_indices)
static std::vector< std::vector< int > > getNearbyPointsSquares(int pointDim, int polyOrderLower, int polyOrderUpper)
void invert()
turns this matrix into its inverse
MMatrix< double > h_inv_
Definition: SolveFactory.h:127
static unsigned int NumberOfPolynomialCoefficients(int pointDimension, int order)