OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
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 <sstream>
29
30#include "Utilities/GSLCompat.h"
31
33
36
37namespace interpolation {
38
40 int smoothing_order, int point_dim, 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) {
46 square_points_ = PPSolveFactory::getNearbyPointsSquares(point_dim, -1, smoothing_order);
47 if (positions.size() + deriv_positions.size() - n_poly_coeffs_ != 0) {
48 std::stringstream ss;
49 ss << "Total size of positions and deriv_positions (" << positions.size() << "+"
50 << deriv_positions.size() << ") should be " << n_poly_coeffs_;
51 throw GeneralOpalException("SolveFactory::SolveFactory", ss.str());
52 }
53 BuildHInvMatrix(positions, deriv_positions, deriv_indices);
54 MMatrix<double> A_temp(value_dim, n_poly_coeffs_, 0.);
55 square_temp_ = SquarePolynomialVector(point_dim, A_temp);
56 }
57
59 std::vector<std::vector<double> > positions,
60 std::vector<std::vector<double> > deriv_positions,
61 std::vector<std::vector<int> >& deriv_indices) {
62 int nCoeffs = positions.size();
64 for (int i = 0; i < nCoeffs; ++i) {
65 std::vector<double> poly_vec = MakeSquareVector(positions[i]);
66 for (int j = 0; j < int(poly_vec.size()); ++j) {
67 h_inv_(i + 1, j + 1) = poly_vec[j];
68 }
69 }
70
71 for (size_t i = 0; i < deriv_positions.size(); ++i) {
72 std::vector<double> deriv_vec =
73 MakeSquareDerivVector(deriv_positions[i], deriv_indices[i]);
74 for (int j = 0; j < n_poly_coeffs_; ++j) {
75 h_inv_(i + 1 + nCoeffs, j + 1) = deriv_vec[j];
76 }
77 }
78 h_inv_.invert();
79 }
80
81 std::vector<double> SolveFactory::MakeSquareVector(std::vector<double> x) {
82 std::vector<double> square_vector(square_points_.size(), 1.);
83 for (size_t i = 0; i < square_points_.size(); ++i) {
84 std::vector<int>& point = square_points_[i];
85 for (size_t j = 0; j < point.size(); ++j)
86 square_vector[i] *= gsl_sf_pow_int(x[j], point[j]);
87 }
88 return square_vector;
89 }
90
92 std::vector<double> x, std::vector<int> deriv_indices) {
93 // vector like Product_i [x_i^{a_i - m_i}*m_i!/(a_i-m_i)]
94 // where:
95 // m_i is given by deriv_indices
96 // a_i are the polynomial vector indices
97
98 std::vector<double> deriv_vec(square_points_.size(), 1.);
99 int square_points_size = square_points_.size();
100 int dim = square_points_[0].size();
101 for (int i = 0; i < square_points_size; ++i) {
102 std::vector<int>& point = square_points_[i];
103 for (int j = 0; j < dim; ++j) {
104 int power = point[j] - deriv_indices[j]; // p_j - q_j
105 if (power < 0) {
106 deriv_vec[i] = 0.;
107 break;
108 } else {
109 // x^(p_j-q_j)
110 deriv_vec[i] *= gsl_sf_pow_int(x[j], power); // x_j^{power}
111 }
112 // p_j*(p_j-1)*(p_j-2)*...*(p_j-q_j)
113 for (int k = point[j]; k > power && k > 0; --k) {
114 deriv_vec[i] *= k;
115 }
116 }
117 }
118 return deriv_vec;
119 }
120
122 const std::vector<std::vector<double> >& values,
123 const std::vector<std::vector<double> >& deriv_values) {
124 // Algorithm:
125 // define G_i = vector of F_i and d^pF/dF^p with values taken from coeffs
126 // and derivs respectively
127 // define H_ij = vector of f_i and d^pf/df^p)
128 // Then use G = H A => A = H^-1 G
129 // where A is vector of polynomial coefficients
130 // First set up G_i from coeffs and derivs; then calculate H_ij;
131 // then do the matrix inversion
132 // It is an error to include the same polynomial index more than once in
133 // coeffs or derivs or both; any polynomial indices that are missing will be
134 // assigned 0 value; polynomial order will be taken as the maximum
135 // polynomial order from coeffs and derivs.
136 // PointDimension and ValueDimension will be taken from coeffs and derivs;
137 // it is an error if these do not all have the same dimensions.
138
139 // OPTIMISATION - if we are doing this many times and only changing values,
140 // can reuse H
141 int nCoeffs = values.size();
142 int nDerivs = deriv_values.size();
143 if (values.size() + deriv_values.size() != size_t(n_poly_coeffs_)) {
145 "SolveFactory::PolynomialSolve",
146 "Values and derivatives over or under constrained");
147 }
148 for (int i = 1; i < nCoeffs && i < n_poly_coeffs_; ++i) {
149 if (values[i].size() < values[0].size()) {
151 "SolveFactory::PolynomialSolve", "The vector of values is too short");
152 }
153 }
154 for (int i = 0; i < nDerivs; ++i) {
155 if (deriv_values[i].size() < values[0].size()) {
157 "SolveFactory::PolynomialSolve",
158 "The vector of derivative values is too short");
159 }
160 }
161
162 int valueDim = 0;
163 if (!values.empty()) {
164 valueDim = values[0].size();
165 } else if (deriv_values.size() != 0) {
166 valueDim = deriv_values[0].size();
167 }
168
169 MMatrix<double> A(valueDim, n_poly_coeffs_, 0.);
170 for (size_t y_index = 0; y_index < values[0].size(); ++y_index) {
172 // First fill the values
173 for (int i = 0; i < nCoeffs && i < n_poly_coeffs_; ++i) {
174 G(i + 1) = values[i][y_index];
175 }
176 // Now fill the derivatives
177 for (int i = 0; i < nDerivs; ++i) {
178 G(i + nCoeffs + 1) = deriv_values[i][y_index];
179 }
180 MVector<double> A_vec = h_inv_ * G;
181 for (int j = 0; j < n_poly_coeffs_; ++j) {
182 A(y_index + 1, j + 1) = A_vec(j + 1);
183 }
184 }
186 temp->SetCoefficients(A);
187 return temp;
188 }
189} // namespace interpolation
double gsl_sf_pow_int(double x, int n)
Integer power .
Definition GSLCompat.h:57
void invert()
turns this matrix into its inverse
static std::vector< std::vector< int > > getNearbyPointsSquares(int pointDim, int polyOrderLower, int polyOrderUpper)
SolveFactory(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 > MakeSquareDerivVector(std::vector< double > position, std::vector< int > derivIndices)
void BuildHInvMatrix(std::vector< std::vector< double > > positions, std::vector< std::vector< double > > deriv_positions, std::vector< std::vector< int > > &deriv_indices)
std::vector< std::vector< int > > square_points_
SquarePolynomialVector * PolynomialSolve(const std::vector< std::vector< double > > &values, const std::vector< std::vector< double > > &deriv_values)
SquarePolynomialVector square_temp_
std::vector< double > MakeSquareVector(std::vector< double > position)
SquarePolynomialVector describes a vector of multivariate polynomials.
static unsigned int NumberOfPolynomialCoefficients(int pointDimension, int order)
void SetCoefficients(int pointDim, MMatrix< double > coeff)