18 #include "eckit/exception/Exceptions.h"
19 #include "ioda/ObsDataVector.h"
20 #include "ioda/ObsSpace.h"
21 #include "oops/util/Logger.h"
22 #include "oops/util/missingValues.h"
35 oops::Log::debug() <<
"ObsErrorFactorConventional: config = " << config << std::endl;
42 const std::vector<std::string> inflatevars =
options_->inflatevars.value();
45 const std::string qcgrp =
options_->testQCflag.value();
48 for (
size_t iv = 0; iv < inflatevars.size(); ++iv) {
74 const float tiny_float = FLT_MIN;
78 const size_t nlevs = data.
nlevs(
Variable(
"air_pressure@GeoVaLs"));
84 int varsize = obserr.nvars();
87 const std::vector<std::string> inflatevars =
options_->inflatevars.value();
88 const std::string qcgrp =
options_->testQCflag.value();
94 if (qcgrp ==
"PreQC") qcthres =
options_->qcthreshold.value().value_or(3);
97 std::vector<float> ob_pressure(
nlocs);
98 data.
get(
Variable(
"air_pressure@MetaData"), ob_pressure);
99 std::vector<std::string> ob_stationID(
nlocs);
100 data.
get(
Variable(
"station_id@MetaData"), ob_stationID);
101 std::vector<util::DateTime> ob_datetime(
nlocs);
102 data.
get(
Variable(
"datetime@MetaData"), ob_datetime);
105 if (ob_datetime.empty()) {
110 std::vector<std::vector<float>> prsl(nlevs, std::vector<float>(
nlocs));
111 for (
size_t ilev = 0; ilev < nlevs; ++ilev) {
112 data.
get(
Variable(
"air_pressure@GeoVaLs"), ilev, prsl[ilev]);
115 for (
size_t iv = 0; iv < varsize; ++iv) {
117 std::vector<int> ob_variable_QCflag(
nlocs);
118 std::vector<int> ob_QCflag(
nlocs);
119 data.
get(
Variable(inflatevars[iv]+
"@"+qcgrp), ob_variable_QCflag);
122 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
123 (ob_variable_QCflag[iloc] <= qcthres && ob_variable_QCflag[iloc] !=
missing) ?
124 ob_QCflag[iloc] = 0 : ob_QCflag[iloc] = 100;
128 std::vector<float> dprsl(nlevs-1);
130 float pre1, pre2, maxpre, conpre, vmag, pdiffu, pdiffd, pdifftotal;
135 ioda::ObsSpace::RecIdxIter irec;
136 for ( irec = obsdb.recidx_begin(); irec != obsdb.recidx_end(); ++irec ) {
137 std:: size_t rNum = obsdb.recidx_recnum(irec);
138 std::vector<std::size_t> rSort = obsdb.recidx_vector(irec);
141 for (
size_t iloc = 0; iloc < rSort.size(); ++iloc) {
144 for (
size_t ilev = 0; ilev < nlevs-1; ++ilev) {
146 dprsl[ilev] = (prsl[ilev][rSort[iloc]]-prsl[ilev+1][rSort[iloc]])*0.001f;
150 for (
size_t ilev = 1; ilev < nlevs-1; ++ilev) {
151 if (ob_pressure[rSort[iloc]] < prsl[ilev][rSort[iloc]]) {
156 pre1 = 0.5f*dprsl[indexlev];
157 pre2 = 0.02f*0.001f*prsl[indexlev][rSort[iloc]];
158 maxpre = std::max(pre1, pre2);
159 conpre = con_g_rd*0.001f*ob_pressure[rSort[iloc]];
160 vmag = std::min(maxpre, conpre);
165 if (ob_QCflag[rSort[iloc]] == 0) {
171 while (lloc < rSort.size()) {
172 float tmp =
abs(ob_pressure[rSort[iloc]]-ob_pressure[rSort[lloc]])*0.001f;
173 if (ob_QCflag[rSort[lloc]] == 0 && tmp < vmag) {
185 float tmp =
abs(ob_pressure[rSort[lloc]]-ob_pressure[rSort[iloc]])*0.001f;
186 if (ob_QCflag[rSort[lloc]] == 0 && tmp < vmag) {
196 pdifftotal = std::max(pdiffd+pdiffu, 5.0f * tiny_float);
197 error_factor = sqrt(2.0f*vmag/pdifftotal);
200 obserr[iv][rSort[iloc]] = error_factor;
203 if (icount !=
nlocs) {
204 std::string errString =
"The data should be sorted or icount and nlocs are not consistent: ";
205 oops::Log::error() << errString << icount <<
", "<<
nlocs << std::endl;
206 throw eckit::BadValue(errString);
208 oops::Log::debug() <<
"ObsErrorFactorCon: inflate var, # of reports, total obs, filtered obs = "
209 << inflatevars[iv] <<
" " << ireport <<
" "<<
nlocs <<
" " << ipass << std::endl;
void compute(const ObsFilterData &, ioda::ObsDataVector< float > &) const
compute the result of the function
~ObsErrorFactorConventional()
ObsErrorFactorConventional(const eckit::Configuration &config)
std::unique_ptr< ObsErrorFactorConventionalParameters > options_
const ufo::Variables & requiredVariables() const
geovals required to compute the function
Options controlling ObsErrorFactorConventional ObsFunction.
ObsFilterData provides access to all data related to an ObsFilter.
size_t nlocs() const
Returns the number of locations in the associated ObsSpace.
ioda::ObsSpace & obsspace() const
Returns reference to ObsSpace associated with ObsFilterData.
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.
integer function nlocs(this)
Return the number of observational locations in this Locations object.
static ObsFunctionMaker< ObsErrorFactorConventional > makerSteps_("ObsErrorFactorConventional")
util::Duration abs(const util::Duration &duration)
static constexpr double grav
static constexpr double rd