UFO
ProfileCheckInterpolation.cc
Go to the documentation of this file.
1 /*
2  * (C) Crown 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 
10 
11 namespace ufo {
12 
13  static ProfileCheckMaker<ProfileCheckInterpolation>
15 
18  : ProfileCheckBase(options),
19  ProfileStandardLevels(options)
20  {}
21 
23  {
24  oops::Log::debug() << " Interpolation check" << std::endl;
25 
26  const int numProfileLevels = profileDataHandler.getNumProfileLevels();
27 
28  const std::vector <float> &pressures =
29  profileDataHandler.get<float>(ufo::VariableNames::obs_air_pressure);
30  const std::vector <float> &tObs =
31  profileDataHandler.get<float>(ufo::VariableNames::obs_air_temperature);
32  const std::vector <float> &tBkg =
33  profileDataHandler.get<float>(ufo::VariableNames::hofx_air_temperature);
34  std::vector <int> &tFlags =
35  profileDataHandler.get<int>(ufo::VariableNames::qcflags_air_temperature);
36  std::vector <int> &NumAnyErrors =
37  profileDataHandler.get<int>(ufo::VariableNames::counter_NumAnyErrors);
38  std::vector <int> &NumInterpErrors =
39  profileDataHandler.get<int>(ufo::VariableNames::counter_NumInterpErrors);
40  std::vector <int> &NumInterpErrObs =
41  profileDataHandler.get<int>(ufo::VariableNames::counter_NumInterpErrObs);
42  const std::vector <float> &tObsCorrection =
43  profileDataHandler.get<float>(ufo::VariableNames::obscorrection_air_temperature);
44 
45  if (!oops::allVectorsSameNonZeroSize(pressures, tObs, tBkg, tFlags,
46  tObsCorrection)) {
47  oops::Log::warning() << "At least one vector is the wrong size. "
48  << "Check will not be performed." << std::endl;
49  oops::Log::warning() << "Vector sizes: "
50  << oops::listOfVectorSizes(pressures, tObs, tBkg, tFlags,
51  tObsCorrection)
52  << std::endl;
53  return;
54  }
55 
56  std::vector <float> tObsFinal;
57  correctVector(tObs, tObsCorrection, tObsFinal);
58 
59  calcStdLevels(numProfileLevels, pressures, tObsFinal, tFlags);
60 
61  LevErrors_.assign(numProfileLevels, -1);
62  tInterp_.assign(numProfileLevels, missingValueFloat);
63 
64  int NumErrors = 0;
65 
66  for (int jlevstd = 0; jlevstd < NumStd_; ++jlevstd) {
67  int jlev = StdLev_[jlevstd]; // Standard level
68 
69  if (tFlags[jlev] & ufo::MetOfficeQCFlags::Profile::SurfaceLevelFlag) continue;
70  int SigB = SigBelow_[jlevstd];
71  int SigA = SigAbove_[jlevstd];
72  float PStd = pressures[jlev];
73  int IPStd = std::round(pressures[jlev] * 0.01); // Pressure rounded to nearest hPa
74 
75  /// BigGap - see 6.3.2.2.2 of the Guide on the Global Data-Processing System.
76  /// Reduced to 50 hPa for standard levels at 150 and 100 hPa
77  float BigGap = options_.ICheck_BigGapInit.value();
78  for (int i = 0; i < StandardLevels_.size(); ++i) {
79  if (StandardLevels_[i] <= IPStd) {
80  BigGap = BigGaps_[i] * 100.0; // hPa -> Pa
81  break;
82  }
83  }
84 
85  if (NumSig_ < std::max(3, NumStd_ / 2)) continue; // Too few sig levs for reliable check
86 
87  if (SigB == -1 || SigA == -1) continue;
88 
89  if (pressures[SigB] - PStd > BigGap ||
90  PStd - pressures[SigA] > BigGap ||
91  LogP_[SigB] == LogP_[SigA]) continue;
92 
93  float Ratio = (LogP_[jlev] - LogP_[SigB]) /
94  (LogP_[SigA] - LogP_[SigB]); // eqn 3.3a
95 
96  tInterp_[jlev] = tObsFinal[SigB] + (tObsFinal[SigA] - tObsFinal[SigB]) * Ratio; // eqn 3.3b
97 
98  // Temperature difference > TInterpTol*TolRelax degrees?
99  float TolRelax = 1.0;
100  if (PStd < options_.ICheck_TolRelaxPThresh.value())
101  TolRelax = options_.ICheck_TolRelax.value();
102  if (std::abs(tObsFinal[jlev] - tInterp_[jlev]) >
103  options_.ICheck_TInterpTol.value() * TolRelax) {
104  NumAnyErrors[0]++;
105  NumInterpErrors[0]++;
106  NumErrors++;
107 
108  // Simplest form of flagging - sig or std flags may be unset in other routines
112 
113  LevErrors_[jlev]++;
114  LevErrors_[SigB]++;
115  LevErrors_[SigA]++;
116 
117  oops::Log::debug() << " -> Failed interpolation check for levels " << jlev
118  << " (central), " << SigB << " (lower) and "
119  << SigA << " (upper)" << std::endl;
120  oops::Log::debug() << " -> Level " << jlev << ": "
121  << "P = " << pressures[jlev] * 0.01 << "hPa, tObs = "
122  << tObsFinal[jlev] - ufo::Constants::t0c << "C, "
123  << "tBkg = " << tBkg[jlev] - ufo::Constants::t0c << "C, "
124  << "tInterp = " << tInterp_[jlev] - ufo::Constants::t0c
125  << "C, tInterp - tObs = " << tInterp_[jlev] - tObsFinal[jlev]
126  << std::endl;
127  oops::Log::debug() << " -> Level " << SigB << ": "
128  << "P = " << pressures[SigB] * 0.01 << "hPa, tObs = "
129  << tObsFinal[SigB] - ufo::Constants::t0c << "C, "
130  << "tBkg = " << tBkg[SigB] - ufo::Constants::t0c << "C" << std::endl;
131  oops::Log::debug() << " -> Level " << SigA << ": "
132  << "P = " << pressures[SigA] * 0.01 << "hPa, tObs = "
133  << tObsFinal[SigA] - ufo::Constants::t0c << "C, "
134  << "tBkg = " << tBkg[SigA] - ufo::Constants::t0c << "C" << std::endl;
135  }
136  }
137  if (NumErrors > 0) NumInterpErrObs[0]++;
138  }
139 
141  {
142  profileDataHandler.set(ufo::VariableNames::StdLev, std::move(StdLev_));
143  profileDataHandler.set(ufo::VariableNames::SigAbove, std::move(SigAbove_));
144  profileDataHandler.set(ufo::VariableNames::SigBelow, std::move(SigBelow_));
145  profileDataHandler.set(ufo::VariableNames::IndStd, std::move(IndStd_));
146  profileDataHandler.set(ufo::VariableNames::LevErrors, std::move(LevErrors_));
147  profileDataHandler.set(ufo::VariableNames::tInterp, std::move(tInterp_));
148  profileDataHandler.set(ufo::VariableNames::LogP, std::move(LogP_));
149  std::vector <int> NumStd(profileDataHandler.getNumProfileLevels(), std::move(NumStd_));
150  std::vector <int> NumSig(profileDataHandler.getNumProfileLevels(), std::move(NumSig_));
151  profileDataHandler.set(ufo::VariableNames::NumStd, std::move(NumStd));
152  profileDataHandler.set(ufo::VariableNames::NumSig, std::move(NumSig));
153  }
154 } // namespace ufo
155 
Options controlling the operation of the ConventionalProfileProcessing filter.
oops::Parameter< float > ICheck_BigGapInit
Initial 'big gap' for interpolation check (hPa)
oops::Parameter< float > ICheck_TolRelax
T tolerance relaxation factor.
oops::Parameter< float > ICheck_TInterpTol
Tolerance for interpolation check (K)
oops::Parameter< float > ICheck_TolRelaxPThresh
Pressure threshold for T tolerance relaxation.
Profile QC checker base class.
const float missingValueFloat
Missing value (float)
const ConventionalProfileProcessingParameters & options_
Configurable parameters.
void correctVector(const std::vector< T > &v1, const std::vector< T > &v2, std::vector< T > &vout)
Apply correction to vector of values.
ProfileCheckInterpolation(const ConventionalProfileProcessingParameters &options)
void fillValidationData(ProfileDataHandler &profileDataHandler) override
Fill variables in validator.
std::vector< int > LevErrors_
Number of failed checks by level.
std::vector< float > tInterp_
Interpolated value of T.
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check.
Retrieve and store data for individual profiles. To do this, first the vector of values in the entire...
std::vector< T > & get(const std::string &fullname)
void set(const std::string &fullname, std::vector< T > &&vec_in)
int getNumProfileLevels() const
Return number of levels to which QC checks should be applied.
Calculate standard levels.
std::vector< float > BigGaps_
Big gaps (hPa) used in interpolation check.
std::vector< int > StdLev_
Index of standard levels.
void calcStdLevels(const int numProfileLevels, const std::vector< float > &pressures, const std::vector< float > &tObs, const std::vector< int > &tFlags)
Calculate standard levels.
std::vector< float > StandardLevels_
Standard levels (hPa)
std::vector< float > LogP_
Log(Pressure) - used for vertical interpolation.
int NumStd_
Number of standard levels.
std::vector< int > IndStd_
Indices of standard levels.
std::vector< int > SigBelow_
Significant level below standard level.
std::vector< int > SigAbove_
Significant level above standard level.
int NumSig_
Number of significant levels.
@ InterpolationFlag
Interpolation check flag.
@ SurfaceLevelFlag
Surface Level.
Definition: RunCRTM.h:27
static ProfileCheckMaker< ProfileCheckInterpolation > makerProfileCheckInterpolation_("Interpolation")
util::Duration abs(const util::Duration &duration)
static constexpr double t0c
Definition: Constants.h:24
static constexpr const char *const tInterp
static constexpr const char *const hofx_air_temperature
Definition: VariableNames.h:38
static constexpr const char *const LogP
static constexpr const char *const obs_air_temperature
Definition: VariableNames.h:19
static constexpr const char *const counter_NumInterpErrObs
static constexpr const char *const LevErrors
static constexpr const char *const counter_NumInterpErrors
static constexpr const char *const counter_NumAnyErrors
static constexpr const char *const NumSig
static constexpr const char *const NumStd
static constexpr const char *const SigBelow
static constexpr const char *const StdLev
static constexpr const char *const obs_air_pressure
Definition: VariableNames.h:18
static constexpr const char *const qcflags_air_temperature
Definition: VariableNames.h:99
static constexpr const char *const obscorrection_air_temperature
static constexpr const char *const SigAbove
static constexpr const char *const IndStd