12 #include "eckit/config/Configuration.h"
14 #include "ioda/distribution/Accumulator.h"
15 #include "ioda/ObsDataVector.h"
16 #include "ioda/ObsSpace.h"
18 #include "oops/util/Logger.h"
20 #include "ufo/GeoVaLs.h"
31 :
FilterBase(obsdb, parameters, flags, obserr), parameters_(parameters)
33 oops::Log::trace() <<
"SatwindInversion contructor starting" << std::endl;
45 oops::Log::trace() <<
"SatwindInversion destructed" << std::endl;
91 std::vector<std::vector<bool>> & flagged)
const {
92 oops::Log::trace() <<
"SatwindInversionCorrection priorFilter" << std::endl;
93 print(oops::Log::trace());
104 const std::string model_temp_name =
"air_temperature";
105 const std::string model_rh_name =
"relative_humidity";
106 const std::string model_vcoord_name =
"air_pressure";
110 std::vector<float> obs_pressure;
113 std::vector<int> comp_method(
obsdb_.nlocs());
114 obsdb_.get_db(
"MetaData",
"wind_computation_method", comp_method);
116 std::vector<int> u_flags(
obsdb_.nlocs());
117 std::vector<int> v_flags(
obsdb_.nlocs());
118 if (
obsdb_.has(
"QCFlags",
"eastward_wind") &&
obsdb_.has(
"QCFlags",
"northward_wind")) {
119 obsdb_.get_db(
"QCFlags",
"eastward_wind", u_flags);
120 obsdb_.get_db(
"QCFlags",
"northward_wind", v_flags);
122 throw eckit::Exception(
"eastward_wind@QCFlags or northward_wind@QCFlags not initialised");
129 std::vector <double> model_temp_profile(gvals->
nlevs(model_temp_name), 0.0);
130 std::vector <double> model_rh_profile(gvals->
nlevs(model_rh_name), 0.0);
131 std::vector <double> model_vcoord_profile(gvals->
nlevs(model_vcoord_name), 0.0);
134 std::vector<float> original_pressure(obs_pressure);
137 std::unique_ptr<ioda::Accumulator<size_t>> countAccumulator =
138 obsdb_.distribution()->createAccumulator<
size_t>();
140 std::unique_ptr<ioda::Accumulator<std::vector<double>>> totalsAccumulator =
141 obsdb_.distribution()->createAccumulator<
double>(
nlocs);
144 for (
size_t iloc=0; iloc <
nlocs; ++iloc) {
147 if (obs_pressure[iloc] >= min_pressure &&
151 gvals->
getAtLocation(model_temp_profile, model_temp_name, iloc);
153 gvals->
getAtLocation(model_vcoord_profile, model_vcoord_name, iloc);
157 bool inversion =
false;
158 bool firsttime =
true;
159 float inversion_base = std::numeric_limits<float>::max();
160 float inversion_top = std::numeric_limits<float>::max();
161 float temp_inversion_base = std::numeric_limits<float>::max();
162 float temp_inversion_top = std::numeric_limits<float>::max();
164 for (
int ilev = 0; ilev < nlevs-2 ; ++ilev) {
166 if (inversion ==
false && model_vcoord_profile[ilev] < min_pressure) {
170 if (model_vcoord_profile[ilev] > max_pressure) {
174 if (inversion ==
false && model_temp_profile[ilev+1] > model_temp_profile[ilev]) {
176 inversion_base = model_vcoord_profile[ilev];
177 temp_inversion_base = model_temp_profile[ilev];
183 model_temp_profile[ilev+1] < model_temp_profile[ilev] &&
184 model_vcoord_profile[ilev] < inversion_base &&
187 if (model_rh_profile[ilev] < rh_threshold) {
188 inversion_top = model_vcoord_profile[ilev];
189 temp_inversion_top = model_temp_profile[ilev];
202 (temp_inversion_top - temp_inversion_base) >= inversion_temperature &&
203 obs_pressure[iloc] < inversion_base) {
205 countAccumulator->addTerm(iloc, 1);
206 totalsAccumulator->addTerm(iloc, PDIFF, inversion_base - obs_pressure[iloc]);
207 obs_pressure[iloc] = inversion_base;
216 obsdb_.put_db(
"MetaData",
"air_pressure_levels", obs_pressure);
217 obsdb_.put_db(
"QCFlags",
"eastward_wind", u_flags);
218 obsdb_.put_db(
"QCFlags",
"northward_wind", v_flags);
219 obsdb_.put_db(
"MetaData",
"air_pressure_original", original_pressure);
222 const std::size_t count = countAccumulator->computeResult();
223 const std::vector<double> totals = totalsAccumulator->computeResult();
225 oops::Log::info() <<
"Satwind Inversion: "<< count
226 <<
" observations with modified pressure" << std::endl;
227 oops::Log::info() <<
"Satwind Inversion: "<< totals[PDIFF] / count
228 <<
" Pa mean pressure difference" << std::endl;
235 os <<
"SatwindInversionCorrection: config = " <<
parameters_ << std::endl;
Base class for UFO QC filters.
GeoVaLs: geophysical values at locations.
size_t nlevs(const std::string &var) const
Return number of levels for a specified variable.
void getAtLocation(std::vector< double > &, const std::string &, const int) const
Get GeoVaLs at a specified location.
const GeoVaLs * getGeoVaLs() const
Returns reference to GeoVaLs required by 1DVar.
size_t nlevs(const Variable &) const
Returns the number of levels in the specified variable.
void get(const Variable &varname, std::vector< float > &values) const
Fills a std::vector with values of the specified variable.
void applyFilter(const std::vector< bool > &, const Variables &, std::vector< std::vector< bool >> &) const override
A filter that modifies the assigned pressure of AMV observations if a temperature inversion is detect...
SatwindInversionCorrection(ioda::ObsSpace &, const Parameters_ &, std::shared_ptr< ioda::ObsDataVector< int > >, std::shared_ptr< ioda::ObsDataVector< float > >)
void print(std::ostream &) const override
~SatwindInversionCorrection()
Parameters controlling the operation of the SatwindInversionCorrection filter.
oops::Parameter< float > max_pressure
Maximum model pressure (Pa) to consider - set default.
oops::Parameter< float > min_pressure
Minimum AMV pressure (Pa) to consider for correction - set default.
oops::Parameter< float > inversion_temperature
Temperature difference (K) between inversion base and top - set default.
oops::RequiredParameter< Variable > obs_pressure
Name of the observation pressure variable to correct.
oops::RequiredParameter< float > rh_threshold
Relative humidity (%) threshold value.
@ SatwindInversionFlag
Inversion height corrected.
integer function nlocs(this)
Return the number of observational locations in this Locations object.
@ visible
Motion observed in the infrared channel.