PolyFEM
Loading...
Searching...
No Matches
RBFInterpolation.cpp
Go to the documentation of this file.
2
4#include <cmath>
5#include <iostream>
6
7namespace polyfem
8{
9 namespace utils
10 {
11 RBFInterpolation::RBFInterpolation(const Eigen::MatrixXd &fun, const Eigen::MatrixXd &pts, const std::string &rbf, const double eps)
12 {
13 init(fun, pts, rbf, eps);
14 }
15
16 void RBFInterpolation::init(const Eigen::MatrixXd &fun, const Eigen::MatrixXd &pts, const std::string &rbf, const double eps)
17 {
18 assert(pts.rows() >= 0);
19#ifdef POLYFEM_OPENCL
20 std::vector<double> pointscl(pts.size());
21 std::vector<double> functioncl(fun.rows());
22
23 int index = 0;
24 for (int i = 0; i < pts.rows(); ++i)
25 {
26 for (int j = 0; j < pts.cols(); ++j)
27 {
28 pointscl[index++] = pts(i, j);
29 }
30 }
31
32 data_.resize(fun.cols());
33 for (int i = 0; i < fun.cols(); ++i)
34 {
35 index = 0;
36
37 for (int j = 0; j < fun.rows(); ++j)
38 functioncl[index] = fun(j, i);
39
40 rbf_pum::init(pointscl, functioncl, data_[i], verbose_, rbfcl_, opt_, unit_cube_, num_threads_);
41 }
42#else
43 std::function<double(double)> tmp;
44
45 if (rbf == "multiquadric")
46 {
47 tmp = [eps](const double r) { return sqrt((r / eps) * (r / eps) + 1); };
48 }
49 else if (rbf == "inverse" || rbf == "inverse_multiquadric" || rbf == "inverse multiquadric")
50 {
51 tmp = [eps](const double r) { return 1.0 / sqrt((r / eps) * (r / eps) + 1); };
52 }
53 else if (rbf == "gaussian")
54 {
55 tmp = [eps](const double r) { return exp(-(r / eps) * (r / eps)); };
56 }
57 else if (rbf == "linear")
58 {
59 tmp = [](const double r) { return r; };
60 }
61 else if (rbf == "cubic")
62 {
63 tmp = [](const double r) { return r * r * r; };
64 }
65 else if (rbf == "quintic")
66 {
67 tmp = [](const double r) { return r * r * r * r * r; };
68 }
69 else if (rbf == "thin_plate" || rbf == "thin-plate")
70 {
71 tmp = [](const double r) { return abs(r) < 1e-10 ? 0 : (r * r * log(r)); };
72 }
73 else
74 {
75 logger().warn("Unable to match {} rbf, falling back to multiquadric", rbf);
76 assert(false);
77
78 tmp = [eps](const double r) { return sqrt((r / eps) * (r / eps) + 1); };
79 }
80
81 init(fun, pts, tmp);
82#endif
83 }
84
85 RBFInterpolation::RBFInterpolation(const Eigen::MatrixXd &fun, const Eigen::MatrixXd &pts, const std::function<double(double)> &rbf)
86 {
87#ifdef POLYFEM_OPENCL
88 assert(false);
89#else
90 init(fun, pts, rbf);
91#endif
92 }
93
94 void RBFInterpolation::init(const Eigen::MatrixXd &fun, const Eigen::MatrixXd &pts, const std::function<double(double)> &rbf)
95 {
96#ifdef POLYFEM_OPENCL
97 assert(false);
98#else
99 assert(pts.rows() >= 0);
100 assert(pts.rows() == fun.rows());
101
102 rbf_ = rbf;
103 centers_ = pts;
104
105 const int n = centers_.rows();
106
107 Eigen::MatrixXd A(n, n);
108
109 for (int i = 0; i < n; ++i)
110 {
111 for (int j = 0; j < n; ++j)
112 {
113 A(i, j) = rbf((centers_.row(i) - centers_.row(j)).norm());
114 }
115 }
116
117 Eigen::FullPivLU<Eigen::MatrixXd> lu(A);
118
119 weights_.resize(n, fun.cols());
120 for (long i = 0; i < fun.cols(); ++i)
121 {
122 weights_.col(i) = lu.solve(fun.col(i));
123 }
124#endif
125 }
126
127 Eigen::MatrixXd RBFInterpolation::interpolate(const Eigen::MatrixXd &pts) const
128 {
129#ifdef POLYFEM_OPENCL
130 Eigen::MatrixXd res(pts.rows(), data_.size());
131
132 std::vector<double> pointscl(pts.size());
133 int index = 0;
134 for (int i = 0; i < pts.rows(); ++i)
135 {
136 for (int j = 0; j < pts.cols(); ++j)
137 {
138 pointscl[index++] = pts(i, j);
139 }
140 }
141
142 std::vector<double> tmp;
143 for (size_t i = 0; i < data_.size(); ++i)
144 {
145 rbf_pum::interpolate(data_[i], pointscl, tmp, verbose_, rbfcl_, opt_, unit_cube_, num_threads_);
146
147 for (size_t j = 0; j < tmp.size(); ++j)
148 res(j, i) = tmp[j];
149 }
150#else
151 assert(pts.cols() == centers_.cols());
152 const int n = centers_.rows();
153 const int m = pts.rows();
154
155 Eigen::MatrixXd mat(m, n);
156 for (int i = 0; i < m; ++i)
157 {
158 for (int j = 0; j < n; ++j)
159 {
160 mat(i, j) = rbf_((centers_.row(j) - pts.row(i)).norm());
161 }
162 }
163
164 const Eigen::MatrixXd res = mat * weights_;
165#endif
166 return res;
167 }
168 } // namespace utils
169} // namespace polyfem
void init(const Eigen::MatrixXd &fun, const Eigen::MatrixXd &pts, const std::function< double(double)> &rbf)
Eigen::MatrixXd interpolate(const Eigen::MatrixXd &pts) const
std::function< double(double)> rbf_
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:42