5 std::vector<std::vector<std::array<double, 16>>>
11 int transpose(std::vector<std::vector<double>>& mat) {
12 std::vector<std::vector<double>> new_mat;
13 for (
unsigned j = 0; j < mat[0].size(); ++j) {
14 std::vector<double> new_line;
15 for (
unsigned i = 0; i < mat.size(); ++i) {
16 new_line.push_back(mat[i][j]);
18 new_mat.push_back(new_line);
24 std::vector<std::vector<double>>
diff(
const std::vector<double>& x,
25 const std::vector<std::vector<double>>& f,
27 std::vector<std::vector<double>> der;
28 unsigned Ny = f[0].size();
29 unsigned Nx = f.size();
36 for (
unsigned j = 0; j < Ny; ++j) {
37 std::vector<double> der_;
39 tang = (f[1][j] - f[0][j]) / hi;
40 px = (f[1][j] - f[0][j] + tang * hi) / (2. * hi);
42 for (
unsigned i = 1; i < Nx - 1; ++i) {
43 px = (f[i + 1][j] - f[i - 1][j]) / (x[i + 1] - x[i - 1]);
46 hi = x[Nx - 1] - x[Nx - 2];
47 tang = (f[Nx - 1][j] - f[Nx - 2][j]) / hi;
48 px = (tang * hi + f[Nx - 1][j] - f[Nx - 2][j]) / (2. * hi);
58 for (
unsigned i = 0; i < Nx; ++i) {
59 std::vector<double> der_;
62 tang = (f[i][1] - f[i][0]) / hi;
63 py = (f[i][1] - f[i][0] + tang * hi) / (2. * hi);
65 for (
unsigned j = 1; j < Ny - 1; ++j) {
66 py = (f[i][j + 1] - f[i][j - 1]) / (x[j + 1] - x[j - 1]);
69 hi = x[Ny - 1] - x[Ny - 2];
70 tang = (f[i][Ny - 1] - f[i][Ny - 2]) / hi;
71 py = (f[i][Ny - 1] - f[i][Ny - 2] + tang * hi) / (2. * hi);
80 std::array<std::vector<std::vector<double>>, 3>
82 const std::vector<double>& x,
const std::vector<double>& y,
83 const std::vector<std::vector<double>>& f) {
84 std::array<std::vector<std::vector<double>>, 3> der;
85 der[0] =
diff(x, f, 0);
86 der[1] =
diff(y, f, 1);
87 der[2] =
diff(y, der[0], 1);
92 const std::vector<double>& y,
93 const std::vector<std::vector<double>>& f) {
98 std::vector<std::vector<std::array<double, 16>>> coefs;
99 for (
unsigned i = 0; i < x.size() - 1; ++i) {
100 double dx = x[i + 1] - x[i];
101 std::vector<std::array<double, 16>> coef;
102 for (
unsigned j = 0; j < y.size() - 1; ++j) {
103 std::array<double, 16> x_;
104 std::array<double, 16> alpha;
106 double dy = y[j + 1] - y[j];
107 double dxdy = dx * dy;
109 x_[0] = f[i][j], x_[1] = f[i + 1][j], x_[2] = f[i][j + 1],
110 x_[3] = f[i + 1][j + 1];
111 x_[4] = derivative[0][i][j] * dx, x_[5] = derivative[0][i + 1][j] * dx,
112 x_[6] = derivative[0][i][j + 1] * dx,
113 x_[7] = derivative[0][i + 1][j + 1] * dx;
114 x_[8] = derivative[1][i][j] * dy, x_[9] = derivative[1][i + 1][j] * dy,
115 x_[10] = derivative[1][i][j + 1] * dy,
116 x_[11] = derivative[1][i + 1][j + 1] * dy;
117 x_[12] = derivative[2][i][j] * dxdy,
118 x_[13] = derivative[2][i + 1][j] * dxdy,
119 x_[14] = derivative[2][i][j + 1] * dxdy,
120 x_[15] = derivative[2][i + 1][j + 1] * dxdy;
122 alpha[0] = x_[0], alpha[1] = x_[4],
123 alpha[2] = 3 * (x_[1] - x_[0]) - 2. * x_[4] - x_[5];
124 alpha[3] = 2. * (x_[0] - x_[1]) + x_[4] + x_[5], alpha[4] = x_[8],
126 alpha[6] = 3. * (x_[9] - x_[8]) - 2. * x_[12] - x_[13],
127 alpha[7] = 2. * (x_[8] - x_[9]) + x_[12] + x_[13];
128 alpha[8] = 3. * (x_[2] - x_[0]) - 2. * x_[8] - x_[10],
129 alpha[9] = 3. * (x_[6] - x_[4]) - 2. * x_[12] - x_[14];
130 alpha[10] = 9. * (x_[0] - x_[1] - x_[2] + x_[3]) +
131 6. * (x_[4] - x_[6] + x_[8] - x_[9]) +
132 3. * (x_[5] - x_[7] + x_[10] - x_[11]) + 4. * x_[12] +
133 2. * (x_[13] + x_[14]) + x_[15];
134 alpha[11] = 6. * (-x_[0] + x_[1] + x_[2] - x_[3]) +
135 3. * (-x_[4] - x_[5] + x_[6] + x_[7]) +
136 4. * (-x_[8] + x_[9]) +
137 2. * (x_[11] - x_[10] - x_[12] - x_[13]) - x_[14] - x_[15];
138 alpha[12] = 2. * (x_[0] - x_[2]) + x_[8] + x_[10],
139 alpha[13] = 2. * (x_[4] - x_[6]) + x_[12] + x_[14];
140 alpha[14] = 6. * (-x_[0] + x_[1] + x_[2] - x_[3]) +
141 4. * (-x_[4] + x_[6]) + 2. * (-x_[5] + x_[7]) +
142 3. * (-x_[8] + x_[9] - x_[10] + x_[11]) +
143 2. * (-x_[12] - x_[14]) - x_[13] - x_[15];
144 alpha[15] = 4. * (x_[0] - x_[1] - x_[2] + x_[3]) +
145 2. * (x_[4] + x_[5] - x_[6] - x_[7] + x_[8] - x_[9] + x_[10] -
147 x_[12] + x_[13] + x_[14] + x_[15];
149 coef.push_back(alpha);
151 coefs.push_back(coef);
157 int binsearch(
const std::vector<double>& x,
const double value) {
159 if (value >= x[x.size() - 1])
164 int RB = x.size() - 1;
170 mid = (LB + RB) >> 1;
172 if (value < d && value >= x[mid - 1])
174 else if (value >= d && value < x[mid + 1])
188 if (x_ <= this->x[0]) {
189 x_ev = this->x[0], i0 = 0;
190 }
else if (x_ >= this->x[this->x.size() - 1]) {
191 x_ev = this->x[this->x.size() - 1], i0 = this->x.size() - 2;
195 if (y_ <= this->y[0]) {
196 y_ev = this->y[0], j0 = 0;
197 }
else if (y_ >= this->y[this->y.size() - 1]) {
198 y_ev = this->y[this->y.size() - 1], j0 = this->y.size() - 2;
202 auto coef = this->a[i0][j0];
203 double dx = this->x[i0 + 1] - this->x[i0];
204 double dy = this->y[j0 + 1] - this->y[j0];
205 double xbar = (x_ev - this->x[i0]) / dx;
206 double ybar = (y_ev - this->y[j0]) / dy;
208 std::array<double, 4> xi{1., xbar, xbar * xbar, xbar * xbar * xbar};
209 std::array<double, 4> yi{1., ybar, ybar * ybar, ybar * ybar * ybar};
215 for (
int j = 0; j < 4; ++j)
216 for (
int i = 0; i < 4; ++i)
217 sum += coef[4 * j + i] * xi[i] * yi[j];
225 if (x_ <= this->x[0]) {
226 x_ev = this->x[0], i0 = 0;
227 }
else if (x_ >= this->x[this->x.size() - 1]) {
228 x_ev = this->x[this->x.size() - 1], i0 = this->x.size() - 2;
232 if (y_ <= this->y[0]) {
233 y_ev = this->y[0], j0 = 0;
234 }
else if (y_ >= this->y[this->y.size() - 1]) {
235 y_ev = this->y[this->y.size() - 1], j0 = this->y.size() - 2;
240 auto coef = this->a[i0][j0];
241 double dx = this->x[i0 + 1] - this->x[i0];
242 double dy = this->y[j0 + 1] - this->y[j0];
243 double xbar = (x_ev - this->x[i0]) / dx;
244 double ybar = (y_ev - this->y[j0]) / dy;
246 std::array<double, 4> xi{0., 1. / dx, 2. * xbar / dx, 3. * xbar * xbar / dx};
247 std::array<double, 4> yi{1., ybar, ybar * ybar, ybar * ybar * ybar};
251 for (
int j = 0; j < 4; ++j)
252 for (
int i = 1; i < 4; ++i)
253 sum += coef[4 * j + i] * xi[i] * yi[j];
261 if (x_ <= this->x[0]) {
262 x_ev = this->x[0], i0 = 0;
263 }
else if (x_ >= this->x[this->x.size() - 1]) {
264 x_ev = this->x[this->x.size() - 1], i0 = this->x.size() - 2;
268 if (y_ <= this->y[0]) {
269 y_ev = this->y[0], j0 = 0;
270 }
else if (y_ >= this->y[this->y.size() - 1]) {
271 y_ev = this->y[this->y.size() - 1], j0 = this->y.size() - 2;
276 auto coef = this->a[i0][j0];
277 double dx = this->x[i0 + 1] - this->x[i0];
278 double dy = this->y[j0 + 1] - this->y[j0];
279 double xbar = (x_ev - this->x[i0]) / dx;
280 double ybar = (y_ev - this->y[j0]) / dy;
282 std::array<double, 4> xi{1., xbar, xbar * xbar, xbar * xbar * xbar};
283 std::array<double, 4> yi{0., 1. / dy, 2. * ybar / dy, 3. * ybar * ybar / dy};
287 for (
int j = 1; j < 4; ++j)
288 for (
int i = 0; i < 4; ++i)
289 sum += coef[4 * j + i] * xi[i] * yi[j];
297 if (x_ <= this->x[0]) {
298 x_ev = this->x[0], i0 = 0;
299 }
else if (x_ >= this->x[this->x.size() - 1]) {
300 x_ev = this->x[this->x.size() - 1], i0 = this->x.size() - 2;
304 if (y_ <= this->y[0]) {
305 y_ev = this->y[0], j0 = 0;
306 }
else if (y_ >= this->y[this->y.size() - 1]) {
307 y_ev = this->y[this->y.size() - 1], j0 = this->y.size() - 2;
312 auto coef = this->a[i0][j0];
313 double dx = this->x[i0 + 1] - this->x[i0];
314 double dy = this->y[j0 + 1] - this->y[j0];
315 double xbar = (x_ev - this->x[i0]) / dx;
316 double ybar = (y_ev - this->y[j0]) / dy;
318 std::array<double, 4> xi{0., 0., 2. / (dx * dx), 6. * xbar / (dx * dx)};
319 std::array<double, 4> yi{1., ybar, ybar * ybar, ybar * ybar * ybar};
323 for (
int j = 0; j < 4; ++j)
324 for (
int i = 2; i < 4; ++i)
325 sum += coef[4 * j + i] * xi[i] * yi[j];
333 if (x_ <= this->x[0]) {
334 x_ev = this->x[0], i0 = 0;
335 }
else if (x_ >= this->x[this->x.size() - 1]) {
336 x_ev = this->x[this->x.size() - 1], i0 = this->x.size() - 2;
340 if (y_ <= this->y[0]) {
341 y_ev = this->y[0], j0 = 0;
342 }
else if (y_ >= this->y[this->y.size() - 1]) {
343 y_ev = this->y[this->y.size() - 1], j0 = this->y.size() - 2;
348 auto coef = this->a[i0][j0];
349 double dx = this->x[i0 + 1] - this->x[i0];
350 double dy = this->y[j0 + 1] - this->y[j0];
351 double xbar = (x_ev - this->x[i0]) / dx;
352 double ybar = (y_ev - this->y[j0]) / dy;
354 std::array<double, 4> xi{1., xbar, xbar * xbar, xbar * xbar * xbar};
355 std::array<double, 4> yi{0., 0., 2. / (dy * dy), 6. * ybar / (dy * dy)};
359 for (
int j = 2; j < 4; ++j)
360 for (
int i = 0; i < 4; ++i)
361 sum += coef[4 * j + i] * xi[i] * yi[j];
369 if (x_ <= this->x[0]) {
370 x_ev = this->x[0], i0 = 0;
371 }
else if (x_ >= this->x[this->x.size() - 1]) {
372 x_ev = this->x[this->x.size() - 1], i0 = this->x.size() - 2;
376 if (y_ <= this->y[0]) {
377 y_ev = this->y[0], j0 = 0;
378 }
else if (y_ >= this->y[this->y.size() - 1]) {
379 y_ev = this->y[this->y.size() - 1], j0 = this->y.size() - 2;
384 auto coef = this->a[i0][j0];
385 double dx = this->x[i0 + 1] - this->x[i0];
386 double dy = this->y[j0 + 1] - this->y[j0];
387 double xbar = (x_ev - this->x[i0]) / dx;
388 double ybar = (y_ev - this->y[j0]) / dy;
390 std::array<double, 4> xi{0., 1. / dx, 2. * xbar / dx, 3. * xbar * xbar / dx};
391 std::array<double, 4> yi{0., 1. / dy, 2. * ybar / dy, 3. * ybar * ybar / dy};
395 for (
int j = 1; j < 4; ++j)
396 for (
int i = 1; i < 4; ++i)
397 sum += coef[4 * j + i] * xi[i] * yi[j];
402 int dx,
int dy)
const {
403 if (dx == 1 && dy == 0)
405 if (dx == 2 && dy == 0)
407 if (dx == 0 && dy == 1)
409 if (dx == 0 && dy == 2)
411 if (dx == 1 && dy == 1)
413 std::cout <<
"dx + dy must be less than 2"
int transpose(std::vector< std::vector< double >> &mat)
std::vector< std::vector< double > > diff(const std::vector< double > &x, const std::vector< std::vector< double >> &f, const int dim=1)
int binsearch(const std::vector< double > &x, const double value)
void fit(const std::vector< double > &x, const std::vector< double > &y, const std::vector< std::vector< double >> &f)
double derivative_yy(double x_, double y_) const
double derivative_xy(double x_, double y_) const
double derivative_x(double x_, double y_) const
double derivative_y(double x_, double y_) const
double partial_derivative(double x_, double y_, int dx, int dy) const
std::vector< std::vector< std::array< double, 16 > > > get_coefs() const
std::array< std::vector< std::vector< double > >, 3 > weighted_finite_derivative(const std::vector< double > &x, const std::vector< double > &y, const std::vector< std::vector< double >> &f)
double eval(double x_, double y_) const
double derivative_xx(double x_, double y_) const