UFO
ProfileAverageWindSpeed.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 
8 #include <set>
9 #include <sstream>
10 #include <string>
11 #include <utility>
12 
17 
19 
20 namespace ufo {
21 
22  static ProfileCheckMaker<ProfileAverageWindSpeed>
23  makerProfileAverageWindSpeed_("AverageWindSpeed");
24 
27  : ProfileCheckBase(options)
28  {}
29 
31  {
32  oops::Log::debug() << " Wind speed averaging" << std::endl;
33 
34  // Produce vector of profiles containing data for the wind speed averaging.
35  std::vector <std::string> variableNamesInt =
44  std::vector <std::string> variableNamesFloat =
53  std::vector <std::string> variableNamesGeoVaLs =
55 
56  if (options_.compareWithOPS.value()) {
57  variableNamesInt.insert
58  (variableNamesInt.end(),
59  {"OPS_" +
60  std::string(ufo::VariableNames::modellevels_average_eastward_wind_qcflags),
61  "OPS_" +
62  std::string(ufo::VariableNames::modellevels_average_northward_wind_qcflags)});
63  variableNamesFloat.insert
64  (variableNamesFloat.end(),
65  {"OPS_" +
66  std::string(ufo::VariableNames::modellevels_average_eastward_wind_derived),
67  "OPS_" +
68  std::string(ufo::VariableNames::modellevels_average_northward_wind_derived)});
69  variableNamesGeoVaLs.insert
70  (variableNamesGeoVaLs.end(),
71  {ufo::VariableNames::geovals_average_eastward_wind,
72  ufo::VariableNames::geovals_average_eastward_wind_qcflags,
73  ufo::VariableNames::geovals_average_northward_wind,
74  ufo::VariableNames::geovals_average_northward_wind_qcflags});
75  }
76 
77  std::vector <ProfileDataHolder> profiles =
78  profileDataHandler.produceProfileVector
79  (variableNamesInt,
80  variableNamesFloat,
81  {},
82  variableNamesGeoVaLs,
83  {});
84 
85  // Run wind speed averaging on each profile in the original ObsSpace,
86  // saving averaged output to the equivalent extended profile.
87  const size_t halfnprofs = profileDataHandler.getObsdb().nrecs() / 2;
88  for (size_t jprof = 0; jprof < halfnprofs; ++jprof) {
89  oops::Log::debug() << " Profile " << (jprof + 1) << " / " << halfnprofs << std::endl;
90  auto& profileOriginal = profiles[jprof];
91  auto& profileExtended = profiles[jprof + halfnprofs];
92  runCheckOnProfiles(profileOriginal, profileExtended);
93  }
94 
95  // Fill validation information if required.
96  if (options_.compareWithOPS.value()) {
97  oops::Log::debug() << " Filling validation data" << std::endl;
98  for (size_t jprof = 0; jprof < halfnprofs * 2; ++jprof) {
99  fillValidationData(profiles[jprof]);
100  }
101  }
102 
103  // Update data handler with profile information.
104  oops::Log::debug() << " Updating data handler" << std::endl;
105  profileDataHandler.updateAllProfiles(profiles);
106  }
107 
109  ProfileDataHolder &profileExtended)
110  {
111  // Check the two profiles are in the correct section of the ObsSpace.
114 
115  const size_t numProfileLevels = profileOriginal.getNumProfileLevels();
116  // Do not perform averaging if there is just one reported level.
117  if (numProfileLevels <= 1)
118  return;
119 
120  const std::vector <float> &uObs =
121  profileOriginal.get<float>(ufo::VariableNames::obs_eastward_wind);
122  const std::vector <float> &vObs =
123  profileOriginal.get<float>(ufo::VariableNames::obs_northward_wind);
124  const std::vector <float> &uPGEBd =
125  profileOriginal.get<float>(ufo::VariableNames::pgebd_eastward_wind);
126  std::vector <int> &uFlags =
127  profileOriginal.get<int>(ufo::VariableNames::qcflags_eastward_wind);
128  std::vector <int> &vFlags =
129  profileOriginal.get<int>(ufo::VariableNames::qcflags_northward_wind);
130  std::vector <int> &NumGapsU =
131  profileOriginal.get<int>(ufo::VariableNames::counter_NumGapsU);
132  // Number of gaps for wind profilers.
133  std::vector <int> &NumGapsUWP =
134  profileOriginal.get<int>(ufo::VariableNames::counter_NumGapsUWP);
135  const std::vector <int> &ObsType =
136  profileOriginal.get<int>(ufo::VariableNames::ObsType);
137 
138  if (!oops::allVectorsSameNonZeroSize(uObs, vObs,
139  uPGEBd,
140  uFlags, vFlags,
141  ObsType)) {
142  oops::Log::warning() << "At least one vector is the wrong size. "
143  << "Wind speed averaging will not be performed." << std::endl;
144  oops::Log::warning() << "Vector sizes: "
145  << oops::listOfVectorSizes(uObs, vObs,
146  uPGEBd,
147  uFlags, vFlags,
148  ObsType)
149  << std::endl;
150  // todo(ctgh): Revisit this (and other routines in which a similar choice has been made)
151  // when the organisation of the input data becomes clearer.
152  return;
153  }
154 
155  // Obtain GeoVaLs surface pressure and eastward wind speed.
156  std::vector <float> &geovals_surface_pressure =
158  if (geovals_surface_pressure.empty())
159  throw eckit::BadValue("Surface pressure GeoVaLs vector is empty.", Here());
160 
161  // Obtain vectors that were produced in the AveragePressure routine.
162  const std::vector <float> &LogPB =
163  profileExtended.get<float>(ufo::VariableNames::modellevels_logP_derived);
164  const std::vector <float> &RepLogP =
165  profileOriginal.get<float>(ufo::VariableNames::LogP_derived);
166  const std::vector <float> &BigGap =
167  profileOriginal.get<float>(ufo::VariableNames::bigPgaps_derived);
168 
169  if (LogPB.empty() ||
170  !oops::allVectorsSameNonZeroSize(RepLogP, BigGap)) {
171  std::stringstream errorMessage;
172  errorMessage << "At least one model-level vector is the wrong size. "
173  << "Ensure that the AveragePressure routine has been run before this one."
174  << std::endl;
175  errorMessage << "Vector sizes: "
176  << oops::listOfVectorSizes(LogPB,
177  RepLogP, BigGap)
178  << std::endl;
179  throw eckit::BadValue(errorMessage.str(), Here());
180  }
181 
182  // Create concatenated vector of log(pressure) on both surface and upper-air levels
183  // for use in the wind speed averaging.
184  std::vector <float> LogPWB = LogPB;
185  LogPWB.insert(LogPWB.begin(), std::log(geovals_surface_pressure[0]));
186 
187  // Flag reported value if the probability of gross error is too large.
188  // Values which have been flagged here, or previously, are not used in the averaging routines.
189  for (size_t jlev = 0; jlev < numProfileLevels; ++jlev) {
190  if (uPGEBd[jlev] > options_.AvgU_PGEskip.value()) {
193  }
194  }
195 
196  // Average observed wind speeds onto model levels.
197  int NumGaps = 0; // Number of large gaps in reported profile
198  std::vector <float> uModObs; // u observations averaged onto model levels.
199  std::vector <int> uFlagsModObs; // Flags associated with the u averaging procedure.
200  // Minimum fraction of a model layer that must have been covered (in the vertical coordinate)
201  // by observed values in order for averaging onto that layer to be performed.
202  const float SondeDZFraction = options_.AvgU_SondeDZFraction.value();
204  uObs,
205  RepLogP,
206  BigGap,
207  LogPWB,
208  SondeDZFraction,
210  uFlagsModObs,
211  uModObs,
212  NumGaps);
213 
214  // Increment wind speed gap counter if necessary.
215  if (NumGaps > 0) {
217  NumGapsUWP[0]++;
218  else
219  NumGapsU[0]++;
220  }
221 
222  std::vector <float> vModObs; // v observations averaged onto model levels.
223  std::vector <int> vFlagsModObs; // Flags associated with the v averaging procedure.
225  vObs,
226  RepLogP,
227  BigGap,
228  LogPWB,
229  SondeDZFraction,
231  vFlagsModObs,
232  vModObs,
233  NumGaps);
234 
235  // Store the eastward wind speed averaged onto model levels.
236  profileExtended.set<float>
238 
239  // Store the QC flags associated with the eastward wind averaging.
240  profileExtended.set<int>
242 
243  // Store the northward wind speed averaged onto model levels.
244  profileExtended.set<float>
246 
247  // Store the QC flags associated with the northward wind averaging.
248  profileExtended.set<int>
250  }
251 
253  {
254  // Retrieve, then save, the OPS versions of
255  // eastward and northward wind averaged onto model levels,
256  // and the QC flags associated with the averaging process.
257  profile.set<float>
259  std::move(profile.getGeoVaLVector
261  profile.set<float>
263  std::move(profile.getGeoVaLVector
265 
266  // The QC flags are stored as floats but are converted to integers here.
267  // Due to the loss of precision, 5 must be added to the missing value.
268  const std::vector <float>& average_eastward_wind_qcflags_float =
269  profile.getGeoVaLVector
271  std::vector <int> average_eastward_wind_qcflags_int
272  (average_eastward_wind_qcflags_float.begin(),
273  average_eastward_wind_qcflags_float.end());
274  std::replace(average_eastward_wind_qcflags_int.begin(),
275  average_eastward_wind_qcflags_int.end(),
276  -2147483648L,
277  -2147483643L);
278  profile.set<int>
280  std::move(average_eastward_wind_qcflags_int));
281  const std::vector <float>& average_northward_wind_qcflags_float =
282  profile.getGeoVaLVector
284  std::vector <int> average_northward_wind_qcflags_int
285  (average_northward_wind_qcflags_float.begin(),
286  average_northward_wind_qcflags_float.end());
287  std::replace(average_northward_wind_qcflags_int.begin(),
288  average_northward_wind_qcflags_int.end(),
289  -2147483648L,
290  -2147483643L);
291  profile.set<int>
293  std::move(average_northward_wind_qcflags_int));
294  }
295 } // namespace ufo
Options controlling the operation of the ConventionalProfileProcessing filter.
oops::Parameter< bool > compareWithOPS
Compare with OPS values?
void runCheckOnProfiles(ProfileDataHolder &profileOriginal, ProfileDataHolder &profileExtended)
ProfileAverageWindSpeed(const ConventionalProfileProcessingParameters &options)
void runCheck(ProfileDataHandler &profileDataHandler) override
void fillValidationData(ProfileDataHolder &profileDataHolder)
Fill variables in validator (for comparison with OPS output).
Profile QC checker base class.
const ConventionalProfileProcessingParameters & options_
Configurable parameters.
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.
int getNumProfileLevels() const
Get number of profile levels for this profile.
std::vector< T > & get(const std::string &fullname)
Retrieve a vector if it is present. If not, throw an exception.
void set(const std::string &fullname, std::vector< T > &&vec_in)
Set values in a vector.
std::vector< float > & getGeoVaLVector(const std::string &fullname)
Retrieve a GeoVaL vector if it is present. If not, throw an exception.
void checkObsSpaceSection(ufo::ObsSpaceSection section)
Check this profile is in the expected ObsSpace section (original or extended).
@ FinalRejectFlag
Final QC flag.
constexpr int profile
Definition: QCflags.h:34
Definition: RunCRTM.h:27
void calculateVerticalAverage(const std::vector< int > &flagsIn, const std::vector< float > &valuesIn, const std::vector< float > &coordIn, const std::vector< float > &bigGap, const std::vector< float > &coordOut, float DZFrac, ProfileAveraging::Method method, std::vector< int > &flagsOut, std::vector< float > &valuesOut, int &numGaps, std::vector< float > *coordMax, std::vector< float > *coordMin)
Profile vertical averaging onto model levels.
static ProfileCheckMaker< ProfileAverageWindSpeed > makerProfileAverageWindSpeed_("AverageWindSpeed")
static constexpr const char *const extended_obs_space
Definition: VariableNames.h:94
static constexpr const char *const qcflags_eastward_wind
static constexpr const char *const counter_NumGapsU
static constexpr const char *const counter_NumGapsUWP
static constexpr const char *const bigPgaps_derived
static constexpr const char *const modellevels_average_eastward_wind_derived
static constexpr const char *const qcflags_northward_wind
static constexpr const char *const modellevels_logP_derived
static constexpr const char *const modellevels_average_eastward_wind_qcflags
static constexpr const char *const geovals_surface_pressure
static constexpr const char *const modellevels_average_northward_wind_qcflags
static constexpr const char *const geovals_average_eastward_wind
static constexpr const char *const geovals_average_northward_wind
static constexpr const char *const LogP_derived
static constexpr const char *const obs_northward_wind
Definition: VariableNames.h:22
static constexpr const char *const obs_eastward_wind
Definition: VariableNames.h:21
static constexpr const char *const geovals_average_northward_wind_qcflags
static constexpr const char *const ObsType
Definition: VariableNames.h:87
static constexpr const char *const pgebd_eastward_wind
Definition: VariableNames.h:76
static constexpr const char *const modellevels_average_northward_wind_derived
static constexpr const char *const geovals_average_eastward_wind_qcflags