UFO
ProfileCheckRH.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  {}
19 
20  void ProfileCheckRH::runCheck(ProfileDataHandler &profileDataHandler)
21  {
22  oops::Log::debug() << " Relative humidity check" << std::endl;
23 
24  const int numProfileLevels = profileDataHandler.getNumProfileLevels();
25  const std::vector <float> &pressures =
26  profileDataHandler.get<float>(ufo::VariableNames::obs_air_pressure);
27  const std::vector <float> &tObs =
28  profileDataHandler.get<float>(ufo::VariableNames::obs_air_temperature);
29  const std::vector <float> &tBkg =
30  profileDataHandler.get<float>(ufo::VariableNames::hofx_air_temperature);
31  const std::vector <float> &RHObs =
32  profileDataHandler.get<float>(ufo::VariableNames::obs_relative_humidity);
33  const std::vector <float> &RHBkg =
34  profileDataHandler.get<float>(ufo::VariableNames::hofx_relative_humidity);
35  const std::vector <float> &tdObs =
36  profileDataHandler.get<float>(ufo::VariableNames::obs_dew_point_temperature);
37  const std::vector <int> &tFlags =
38  profileDataHandler.get<int>(ufo::VariableNames::qcflags_air_temperature);
39  std::vector <int> &RHFlags =
40  profileDataHandler.get<int>(ufo::VariableNames::qcflags_relative_humidity);
41  const std::vector <float> &tObsCorrection =
42  profileDataHandler.get<float>(ufo::VariableNames::obscorrection_air_temperature);
43 
44  std::vector <int> &TotCProfs =
45  profileDataHandler.get<int>(ufo::VariableNames::counter_TotCProfs);
46  std::vector <int> &TotHProfs =
47  profileDataHandler.get<int>(ufo::VariableNames::counter_TotHProfs);
48  std::vector <int> &TotCFlags =
49  profileDataHandler.get<int>(ufo::VariableNames::counter_TotCFlags);
50  std::vector <int> &TotHFlags =
51  profileDataHandler.get<int>(ufo::VariableNames::counter_TotHFlags);
52  std::vector <int> &TotLFlags =
53  profileDataHandler.get<int>(ufo::VariableNames::counter_TotLFlags);
54 
55  if (!oops::allVectorsSameNonZeroSize(pressures, tObs, tBkg, RHObs, RHBkg,
56  tdObs, tFlags, RHFlags, tObsCorrection)) {
57  oops::Log::warning() << "At least one vector is the wrong size. "
58  << "Check will not be performed." << std::endl;
59  oops::Log::warning() << "Vector sizes: "
60  << oops::listOfVectorSizes(pressures, tObs, tBkg, RHObs, RHBkg,
61  tdObs, tFlags, RHFlags, tObsCorrection)
62  << std::endl;
63  return;
64  }
65 
66  std::vector <float> tObsFinal;
67  correctVector(tObs, tObsCorrection, tObsFinal);
68 
69  // Set up arrays and counters
70 
71  int NumLev = 0;
72  float PTrop = 0.0; // Tropopause pressure level
73  int NLowP = 0; // Number of RH reports above 100 hPa
74  float RHDLowP = 0.0; // Mean RH O-B above 100 hPa
75  Press_.assign(numProfileLevels, 0.0);
76  Temp_.assign(numProfileLevels, 0.0);
77  rh_.assign(numProfileLevels, 0.0);
78  td_.assign(numProfileLevels, 0.0);
79  tbk_.assign(numProfileLevels, 0.0);
80  rhbk_.assign(numProfileLevels, 0.0);
81  FlagH_.assign(numProfileLevels, 0);
82  Indx_.assign(numProfileLevels, -1);
83 
84  float Tmin = options_.RHCheck_TminInit.value();
85  for (int jlev = 0; jlev < numProfileLevels; ++jlev) {
87  PTrop = pressures[jlev] * 0.01;
88  }
89  if (pressures[jlev] > 0.0 &&
90  RHObs[jlev] != missingValueFloat) {
91  Tmin = std::min(Tmin, tObsFinal[jlev]);
92  Indx_[NumLev] = jlev;
93  Press_[NumLev] = pressures[jlev] * 0.01;
94  Temp_[NumLev] = tObsFinal[jlev];
95  rh_[NumLev] = RHObs[jlev];
96  td_[NumLev] = tdObs[jlev];
97  tbk_[NumLev] = tBkg[jlev];
98  rhbk_[NumLev] = RHBkg[jlev];
99  if (Press_[NumLev] <= options_.RHCheck_PressInitThresh.value()) {
100  NLowP++;
101  RHDLowP = RHDLowP + rh_[NumLev] - rhbk_[NumLev];
102  }
103  NumLev++;
104  }
105  }
106  if (NumLev <= 1) return;
107 
108  // Look for errors at the top of cloud layers
109 
110  const float RHThresh = options_.RHCheck_RHThresh.value();
111  const float PressDiffAdjThresh = options_.RHCheck_PressDiffAdjThresh.value();
112  for (int jlev = 1; jlev < NumLev; ++jlev) {
113  if (Press_[jlev] < options_.RHCheck_PressThresh.value()) break;
114  if ((Press_[0] - Press_[jlev]) < options_.RHCheck_PressDiff0Thresh.value()) continue;
115  if (FlagH_[jlev] == 1) continue;
116  if ((td_[jlev] - td_[jlev - 1] > options_.RHCheck_tdDiffThresh.value() &&
117  rh_[jlev - 1] >= RHThresh) ||
118  (td_[jlev] > td_[jlev - 1] &&
119  std::min(rh_[jlev - 1], rh_[jlev]) >= RHThresh)) {
120  float MinRHabove = rh_[jlev]; // Min RH in levels close in pressure to test level
121  for (int klev = jlev + 1; klev < NumLev; ++klev) {
122  if (Press_[jlev] - Press_[klev] > PressDiffAdjThresh) break;
123  MinRHabove = std::min(MinRHabove, rh_[klev]);
124  }
125  if (MinRHabove < options_.RHCheck_MinRHThresh.value()) {
126  FlagH_[jlev] = 2;
127  TotCProfs[0]++;
128  oops::Log::debug() << " -> Error at top of cloud layer for level " << jlev << std::endl;
129  for (int klev = jlev + 1; klev < NumLev; ++klev) {
130  if (Press_[jlev] - Press_[klev] > PressDiffAdjThresh) break;
131  if (td_[klev] <= td_[jlev - 1]) break;
132  FlagH_[klev] = 2;
133  }
134  }
135  }
136  }
137 
138  if (NLowP > 0) RHDLowP = RHDLowP / static_cast <float> (NLowP);
139 
140  // Simple check for sonde ascent too moist at high levels
141  // Start at top and work down
142 
143  const float SondeRHHiTol = options_.RHCheck_SondeRHHiTol.value();
144 
145  int NumLFlags = 0;
146  int NumHFlags = 0;
147  int NumCFlags = 0;
148  if ((PTrop != 0.0 && Press_[NumLev - 1] <= PTrop) ||
149  Tmin < options_.RHCheck_TminThresh.value()) {
150  for (int ilev = NumLev - 1; ilev >= 0; ilev--) {
151  if (rh_[ilev] > rhbk_[ilev] + SondeRHHiTol ||
152  (Press_[ilev] <= options_.RHCheck_PressInitThresh.value() && RHDLowP > SondeRHHiTol)) {
153  if (FlagH_[ilev] == 0) {
154  oops::Log::debug() << " -> Sonde ascent too moist for level " << ilev << std::endl;
155  FlagH_[ilev] = 1;
156  if (Temp_[ilev] >= options_.RHCheck_TempThresh.value()) NumLFlags = NumLFlags + 1;
157  }
158  } else {
159  break;
160  }
161  }
162  }
163 
164  // Set level flags
165  for (int i = 0; i < NumLev; ++i) {
166  if (FlagH_[i] == 1) ++NumHFlags;
167  if (FlagH_[i] == 2) ++NumCFlags;
168  }
169 
170  if (NumHFlags > 0) TotHProfs[0]++;
171 
172  for (int n = 0; n < NumCFlags; ++n)
173  TotCFlags[0]++;
174  for (int n = 0; n < NumHFlags; ++n)
175  TotHFlags[0]++;
176  for (int n = 0; n < NumLFlags; ++n)
177  TotLFlags[0]++;
178 
179  if (NumCFlags + NumHFlags > 0) {
180  for (int jlev = 0; jlev < NumLev; ++jlev) {
181  if (FlagH_[jlev] > 0) {
182  int ilev = Indx_[jlev];
185  }
186  }
187  }
188  }
189 
191  {
192  profileDataHandler.set(ufo::VariableNames::Press, std::move(Press_));
193  profileDataHandler.set(ufo::VariableNames::Temp, std::move(Temp_));
194  profileDataHandler.set(ufo::VariableNames::rh, std::move(rh_));
195  profileDataHandler.set(ufo::VariableNames::td, std::move(td_));
196  profileDataHandler.set(ufo::VariableNames::tbk, std::move(tbk_));
197  profileDataHandler.set(ufo::VariableNames::rhbk, std::move(rhbk_));
198  profileDataHandler.set(ufo::VariableNames::FlagH, std::move(FlagH_));
199  profileDataHandler.set(ufo::VariableNames::Indx, std::move(Indx_));
200  }
201 } // namespace ufo
Options controlling the operation of the ConventionalProfileProcessing filter.
oops::Parameter< float > RHCheck_PressDiffAdjThresh
Threshold for pressure difference between adjacent levels (Pa)
oops::Parameter< float > RHCheck_PressInitThresh
Threshold for pressure when setting up arrays (Pa)
oops::Parameter< float > RHCheck_TminInit
Initial value of minimum temperature (K)
oops::Parameter< float > RHCheck_PressThresh
Threshold for pressure (Pa)
oops::Parameter< float > RHCheck_tdDiffThresh
Threshold for dew point temperature difference (K)
oops::Parameter< float > RHCheck_PressDiff0Thresh
Threshold for pressure difference relative to level 0 (Pa)
oops::Parameter< float > RHCheck_TempThresh
Lower threshold for temperature in moisture check.
oops::Parameter< float > RHCheck_TminThresh
Upper threshold for Tmin in moisture check.
oops::Parameter< float > RHCheck_MinRHThresh
Threshold for minimum relative humidity (%)
oops::Parameter< float > RHCheck_SondeRHHiTol
Tolerance for high level check of relative humidity (%)
oops::Parameter< float > RHCheck_RHThresh
Threshold for relative humidity (%)
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.
std::vector< float > rh_
Observed relative humidity for selected levels (%)
std::vector< float > td_
Observed dew point temperature for selected levels (K)
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check.
std::vector< float > Temp_
Observed temperature for selected levels (K)
ProfileCheckRH(const ConventionalProfileProcessingParameters &options)
std::vector< int > Indx_
Indices of selected levels.
std::vector< int > FlagH_
Flags for RH checks.
std::vector< float > rhbk_
Model relative humidity for selected levels (%)
std::vector< float > Press_
Observed pressure for selected levels (hPa)
void fillValidationData(ProfileDataHandler &profileDataHandler) override
Fill variables in validator.
std::vector< float > tbk_
Model temperature for selected levels (K)
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.
@ InterpolationFlag
Interpolation check flag.
@ TropopauseFlag
Tropopause Level.
@ FinalRejectFlag
Final QC flag.
Definition: RunCRTM.h:27
static ProfileCheckMaker< ProfileCheckRH > makerProfileCheckRH_("RH")
static constexpr const char *const rhbk
static constexpr const char *const counter_TotHFlags
static constexpr const char *const counter_TotLFlags
static constexpr const char *const obs_relative_humidity
Definition: VariableNames.h:20
static constexpr const char *const hofx_air_temperature
Definition: VariableNames.h:38
static constexpr const char *const obs_air_temperature
Definition: VariableNames.h:19
static constexpr const char *const FlagH
static constexpr const char *const Temp
static constexpr const char *const qcflags_relative_humidity
static constexpr const char *const rh
static constexpr const char *const counter_TotCFlags
static constexpr const char *const td
static constexpr const char *const Indx
static constexpr const char *const Press
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 obs_dew_point_temperature
Definition: VariableNames.h:24
static constexpr const char *const counter_TotHProfs
static constexpr const char *const tbk
static constexpr const char *const counter_TotCProfs
static constexpr const char *const hofx_relative_humidity
Definition: VariableNames.h:40