UFO
ProfileCheckUInterpAlternative.cc
Go to the documentation of this file.
1 /*
2  * (C) Crown copyright 2021, 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 
13 
14 namespace ufo {
15 
16  static ProfileCheckMaker<ProfileCheckUInterpAlternative>
17  makerProfileCheckUInterpAlternative_("UInterpAlternative");
18 
21  : ProfileCheckBase(options),
22  ProfileStandardLevels(options)
23  {}
24 
26  {
27  oops::Log::debug() << " Alternative U interpolation check" << std::endl;
28 
29  // Produce vector of profiles containing data for the alternative U interpolation check.
30  std::vector <std::string> variableNamesInt =
34  std::vector <std::string> variableNamesFloat =
38  if (options_.compareWithOPS.value()) {
39  variableNamesInt.insert(variableNamesInt.end(),
40  {ufo::VariableNames::StdLev,
41  ufo::VariableNames::SigAbove,
42  ufo::VariableNames::SigBelow,
43  ufo::VariableNames::LevErrors,
44  ufo::VariableNames::NumStd,
45  ufo::VariableNames::NumSig});
46  variableNamesFloat.insert(variableNamesFloat.end(),
47  {ufo::VariableNames::uInterp,
48  ufo::VariableNames::vInterp,
49  ufo::VariableNames::LogP});
50  }
51 
52  std::vector <ProfileDataHolder> profiles =
53  profileDataHandler.produceProfileVector
54  (variableNamesInt,
55  variableNamesFloat,
56  {},
57  {},
58  {});
59 
60  // Run alternative U interpolation check on each profile.
61  const size_t nprofs = profileDataHandler.getObsdb().nrecs();
62  for (size_t jprof = 0; jprof < nprofs; ++jprof) {
63  oops::Log::debug() << "Profile " << (jprof + 1) << " / " << nprofs << std::endl;
64  auto& profile = profiles[jprof];
66  // Fill validation information if required.
67  if (options_.compareWithOPS.value())
69  }
70 
71  // Update data handler with profile information.
72  oops::Log::debug() << " Updating data handler" << std::endl;
73  profileDataHandler.updateAllProfiles(profiles);
74  }
75 
77  {
78  const int numProfileLevels = profile.getNumProfileLevels();
79  const std::vector <float> &pressures =
81  const std::vector <float> &uObs =
83  const std::vector <float> &vObs =
85  std::vector <int> &uFlags =
87  std::vector <int> &NumSamePErrObs =
89  std::vector <int> &NumInterpErrObs =
91 
92  if (!oops::allVectorsSameNonZeroSize(pressures, uObs, vObs, uFlags)) {
93  oops::Log::warning() << "At least one vector is the wrong size. "
94  << "Check will not be performed." << std::endl;
95  oops::Log::warning() << "Vector sizes: "
96  << oops::listOfVectorSizes(pressures, uObs, vObs, uFlags)
97  << std::endl;
98  return;
99  }
100 
101  calcStdLevelsUV(numProfileLevels, pressures, uObs, vObs, uFlags);
102 
103  LevErrors_.assign(numProfileLevels, -1);
104  uInterp_.assign(numProfileLevels, 0.0);
105  vInterp_.assign(numProfileLevels, 0.0);
106 
107  int NumErrors = 0;
108 
109  // Check levels with identical pressures
110  int jlevprev = -1;
111  for (int jlev = 0; jlev < numProfileLevels; ++jlev) {
112  if (uObs[jlev] != missingValueFloat && vObs[jlev] != missingValueFloat) {
113  if (jlevprev != -1) {
114  if (pressures[jlev] == pressures[jlevprev] &&
115  (uObs[jlev] != uObs[jlevprev] || vObs[jlev] != vObs[jlevprev])) {
116  float VectDiffSq = std::pow(uObs[jlev] - uObs[jlevprev], 2) +
117  std::pow(vObs[jlev] - vObs[jlevprev], 2);
118  if (VectDiffSq > options_.UICheck_TInterpIdenticalPTolSq.value()) {
119  NumErrors++;
122  oops::Log::debug() << " -> Wind speed interpolation check: identical P "
123  << "and significantly different wind speed magnitude for "
124  << "levels " << jlevprev << " and " << jlev << std::endl;
125  oops::Log::debug() << " -> Level " << jlevprev << ": "
126  << "P = " << pressures[jlevprev] * 0.01 << "hPa, uObs = "
127  << uObs[jlevprev] << "ms^-1, vObs = "
128  << vObs[jlevprev] << "ms^-1" << std::endl;
129  oops::Log::debug() << " -> Level " << jlev << ": "
130  << "P = " << pressures[jlev] * 0.01 << "hPa, uObs = "
131  << uObs[jlev] << "ms^-1, vObs = "
132  << vObs[jlev] << "ms^-1" << std::endl;
133  oops::Log::debug() << " -> VectDiffSq = " << VectDiffSq << "m^2s^-2" << std::endl;
134  }
135  }
136  }
137  jlevprev = jlev;
138  }
139  }
140 
141  if (NumErrors > 0) NumSamePErrObs[0]++;
142 
143  if (NumSig_ < std::max(3, NumStd_ / 2)) return; // Too few sig levels for reliable check
144 
145  // Interpolation check
146  NumErrors = 0;
147  for (int jlevStd = 0; jlevStd < NumStd_; ++jlevStd) {
148  if (SigBelow_[jlevStd] == -1 || SigAbove_[jlevStd] == -1) continue;
149  int jlev = StdLev_[jlevStd]; // Standard level
150  int SigB = SigBelow_[jlevStd];
151  int SigA = SigAbove_[jlevStd];
152  float PStd = pressures[jlev];
153  // BigGap - see 6.3.2.2.2 of the Guide on the Global Data-Processing System
154  float BigGap = options_.UICheck_BigGapLowP.value();
155  const std::vector <float> BigGaps = options_.UICheck_BigGaps.value();
156  const std::vector <float> BigGapsPThresh = options_.UICheck_BigGapsPThresh.value();
157  for (size_t bgidx = 0; bgidx < BigGapsPThresh.size(); ++bgidx) {
158  if (PStd > BigGapsPThresh[bgidx]) {
159  BigGap = BigGaps[bgidx];
160  break;
161  }
162  }
163 
164  if (pressures[SigB] - PStd > BigGap ||
165  PStd - pressures[SigA] > BigGap) {
166  uInterp_[jlev] = missingValueFloat;
167  vInterp_[jlev] = missingValueFloat;
168  continue;
169  }
170 
171  if (LogP_[SigB] == LogP_[SigA]) continue;
172 
173  float Ratio = (LogP_[jlev] - LogP_[SigB]) / (LogP_[SigA] - LogP_[SigB]); // eqn 3.3a
174  uInterp_[jlev] = uObs[SigB] + (uObs[SigA] - uObs[SigB]) * Ratio; // eqn 3.3b
175  vInterp_[jlev] = vObs[SigB] + (vObs[SigA] - vObs[SigB]) * Ratio; // eqn 3.3b
176 
177  // Vector wind difference > UInterpTol m/s?
178  float VectDiffSq = std::pow(uObs[jlev] - uInterp_[jlev], 2) +
179  std::pow(vObs[jlev] - vInterp_[jlev], 2);
180  if (VectDiffSq > options_.UICheck_TInterpTolSq.value()) {
181  NumErrors++;
182  LevErrors_[jlev]++;
183  LevErrors_[SigB]++;
184  LevErrors_[SigA]++;
185  // Simplest form of flagging
189 
190  oops::Log::debug() << " -> Failed wind speed interpolation check for levels " << jlev
191  << " (central), " << SigB << " (lower) and "
192  << SigA << " (upper)" << std::endl;
193  oops::Log::debug() << " -> Level " << jlev << ": "
194  << "P = " << pressures[jlev] * 0.01 << "hPa, uObs = "
195  << uObs[jlev] << "ms^-1, vObs = "
196  << vObs[jlev] << "ms^-1, uInterp = " << uInterp_[jlev]
197  << "ms^-1, vInterp = " << vInterp_[jlev] << "ms^-1" << std::endl;
198  oops::Log::debug() << " -> VectDiffSq = " << VectDiffSq << "m^2s^-2" << std::endl;
199  }
200  }
201 
202  if (NumErrors > 0) NumInterpErrObs[0]++;
203  }
204 
206  {
207  profile.set(ufo::VariableNames::StdLev, std::move(StdLev_));
213  profile.set(ufo::VariableNames::LogP, std::move(LogP_));
214  std::vector <int> NumStd(profile.getNumProfileLevels(), std::move(NumStd_));
215  std::vector <int> NumSig(profile.getNumProfileLevels(), std::move(NumSig_));
216  profile.set(ufo::VariableNames::NumStd, std::move(NumStd));
217  profile.set(ufo::VariableNames::NumSig, std::move(NumSig));
218  }
219 } // namespace ufo
Options controlling the operation of the ConventionalProfileProcessing filter.
oops::Parameter< bool > compareWithOPS
Compare with OPS values?
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.
std::vector< float > uInterp_
Interpolated value of u.
void runCheckOnProfile(ProfileDataHolder &profile)
Run check on an individual profile.
void fillValidationData(ProfileDataHolder &profileDataHolder)
Fill variables in validator.
std::vector< float > vInterp_
Interpolated value of v.
std::vector< int > LevErrors_
Number of failed checks by level.
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check on all profiles.
ProfileCheckUInterpAlternative(const ConventionalProfileProcessingParameters &options)
Retrieve and store data for individual profiles. To do this, first the vector of values in the entire...
void updateAllProfiles(std::vector< ProfileDataHolder > &profiles)
Read values from a collection of profiles and update information related to each one.
std::vector< ProfileDataHolder > produceProfileVector(const std::vector< std::string > &variableNamesInt, const std::vector< std::string > &variableNamesFloat, const std::vector< std::string > &variableNamesString, const std::vector< std::string > &variableNamesGeoVaLs, const std::vector< std::string > &variableNamesObsDiags)
Produce a vector of all profiles, loading the requested variables into each one.
ioda::ObsSpace & getObsdb()
Return obsdb.
Profile data holder class.
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.
constexpr int profile
Definition: QCflags.h:34
Definition: RunCRTM.h:27
static ProfileCheckMaker< ProfileCheckUInterpAlternative > makerProfileCheckUInterpAlternative_("UInterpAlternative")
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