20 #include <gsl/gsl_interp.h>
23 #include "pism/util/interpolation.hh"
24 #include "pism/util/error_handling.hh"
29 const std::vector<double> &input_x,
30 const std::vector<double> &output_x)
32 output_x.data(), output_x.size()) {
37 const double *input_x,
unsigned int input_x_size,
38 const double *output_x,
unsigned int output_x_size) {
41 if (input_x_size < 2) {
42 m_left.resize(output_x_size);
46 for (
unsigned int k = 0;
k < output_x_size; ++
k) {
56 for (
unsigned int i = 0; i < input_x_size - 1; ++i) {
57 if (input_x[i] >= input_x[i + 1]) {
59 "an input grid for interpolation has to be "
60 "strictly increasing");
66 init_linear(input_x, input_x_size, output_x, output_x_size);
69 init_nearest(input_x, input_x_size, output_x, output_x_size);
90 const double *output_x,
unsigned int output_x_size) {
91 assert(input_x_size >= 2);
93 m_left.resize(output_x_size);
98 for (
unsigned int i = 0; i < output_x_size; ++i) {
99 double x = output_x[i];
104 L = gsl_interp_bsearch(input_x, x, 0, input_x_size),
108 if (x >= input_x[
L] and R < input_x_size) {
110 alpha = (x - input_x[
L]) / (input_x[R] - input_x[
L]);
117 assert(
L < input_x_size);
118 assert(R < input_x_size);
156 std::vector<double> result(
m_alpha.size());
165 for (
size_t k = 0;
k <
n; ++
k) {
169 output[
k] = input[
L] +
m_alpha[
k] * (input[R] - input[
L]);
174 const double *output_x,
unsigned int output_x_size) {
176 init_linear(input_x, input_x_size, output_x, output_x_size);
178 for (
unsigned int j = 0; j <
m_alpha.size(); ++j) {
187 const double *output_x,
unsigned int output_x_size) {
188 assert(input_x_size >= 2);
190 m_left.resize(output_x_size);
195 for (
unsigned int i = 0; i < output_x_size; ++i) {
199 size_t L = gsl_interp_bsearch(input_x, output_x[i], 0, input_x_size);
205 assert(
m_left[i] >= 0 and
m_left[i] < (
int)input_x_size);
217 al = gsl_interp_bsearch(x, a, 0, x_size),
218 ar = (a >= x[al] and al + 1 < x_size) ? al + 1 : al,
219 bl = gsl_interp_bsearch(x, b, 0, x_size),
220 br = (b >= x[bl] and bl + 1 < x_size) ? bl + 1 : bl;
222 std::map<size_t, double> result;
224 if (al == bl and ar == br) {
226 result[al] += (b - a);
229 result[al] += (x[ar] - a);
232 for (
size_t k = ar;
k < bl; ++
k) {
233 result[
k] += x[
k + 1] - x[
k];
237 result[bl] += b - x[bl];
249 al = gsl_interp_bsearch(x, a, 0, x_size),
250 ar = (a >= x[al] and al + 1 < x_size) ? al + 1 : al,
251 bl = gsl_interp_bsearch(x, b, 0, x_size),
252 br = (b >= x[bl] and bl + 1 < x_size) ? bl + 1 : bl;
255 alpha_a = (al == ar) ? 0.0 : (a - x[al]) / (x[ar] - x[al]),
256 alpha_b = (bl == br) ? 0.0 : (b - x[bl]) / (x[br] - x[bl]);
258 std::map<size_t, double> result;
260 if (al == bl and ar == br) {
263 result[al] += 0.5 * (2.0 - alpha_a - alpha_b) * (b - a);
264 result[ar] += 0.5 * (alpha_a + alpha_b) * (b - a);
267 result[al] += 0.5 * (1.0 - alpha_a) * (x[ar] - a);
268 result[ar] += 0.5 * (1.0 + alpha_a) * (x[ar] - a);
271 for (
size_t k = ar;
k < bl; ++
k) {
275 result[
L] += 0.5 * (x[R] - x[
L]);
276 result[R] += 0.5 * (x[R] - x[
L]);
280 result[bl] += 0.5 * (2.0 - alpha_b) * (b - x[bl]);
281 result[br] += 0.5 * alpha_b * (b - x[bl]);
316 "invalid integration interval (a >= b)");
321 "unsupported interpolation type");
324 auto weights = (type ==
LINEAR) ?
328 size_t N = x_size - 1;
344 auto W = weights(x, x_size, t0, b);
351 auto W = weights(x, x_size, a, t1);
357 return weights(x, x_size, a, b);
void init_linear(const double *input_x, unsigned int input_x_size, const double *output_x, unsigned int output_x_size)
std::vector< double > m_alpha
Interpolation weights.
Interpolation(InterpolationType type, const std::vector< double > &input_x, const std::vector< double > &output_x)
void init_piecewise_constant(const double *input_x, unsigned int input_x_size, const double *output_x, unsigned int output_x_size)
std::vector< int > m_left
Interpolation indexes.
void init_nearest(const double *input_x, unsigned int input_x_size, const double *output_x, unsigned int output_x_size)
const std::vector< double > & alpha() const
const std::vector< int > & right() const
const std::vector< int > & left() const
std::vector< double > interpolate(const std::vector< double > &input_values) const
Return interpolated values (on the output grid) given input_values on the input grid.
std::vector< int > m_right
#define PISM_ERROR_LOCATION
static std::map< size_t, double > weights_piecewise_linear(const double *x, size_t x_size, double a, double b)
std::map< size_t, double > integration_weights(const double *x, size_t x_size, InterpolationType type, double a, double b)
static std::map< size_t, double > weights_piecewise_constant(const double *x, size_t x_size, double a, double b)