UFO
ProfileCheckUInterp.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 
14 
17  : ProfileCheckBase(options),
18  ProfileStandardLevels(options)
19  {}
20 
22  {
23  oops::Log::debug() << " U interpolation check" << std::endl;
24 
25  const int numProfileLevels = profileDataHandler.getNumProfileLevels();
26  const std::vector <float> &pressures =
27  profileDataHandler.get<float>(ufo::VariableNames::obs_air_pressure);
28  const std::vector <float> &uObs =
29  profileDataHandler.get<float>(ufo::VariableNames::obs_eastward_wind);
30  const std::vector <float> &vObs =
31  profileDataHandler.get<float>(ufo::VariableNames::obs_northward_wind);
32  std::vector <int> &uFlags =
33  profileDataHandler.get<int>(ufo::VariableNames::qcflags_eastward_wind);
34  std::vector <int> &NumSamePErrObs =
35  profileDataHandler.get<int>(ufo::VariableNames::counter_NumSamePErrObs);
36  std::vector <int> &NumInterpErrObs =
37  profileDataHandler.get<int>(ufo::VariableNames::counter_NumInterpErrObs);
38 
39  if (!oops::allVectorsSameNonZeroSize(pressures, uObs, vObs, uFlags)) {
40  oops::Log::warning() << "At least one vector is the wrong size. "
41  << "Check will not be performed." << std::endl;
42  oops::Log::warning() << "Vector sizes: "
43  << oops::listOfVectorSizes(pressures, uObs, vObs, uFlags)
44  << std::endl;
45  return;
46  }
47 
48  calcStdLevelsUV(numProfileLevels, pressures, uObs, vObs, uFlags);
49 
50  LevErrors_.assign(numProfileLevels, -1);
51  uInterp_.assign(numProfileLevels, 0.0);
52  vInterp_.assign(numProfileLevels, 0.0);
53 
54  int NumErrors = 0;
55 
56  // Check levels with identical pressures
57  int jlevprev = -1;
58  for (int jlev = 0; jlev < numProfileLevels; ++jlev) {
59  if (uObs[jlev] != missingValueFloat && vObs[jlev] != missingValueFloat) {
60  if (jlevprev != -1) {
61  if (pressures[jlev] == pressures[jlevprev] &&
62  (uObs[jlev] != uObs[jlevprev] || vObs[jlev] != vObs[jlevprev])) {
63  float VectDiffSq = std::pow(uObs[jlev] - uObs[jlevprev], 2) +
64  std::pow(vObs[jlev] - vObs[jlevprev], 2);
65  if (VectDiffSq > options_.UICheck_TInterpIdenticalPTolSq.value()) {
66  NumErrors++;
69  oops::Log::debug() << " -> Wind speed interpolation check: identical P "
70  << "and significantly different wind speed magnitude for "
71  << "levels " << jlevprev << " and " << jlev << std::endl;
72  oops::Log::debug() << " -> Level " << jlevprev << ": "
73  << "P = " << pressures[jlevprev] * 0.01 << "hPa, uObs = "
74  << uObs[jlevprev] << "ms^-1, vObs = "
75  << vObs[jlevprev] << "ms^-1" << std::endl;
76  oops::Log::debug() << " -> Level " << jlev << ": "
77  << "P = " << pressures[jlev] * 0.01 << "hPa, uObs = "
78  << uObs[jlev] << "ms^-1, vObs = "
79  << vObs[jlev] << "ms^-1" << std::endl;
80  oops::Log::debug() << " -> VectDiffSq = " << VectDiffSq << "m^2s^-2" << std::endl;
81  }
82  }
83  }
84  jlevprev = jlev;
85  }
86  }
87 
88  if (NumErrors > 0) NumSamePErrObs[0]++;
89 
90  if (NumSig_ < std::max(3, NumStd_ / 2)) return; // Too few sig levels for reliable check
91 
92  // Interpolation check
93  NumErrors = 0;
94  for (int jlevStd = 0; jlevStd < NumStd_; ++jlevStd) {
95  if (SigBelow_[jlevStd] == -1 || SigAbove_[jlevStd] == -1) continue;
96  int jlev = StdLev_[jlevStd]; // Standard level
97  int SigB = SigBelow_[jlevStd];
98  int SigA = SigAbove_[jlevStd];
99  float PStd = pressures[jlev];
100  // BigGap - see 6.3.2.2.2 of the Guide on the Global Data-Processing System
101  float BigGap = options_.UICheck_BigGapLowP.value();
102  const std::vector <float> BigGaps = options_.UICheck_BigGaps.value();
103  const std::vector <float> BigGapsPThresh = options_.UICheck_BigGapsPThresh.value();
104  for (size_t bgidx = 0; bgidx < BigGapsPThresh.size(); ++bgidx) {
105  if (PStd > BigGapsPThresh[bgidx]) {
106  BigGap = BigGaps[bgidx];
107  break;
108  }
109  }
110 
111  if (pressures[SigB] - PStd > BigGap ||
112  PStd - pressures[SigA] > BigGap) {
113  uInterp_[jlev] = missingValueFloat;
114  vInterp_[jlev] = missingValueFloat;
115  continue;
116  }
117 
118  if (LogP_[SigB] == LogP_[SigA]) continue;
119 
120  float Ratio = (LogP_[jlev] - LogP_[SigB]) / (LogP_[SigA] - LogP_[SigB]); // eqn 3.3a
121  uInterp_[jlev] = uObs[SigB] + (uObs[SigA] - uObs[SigB]) * Ratio; // eqn 3.3b
122  vInterp_[jlev] = vObs[SigB] + (vObs[SigA] - vObs[SigB]) * Ratio; // eqn 3.3b
123 
124  // Vector wind difference > UInterpTol m/s?
125  float VectDiffSq = std::pow(uObs[jlev] - uInterp_[jlev], 2) +
126  std::pow(vObs[jlev] - vInterp_[jlev], 2);
127  if (VectDiffSq > options_.UICheck_TInterpTolSq.value()) {
128  NumErrors++;
129  LevErrors_[jlev]++;
130  LevErrors_[SigB]++;
131  LevErrors_[SigA]++;
132  // Simplest form of flagging
136 
137  oops::Log::debug() << " -> Failed wind speed interpolation check for levels " << jlev
138  << " (central), " << SigB << " (lower) and "
139  << SigA << " (upper)" << std::endl;
140  oops::Log::debug() << " -> Level " << jlev << ": "
141  << "P = " << pressures[jlev] * 0.01 << "hPa, uObs = "
142  << uObs[jlev] << "ms^-1, vObs = "
143  << vObs[jlev] << "ms^-1, uInterp = " << uInterp_[jlev]
144  << "ms^-1, vInterp = " << vInterp_[jlev] << "ms^-1" << std::endl;
145  oops::Log::debug() << " -> VectDiffSq = " << VectDiffSq << "m^2s^-2" << std::endl;
146  }
147  }
148 
149  if (NumErrors > 0) NumInterpErrObs[0]++;
150  }
151 
153  {
154  profileDataHandler.set(ufo::VariableNames::StdLev, std::move(StdLev_));
155  profileDataHandler.set(ufo::VariableNames::SigAbove, std::move(SigAbove_));
156  profileDataHandler.set(ufo::VariableNames::SigBelow, std::move(SigBelow_));
157  profileDataHandler.set(ufo::VariableNames::LevErrors, std::move(LevErrors_));
158  profileDataHandler.set(ufo::VariableNames::uInterp, std::move(uInterp_));
159  profileDataHandler.set(ufo::VariableNames::vInterp, std::move(vInterp_));
160  profileDataHandler.set(ufo::VariableNames::LogP, std::move(LogP_));
161  std::vector <int> NumStd(profileDataHandler.getNumProfileLevels(), std::move(NumStd_));
162  std::vector <int> NumSig(profileDataHandler.getNumProfileLevels(), std::move(NumSig_));
163  profileDataHandler.set(ufo::VariableNames::NumStd, std::move(NumStd));
164  profileDataHandler.set(ufo::VariableNames::NumSig, std::move(NumSig));
165  }
166 } // namespace ufo
Options controlling the operation of the ConventionalProfileProcessing filter.
oops::Parameter< float > UICheck_BigGapLowP
Big gap (Pa) used at lowest pressures in wind speed interpolation check.
oops::Parameter< float > UICheck_TInterpIdenticalPTolSq
Squared tolerance for identical pressure in wind speed interpolation check (m^2 s^-2)
oops::Parameter< float > UICheck_TInterpTolSq
Squared tolerance for wind speed interpolation check (m^2 s^-2)
Profile QC checker base class.
const float missingValueFloat
Missing value (float)
const ConventionalProfileProcessingParameters & options_
Configurable parameters.
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check.
std::vector< float > vInterp_
Interpolated value of v.
void fillValidationData(ProfileDataHandler &profileDataHandler) override
Fill variables in validator.
ProfileCheckUInterp(const ConventionalProfileProcessingParameters &options)
std::vector< float > uInterp_
Interpolated value of u.
std::vector< int > LevErrors_
Number of failed checks by level.
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.
void calcStdLevelsUV(const int numProfileLevels, const std::vector< float > &pressures, const std::vector< float > &uObs, const std::vector< float > &vObs, const std::vector< int > &uFlags)
Calculate standard levels for U and V data.
std::vector< int > StdLev_
Index of standard levels.
std::vector< float > LogP_
Log(Pressure) - used for vertical interpolation.
int NumStd_
Number 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.
Definition: RunCRTM.h:27
static ProfileCheckMaker< ProfileCheckUInterp > makerProfileCheckUInterp_("UInterp")
static constexpr const char *const qcflags_eastward_wind
static constexpr const char *const LogP
static constexpr const char *const counter_NumSamePErrObs
static constexpr const char *const counter_NumInterpErrObs
static constexpr const char *const LevErrors
static constexpr const char *const uInterp
static constexpr const char *const NumSig
static constexpr const char *const obs_northward_wind
Definition: VariableNames.h:22
static constexpr const char *const NumStd
static constexpr const char *const obs_eastward_wind
Definition: VariableNames.h:21
static constexpr const char *const SigBelow
static constexpr const char *const StdLev
static constexpr const char *const vInterp
static constexpr const char *const obs_air_pressure
Definition: VariableNames.h:18
static constexpr const char *const SigAbove