UFO
ProfileVerticalInterpolation.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2020, Met Office
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  */
7 
9 
10 namespace ufo {
11  void profileVerticalInterpolation(const std::vector <float> &coordIn,
12  const std::vector <float> &valuesIn,
13  const std::vector <float> &coordOut,
14  std::vector <float> &valuesOut,
18  {
19  const float missingValueFloat = util::missingValue(missingValueFloat);
20  // Number of input levels.
21  const int nLevsIn = static_cast<int> (coordIn.size());
22  // Coordinate multiplier (depends upon the coordinate ordering).
23  const float coordMultiplier =
24  coordOrder == ProfileInterpolation::CoordinateOrder::Descending ? -1.0 : 1.0;
25 
26  // Initial value of 'previous' output coordinate is +/- the maximum float.
27  float previousCoordOut = coordMultiplier * std::numeric_limits<float>::max();
28  // Initial value of 'previous' input level index is the maximum integer.
29  int previousLevIn = std::numeric_limits<int>::max();
30 
31  // Loop over each output level.
32  for (int jlevOut = 0; jlevOut < coordOut.size(); ++jlevOut) {
33  if (coordOut[jlevOut] == missingValueFloat) continue;
34  // Index of input level closest to output level (from below or above depending on
35  // whether the coordinates are in ascending or descending order).
36  int jlevIn = 0;
37 
38  // Position at which to start searching for the closest input level.
39  // By default this is set to the start of the vector.
40  int PosStart = 0;
41  // If the output coordinate for this level is larger than the previous value,
42  // start searching at the previous level index.
43  // (This is in the case of ascending coordinate order; the opposite criterion must be
44  // fulfilled for descending order.)
45  if (coordMultiplier * coordOut[jlevOut] > coordMultiplier * previousCoordOut)
46  PosStart = previousLevIn;
47 
48  // Perform the search for the closest input level.
49  for (int Pos = PosStart; Pos < nLevsIn; ++Pos) {
50  if (coordMultiplier * coordIn[Pos] > coordMultiplier * coordOut[jlevOut]) {
51  jlevIn = Pos;
52  break;
53  }
54  }
55  // Modify previous input level index and output coordinate.
56  previousLevIn = jlevIn;
57  previousCoordOut = coordOut[jlevOut];
58 
59  // Perform the interpolation.
60  if (coordOut[jlevOut] == coordIn[jlevIn]) {
61  // Copy the value if the input and output coordinate are identical.
62  valuesOut[jlevOut] = valuesIn[jlevIn];
64  coordMultiplier * coordOut[jlevOut] > coordMultiplier * coordIn[nLevsIn - 1]) {
65  // If the output coordinate is either:
66  // - larger than the largest input coordinate if the coordinates are in ascending order, or
67  // - smaller than the smallest input coordinate if the coordinates are in descending order
68  // and there is no extrapolation, set the output value to one of two possibilities:
70  valuesOut[jlevOut] = missingValueFloat;
72  valuesOut[jlevOut] = valuesIn[nLevsIn - 1];
74  coordMultiplier * coordOut[jlevOut] < coordMultiplier * coordIn[0]) {
75  // If the output coordinate is either:
76  // - smaller than the smallest input coordinate if the coordinates
77  // are in ascending order, or
78  // - larger than the largest input coordinate if the coordinates are in descending order
79  // and there is no extrapolation, set the output value to one of two possibilities:
81  valuesOut[jlevOut] = missingValueFloat;
83  valuesOut[jlevOut] = valuesIn[0];
84  } else {
85  // Interpolation (or extrapolation if the output coordinate is out-of-bounds)
86  // will be performed.
87  // Compute the interpolation factor.
88  float Interp_factor = 0.0;
90  // Log-linear interpolation.
91  if (coordOut[jlevOut] > 0.0 &&
92  coordIn[jlevIn] > 0.0 &&
93  coordIn[jlevIn + 1] > 0.0) {
94  Interp_factor = std::log(coordOut[jlevOut] / coordIn[jlevIn]) /
95  std::log(coordIn[jlevIn + 1] / coordIn[jlevIn]);
96  }
97  } else {
98  // Linear interpolation.
99  if (coordIn[jlevIn + 1] - coordIn[jlevIn] != 0) {
100  Interp_factor = (coordOut[jlevOut] - coordIn[jlevIn]) /
101  (coordIn[jlevIn + 1] - coordIn[jlevIn]);
102  }
103  }
104  // Determine the interpolated value.
105  if (valuesIn[jlevIn] != missingValueFloat &&
106  valuesIn[jlevIn + 1] != missingValueFloat) {
107  valuesOut[jlevOut] = valuesIn[jlevIn] +
108  (valuesIn[jlevIn + 1] - valuesIn[jlevIn]) * Interp_factor;
109  }
110  }
111  }
112  }
113 } // namespace ufo
Definition: RunCRTM.h:27
void profileVerticalInterpolation(const std::vector< float > &coordIn, const std::vector< float > &valuesIn, const std::vector< float > &coordOut, std::vector< float > &valuesOut, const ProfileInterpolation::InterpolationMethod interpMethod, const ProfileInterpolation::CoordinateOrder coordOrder, const ProfileInterpolation::OutOfBoundsTreatment outOfBounds)