21#include <gsl/gsl_interp.h>
24#include "pism/util/Interpolation1D.hh"
25#include "pism/util/error_handling.hh"
30 const std::vector<double> &input_x,
31 const std::vector<double> &output_x)
33 output_x.data(), output_x.size()) {
38 const double *input_x,
unsigned int input_x_size,
39 const double *output_x,
unsigned int output_x_size) {
42 if (input_x_size < 2) {
43 m_left.resize(output_x_size);
47 for (
unsigned int k = 0;
k < output_x_size; ++
k) {
57 for (
unsigned int i = 0; i < input_x_size - 1; ++i) {
58 if (input_x[i] >= input_x[i + 1]) {
60 "an input grid for interpolation has to be "
61 "strictly increasing");
67 init_linear(input_x, input_x_size, output_x, output_x_size);
70 init_nearest(input_x, input_x_size, output_x, output_x_size);
91 const double *output_x,
unsigned int output_x_size) {
92 assert(input_x_size >= 2);
94 m_left.resize(output_x_size);
99 for (
unsigned int i = 0; i < output_x_size; ++i) {
100 double x = output_x[i];
105 L = gsl_interp_bsearch(input_x, x, 0, input_x_size),
109 if (x >= input_x[
L] and R < input_x_size) {
111 alpha = (x - input_x[
L]) / (input_x[R] - input_x[
L]);
118 assert(
L < input_x_size);
119 assert(R < input_x_size);
122 m_left[i] =
static_cast<int>(
L);
123 m_right[i] =
static_cast<int>(R);
157 std::vector<double> result(
m_alpha.size());
166 for (
size_t k = 0;
k <
n; ++
k) {
170 output[
k] = input[
L] +
m_alpha[
k] * (input[R] - input[
L]);
175 const double *output_x,
unsigned int output_x_size) {
177 init_linear(input_x, input_x_size, output_x, output_x_size);
179 for (
unsigned int j = 0; j <
m_alpha.size(); ++j) {
188 const double *output_x,
unsigned int output_x_size) {
189 assert(input_x_size >= 2);
191 m_left.resize(output_x_size);
196 for (
unsigned int i = 0; i < output_x_size; ++i) {
200 size_t L = gsl_interp_bsearch(input_x, output_x[i], 0, input_x_size);
202 m_left[i] =
static_cast<int>(
L);
206 assert(
m_left[i] >= 0 and
m_left[i] < (
int)input_x_size);
218 al = gsl_interp_bsearch(x, a, 0, x_size),
219 ar = (a >= x[al] and al + 1 < x_size) ? al + 1 : al,
220 bl = gsl_interp_bsearch(x, b, 0, x_size),
221 br = (b >= x[bl] and bl + 1 < x_size) ? bl + 1 : bl;
223 std::map<size_t, double> result;
225 if (al == bl and ar == br) {
227 result[al] += (b - a);
230 result[al] += (x[ar] - a);
233 for (
size_t k = ar;
k < bl; ++
k) {
234 result[
k] += x[
k + 1] - x[
k];
238 result[bl] += b - x[bl];
250 al = gsl_interp_bsearch(x, a, 0, x_size),
251 ar = (a >= x[al] and al + 1 < x_size) ? al + 1 : al,
252 bl = gsl_interp_bsearch(x, b, 0, x_size),
253 br = (b >= x[bl] and bl + 1 < x_size) ? bl + 1 : bl;
256 alpha_a = (al == ar) ? 0.0 : (a - x[al]) / (x[ar] - x[al]),
257 alpha_b = (bl == br) ? 0.0 : (b - x[bl]) / (x[br] - x[bl]);
259 std::map<size_t, double> result;
261 if (al == bl and ar == br) {
264 result[al] += 0.5 * (2.0 - alpha_a - alpha_b) * (b - a);
265 result[ar] += 0.5 * (alpha_a + alpha_b) * (b - a);
268 result[al] += 0.5 * (1.0 - alpha_a) * (x[ar] - a);
269 result[ar] += 0.5 * (1.0 + alpha_a) * (x[ar] - a);
272 for (
size_t k = ar;
k < bl; ++
k) {
276 result[
L] += 0.5 * (x[R] - x[
L]);
277 result[R] += 0.5 * (x[R] - x[
L]);
281 result[bl] += 0.5 * (2.0 - alpha_b) * (b - x[bl]);
282 result[br] += 0.5 * alpha_b * (b - x[bl]);
317 "invalid integration interval (a >= b)");
322 "unsupported interpolation type");
325 auto weights = (type ==
LINEAR) ?
329 size_t N = x_size - 1;
345 auto W = weights(x, x_size, t0, b);
352 auto W = weights(x, x_size, a, t1);
358 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)
void init_piecewise_constant(const double *input_x, unsigned int input_x_size, const double *output_x, unsigned int output_x_size)
Interpolation1D(InterpolationType type, const std::vector< double > &input_x, const std::vector< double > &output_x)
std::vector< int > m_right
std::vector< double > m_alpha
Interpolation weights.
const std::vector< double > & alpha() const
const std::vector< int > & right() const
void init_nearest(const double *input_x, unsigned int input_x_size, const double *output_x, unsigned int output_x_size)
const std::vector< int > & left() const
std::vector< int > m_left
Interpolation indexes.
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.
#define PISM_ERROR_LOCATION
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_linear(const double *x, size_t x_size, double a, double b)
static std::map< size_t, double > weights_piecewise_constant(const double *x, size_t x_size, double a, double b)