UFO
ProfileCheckUnstableLayer.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<ProfileCheckUnstableLayer>
15 
18  : ProfileCheckBase(options)
19  {}
20 
22  {
23  oops::Log::debug() << " Unstable layer/superadiabat check" << std::endl;
24 
25  const int numProfileLevels = profileDataHandler.getNumProfileLevels();
26 
27  const std::vector <float> &pressures =
28  profileDataHandler.get<float>(ufo::VariableNames::obs_air_pressure);
29  const std::vector <float> &tObs =
30  profileDataHandler.get<float>(ufo::VariableNames::obs_air_temperature);
31  const std::vector <float> &tBkg =
32  profileDataHandler.get<float>(ufo::VariableNames::hofx_air_temperature);
33  std::vector <int> &tFlags =
34  profileDataHandler.get<int>(ufo::VariableNames::qcflags_air_temperature);
35  std::vector <int> &NumAnyErrors =
36  profileDataHandler.get<int>(ufo::VariableNames::counter_NumAnyErrors);
37  std::vector <int> &NumSuperadiabat =
38  profileDataHandler.get<int>(ufo::VariableNames::counter_NumSuperadiabat);
39  const std::vector <float> &tObsCorrection =
40  profileDataHandler.get<float>(ufo::VariableNames::obscorrection_air_temperature);
41 
42  if (!oops::allVectorsSameNonZeroSize(pressures, tObs, tBkg, tFlags, tObsCorrection)) {
43  oops::Log::warning() << "At least one vector is the wrong size. "
44  << "Check will not be performed." << std::endl;
45  oops::Log::warning() << "Vector sizes: "
46  << oops::listOfVectorSizes(pressures, tObs, tBkg, tFlags, tObsCorrection)
47  << std::endl;
48  return;
49  }
50 
51  std::vector <float> tObsFinal;
52  correctVector(tObs, tObsCorrection, tObsFinal);
53 
54  PBottom_ = 0.0;
55 
56  int jlevprev = 0;
57  for (int jlev = 0; jlev < numProfileLevels; ++jlev) {
58  // Ignore this level if it has been flagged as rejected.
59  if (tFlags[jlev] & ufo::MetOfficeQCFlags::Elem::FinalRejectFlag) continue;
60  if (tObsFinal[jlev] != missingValueFloat &&
61  pressures[jlev] > options_.ULCheck_MinP.value()) {
62  if (PBottom_ == 0.0) {
63  PBottom_ = pressures[jlev];
64  } else {
65  // Temperature calculated adiabatically from prev level
66  const float Tadiabat = tObsFinal[jlevprev] *
67  std::pow(pressures[jlev] / pressures[jlevprev], ufo::Constants::rd_over_cp);
68  if (tObsFinal[jlev] - Tadiabat <= options_.ULCheck_SuperadiabatTol.value() &&
69  pressures[jlevprev] <= PBottom_ - options_.ULCheck_PBThresh.value()) {
70  NumAnyErrors[0]++;
71  NumSuperadiabat[0]++;
74 
75  oops::Log::debug() << " -> Failed unstable layer/superadiabat check for levels "
76  << jlevprev << " and " << jlev << std::endl;
77  oops::Log::debug() << " -> Tadiabat = " << Tadiabat - ufo::Constants::t0c << "C"
78  << std::endl;
79  oops::Log::debug() << " -> Level " << jlevprev << ": "
80  << "P = " << pressures[jlevprev] * 0.01 << "hPa, tObs = "
81  << tObsFinal[jlevprev] - ufo::Constants::t0c << "C, tBkg = "
82  << tBkg[jlevprev] - ufo::Constants::t0c << "C, "
83  << "tObs - Tadiabat = " << tObsFinal[jlev] - Tadiabat
84  << "C" << std::endl;
85  oops::Log::debug() << " -> Level " << jlev << ": "
86  << "P = " << pressures[jlev] * 0.01 << "hPa, tObs = "
87  << tObsFinal[jlev] - ufo::Constants::t0c << "C, tBkg = "
88  << tBkg[jlev] - ufo::Constants::t0c << "C" << std::endl;
89  }
90  }
91  jlevprev = jlev;
92  }
93  }
94  }
95 
97  {
98  std::vector <float> PBottom(profileDataHandler.getNumProfileLevels(), PBottom_);
99  profileDataHandler.set(ufo::VariableNames::PBottom, std::move(PBottom));
100  }
101 } // namespace ufo
Options controlling the operation of the ConventionalProfileProcessing filter.
oops::Parameter< float > ULCheck_PBThresh
Bottom pressure threshold for unstable layer/superadiabat check (Pa)
oops::Parameter< float > ULCheck_MinP
Min P for unstable layer/superadiabat check (Pa)
oops::Parameter< float > ULCheck_SuperadiabatTol
Tolerance for unstable layer/superadiabat check (K)
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.
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check.
void fillValidationData(ProfileDataHandler &profileDataHandler) override
Fill variables in validator.
ProfileCheckUnstableLayer(const ConventionalProfileProcessingParameters &options)
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.
@ SuperadiabatFlag
Superadiabatic check flag.
@ FinalRejectFlag
Final QC flag.
Definition: RunCRTM.h:27
static ProfileCheckMaker< ProfileCheckUnstableLayer > makerProfileCheckUnstableLayer_("UnstableLayer")
static constexpr double rd_over_cp
Definition: Constants.h:35
static constexpr double t0c
Definition: Constants.h:24
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 counter_NumAnyErrors
static constexpr const char *const PBottom
static constexpr const char *const counter_NumSuperadiabat
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