PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
interpolation.hh
Go to the documentation of this file.
1 /* Copyright (C) 2015, 2017, 2018, 2019, 2021, 2022, 2023 PISM Authors
2  *
3  * This file is part of PISM.
4  *
5  * PISM is free software; you can redistribute it and/or modify it under the
6  * terms of the GNU General Public License as published by the Free Software
7  * Foundation; either version 3 of the License, or (at your option) any later
8  * version.
9  *
10  * PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with PISM; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #ifndef PISM_INTERPOLATION_H
21 #define PISM_INTERPOLATION_H
22 
23 #include <cstddef> // size_t
24 #include <vector>
25 #include <map>
26 
27 namespace pism {
28 
30 
31 /**
32  * Class encapsulating linear and piece-wise constant interpolation indexes and weights.
33  *
34  * Most library interpolation routines (GSL's, for example) assume that we are working with a fixed
35  * function given on an input grid; these libraries support evaluating this function at arbitrary
36  * points. In this case an interpolation routine may use values on the input grid to create an
37  * interpolant, but has no knowledge of an "output grid."
38  *
39  * In PISM we have a slightly different situation: we need to transfer several gridded functions
40  * between two *fixed* grids, so we can use both grids to compute interpolation weights, but cannot
41  * use values on the input grid.
42  *
43  * If a point on the output grid is outside the interval defined by the input grid this code uses
44  * *constant extrapolation*.
45  *
46  * This class isolates the code computing interpolation weights so that we can use these 1D weights
47  * in a 2D or 3D regridding code. This avoids code duplication: in bilinear (trilinear)
48  * interpolation X and Y (and Z) grid dimensions are treated the same. This also makes it possible
49  * to test the code computing interpolation weights in isolation.
50  *
51  * We provide getters `left()`, `right()` and `alpha()`.
52  *
53  * Here `left[i]` is the index in the input grid (`x_input`) such that
54  * ~~~ c++
55  * input_x[left[i]] < output_x[i]
56  * ~~~
57  * similar for `right[i]`:
58  * ~~~ c++
59  * input_x[right[i]] >= output_x[i]
60  * ~~~
61  * When `output_x[i]` is outside the input interval `left[i]` and `right[i]` are adjusted so that
62  * the interpolation formula below corresponds to constant extrapolation.
63  *
64  * `alpha[i]` is the linear interpolation weight used like this:
65  * ~~~ c++
66  * const int
67  * L = m_left[k],
68  * R = m_right[k];
69  * const double Alpha = m_alpha[k];
70  * result[k] = input_values[L] + Alpha * (input_values[R] - input_values[L]);
71  * ~~~
72  *
73  * Piecewise constant 1D interpolation used for time-dependent forcing (fluxes that should
74  * be interpreted as piecewise-constant to simplify accounting of mass conservation).
75  *
76  * Here `input_x` defines left end-points of intervals, For example, [0, 1] defines two
77  * intervals: [0, 1) and [1, x_e). Here the value x_e is irrelevant because we use
78  * constant extrapolation for points outside the interval covered by input data.
79  *
80  */
82 public:
83  Interpolation(InterpolationType type, const std::vector<double> &input_x,
84  const std::vector<double> &output_x);
85  Interpolation(InterpolationType type, const double *input_x, unsigned int input_x_size,
86  const double *output_x, unsigned int output_x_size);
87 
88  const std::vector<int>& left() const;
89  const std::vector<int>& right() const;
90  const std::vector<double>& alpha() const;
91 
92  int left(size_t j) const;
93  int right(size_t j) const;
94  double alpha(size_t j) const;
95 
96  /*!
97  * Number of grid points in the output grid.
98  */
99  int n_output() const;
100 
101  //! Return interpolated values (on the output grid) given `input_values` on the input grid.
102  /** This is used for testing. (Regular code calls left(), right(), and alpha().)
103  */
104  std::vector<double> interpolate(const std::vector<double> &input_values) const;
105 
106  /*!
107  * Compute interpolated values on the output grid given values on the input grid.
108  */
109  void interpolate(const double *input, double *output) const;
110 
111 private:
112  //! Interpolation indexes
113  std::vector<int> m_left, m_right;
114  //! Interpolation weights
115  std::vector<double> m_alpha;
116 
117  void init_linear(const double *input_x, unsigned int input_x_size,
118  const double *output_x, unsigned int output_x_size);
119  void init_nearest(const double *input_x, unsigned int input_x_size,
120  const double *output_x, unsigned int output_x_size);
121  void init_piecewise_constant(const double *input_x, unsigned int input_x_size,
122  const double *output_x, unsigned int output_x_size);
123 };
124 
125 std::map<size_t, double> integration_weights(const double *x,
126  size_t x_size,
127  InterpolationType type,
128  double a,
129  double b);
130 
131 std::map<size_t, double> integration_weights(const std::vector<double> &x,
132  InterpolationType type,
133  double a,
134  double b);
135 
136 } // end of namespace pism
137 
138 #endif /* PISM_INTERPOLATION_H */
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
InterpolationType
@ PIECEWISE_CONSTANT
std::map< size_t, double > integration_weights(const double *x, size_t x_size, InterpolationType type, double a, double b)