13 #include "Interpolator.h"
17 #include "linalg/Matrix.h"
18 #include "linalg/scalapack_wrapper.h"
22 #if __cplusplus >= 201103L
25 #include <boost/shared_ptr.hpp>
32 Interpolator::Interpolator(
const std::vector<Vector> & parameter_points,
33 const std::vector<std::shared_ptr<Matrix>> & rotation_matrices,
36 std::string interp_method,
37 double closest_rbf_val,
38 bool compute_gradients)
40 CAROM_VERIFY(parameter_points.size() == rotation_matrices.size());
41 CAROM_VERIFY(parameter_points.size() > 1);
42 CAROM_VERIFY(rbf ==
"G" || rbf ==
"IQ" || rbf ==
"IMQ");
43 CAROM_VERIFY(interp_method ==
"LS" || interp_method ==
"IDW"
44 || interp_method ==
"LP");
45 CAROM_VERIFY(closest_rbf_val >= 0.0 && closest_rbf_val <= 1.0);
49 MPI_Initialized(&mpi_init);
51 MPI_Init(
nullptr,
nullptr);
54 MPI_Comm_rank(MPI_COMM_WORLD, &d_rank);
55 MPI_Comm_size(MPI_COMM_WORLD, &d_num_procs);
57 d_compute_gradients = compute_gradients;
58 d_parameter_points = parameter_points;
59 d_rotation_matrices = rotation_matrices;
60 d_ref_point = ref_point;
62 d_interp_method = interp_method;
67 const std::vector<Vector> & parameter_points,
68 const std::string & interp_method,
const std::string & rbf,
double epsilon,
71 std::vector<double> rbfs;
72 if (interp_method ==
"LS")
74 for (
int i = 0; i < parameter_points.size(); i++)
76 rbfs.push_back(
obtainRBF(rbf, epsilon, point, parameter_points[i]));
79 else if (interp_method ==
"IDW")
81 bool distance_is_zero =
false;
82 for (
int i = 0; i < parameter_points.size(); i++)
84 rbfs.push_back(
obtainRBF(rbf, epsilon, point, parameter_points[i]));
85 if (rbfs.back() == 1.0)
87 distance_is_zero =
true;
92 for (
int i = 0; i < rbfs.size(); i++)
101 else if (interp_method ==
"LP")
103 for (
int i = 0; i < parameter_points.size(); i++)
107 for (
int j = 0; j < parameter_points.size(); j++)
114 Vector numerator_vec, denomenator_vec;
115 point.
minus(parameter_points[j], numerator_vec);
116 parameter_points[i].minus(parameter_points[j], denomenator_vec);
117 double numerator = numerator_vec.
norm();
118 double denomenator = denomenator_vec.
norm();
122 coeff = (numerator / denomenator);
127 coeff *= (numerator / denomenator);
130 rbfs.push_back(coeff);
137 const std::vector<Vector> & parameter_points,
138 const std::string & interp_method,
const std::string & rbf,
double epsilon,
139 const Vector & point,
const int index)
141 std::vector<double> rbfs;
142 if (interp_method ==
"LS")
144 for (
int i = 0; i < parameter_points.size(); i++)
152 CAROM_ERROR(
"Interpolated gradients are only implemented for \"LS\"");
158 const Vector & point2,
const int index)
161 point1.
minus(point2, diff);
162 const double eps_norm_squared = epsilon * epsilon * diff.
norm2();
169 res = -2.0*epsilon*epsilon*diff.
item(index)*std::exp(-eps_norm_squared);
172 else if (rbf ==
"IQ")
175 res = -2.0*epsilon*epsilon*diff.
item(index)/((1.0+eps_norm_squared)*
176 (1.0+eps_norm_squared));
180 else if (rbf ==
"IMQ")
183 res = -epsilon*epsilon*diff.
item(index)/(std::sqrt(1.0+eps_norm_squared)*
184 (1.0+eps_norm_squared));
193 for (
int i = 0; i < rbf.size(); i++)
204 point1.
minus(point2, diff);
205 const double eps_norm_squared = epsilon * epsilon * diff.
norm2();
211 res = std::exp(-eps_norm_squared);
214 else if (rbf ==
"IQ")
216 res = 1.0 / (1.0 + eps_norm_squared);
219 else if (rbf ==
"IMQ")
221 res = 1.0 / std::sqrt(1.0 + eps_norm_squared);
228 const std::string & rbf,
double closest_rbf_val)
230 double closest_point_dist = INT_MAX;
232 for (
int i = 0; i < parameter_points.size(); i++)
234 for (
int j = 0; j < parameter_points.size(); j++)
242 parameter_points[i].
minus(parameter_points[j], diff);
243 double dist = diff.
norm2();
244 if (dist < closest_point_dist)
246 closest_point_dist = dist;
251 epsilon = std::sqrt(-std::log(closest_rbf_val) / diff.
norm2());
254 else if (rbf ==
"IQ")
256 epsilon = std::sqrt(((1.0 / closest_rbf_val) - 1.0) / diff.
norm2());
259 else if (rbf ==
"IMQ")
261 epsilon = std::sqrt((std::pow(1.0 / closest_rbf_val, 2) - 1.0) / diff.
norm2());
271 const std::vector<Vector> & parameter_points,
272 const std::vector<std::shared_ptr<Matrix>> & bases,
279 MPI_Initialized(&mpi_init);
281 MPI_Init(
nullptr,
nullptr);
284 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
285 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
287 std::vector<std::shared_ptr<Matrix>> rotation_matrices;
291 for (
int i = 0; i < parameter_points.size(); i++)
293 CAROM_VERIFY(bases[i]->numRows() == bases[ref_point]->numRows());
294 CAROM_VERIFY(bases[i]->numColumns() == bases[ref_point]->numColumns());
295 CAROM_VERIFY(bases[i]->distributed() == bases[ref_point]->distributed());
301 std::shared_ptr<Matrix> identity_matrix(
new Matrix(bases[i]->numColumns(),
302 bases[i]->numColumns(),
false));
303 for (
int j = 0; j < identity_matrix->numColumns(); j++) {
304 identity_matrix->item(j, j) = 1.0;
306 rotation_matrices.push_back(identity_matrix);
310 std::unique_ptr<Matrix> basis_mult_basis = bases[i]->transposeMult(
312 Matrix basis(basis_mult_basis->numRows(),
313 basis_mult_basis->numColumns(),
false);
314 Matrix basis_right(basis_mult_basis->numColumns(),
315 basis_mult_basis->numColumns(),
false);
322 Vector sv(basis_mult_basis->numColumns(),
false);
323 SerialSVD(basis_mult_basis.get(), &basis_right, &sv, &basis);
329 MPI_Bcast(basis_right.
getData(),
334 rotation_matrices.push_back(basis.
mult(basis_right));
337 return rotation_matrices;
340 std::unique_ptr<std::vector<Vector>>
341 scalarsToVectors(
const std::vector<double> & s)
343 std::vector<Vector> *v =
new std::vector<Vector>(s.size());
344 for (
int i=0; i<s.size(); ++i)
350 return std::unique_ptr<std::vector<Vector>>(v);
double * getData() const
Get the matrix data as a pointer.
int numColumns() const
Returns the number of columns in the Matrix. This method will return the same value from each process...
int numRows() const
Returns the number of rows of the Matrix on this processor.
std::unique_ptr< Matrix > mult(const Matrix &other) const
Multiplies this Matrix with other and returns the product.
double norm() const
Form the norm of this.
std::unique_ptr< Vector > minus(const Vector &other) const
Subtracts other and this and returns the result.
const double & item(int i) const
Const Vector member access.
double norm2() const
Form the squared norm of this.
double rbfWeightedSum(std::vector< double > &rbf)
Compute the sum of the RBF weights.
std::vector< std::shared_ptr< Matrix > > obtainRotationMatrices(const std::vector< Vector > ¶meter_points, const std::vector< std::shared_ptr< Matrix >> &bases, int ref_point)
Obtain the rotation matrices for all the parameter points using the basis of the reference point.
std::vector< double > obtainRBFGradientToTrainingPoints(const std::vector< Vector > ¶meter_points, const std::string &interp_method, const std::string &rbf, double epsilon, const Vector &point, const int index)
Compute the RBF gradient from the parameter points with the unsampled parameter point.
std::vector< double > obtainRBFToTrainingPoints(const std::vector< Vector > ¶meter_points, const std::string &interp_method, const std::string &rbf, double epsilon, const Vector &point)
Compute the RBF from the parameter points with the unsampled parameter point.
double convertClosestRBFToEpsilon(const std::vector< Vector > ¶meter_points, const std::string &rbf, double closest_rbf_val)
Convert closest RBF value to an epsilon value.
void SerialSVD(Matrix *A, Matrix *U, Vector *S, Matrix *V)
Computes the SVD of a undistributed matrix in serial.
double obtainRBF(std::string rbf, double epsilon, const Vector &point1, const Vector &point2)
Compute the RBF between two points.
double obtainRBFGradient(std::string rbf, double epsilon, const Vector &point1, const Vector &point2, const int index)
Compute the RBF gradient between two points.