15 #include "eckit/exception/Exceptions.h"
16 #include "ioda/ObsDataVector.h"
17 #include "oops/util/Logger.h"
18 #include "oops/util/missingValues.h"
27 ObsErrorFactorSfcPressure::ObsErrorFactorSfcPressure(
const eckit::Configuration &config)
29 oops::Log::debug() <<
"ObsErrorFactorSfcPressure: config = " << config << std::endl;
30 const float tiny_float = FLT_MIN;
31 const float huge_float = FLT_MAX;
35 options_->deserialize(config);
38 const float error_min = options_->error_min.value();
39 const float error_max = options_->error_max.value();
40 ASSERT(error_min < error_max);
44 const std::string errgrp = options_->original_obserr.value();
45 invars_ +=
Variable(
"surface_pressure@"+errgrp);
48 invars_ +=
Variable(
"surface_pressure@ObsValue");
49 invars_ +=
Variable(
"air_temperature@ObsValue");
52 invars_ +=
Variable(
"station_elevation@MetaData");
55 invars_ +=
Variable(
"surface_pressure@GeoVaLs");
56 invars_ +=
Variable(
"air_pressure@GeoVaLs");
57 const std::string geovar_temp = options_->geovar_temp.value();
58 invars_ +=
Variable(geovar_temp +
"@GeoVaLs");
59 const std::string geovar_sfc_geomz = options_->geovar_sfc_geomz.value();
60 invars_ +=
Variable(geovar_sfc_geomz +
"@GeoVaLs");
65 ObsErrorFactorSfcPressure::~ObsErrorFactorSfcPressure() {}
69 void ObsErrorFactorSfcPressure::compute(
const ObsFilterData & data,
73 const float lapse_rate = 1.0f*Constants::Lclr;
76 ASSERT(obserr.nvars() == 1);
79 size_t nlocs = data.nlocs();
80 size_t nlevs = data.nlevs(Variable(
"air_pressure@GeoVaLs"));
83 const float error_min = options_->error_min.value();
84 const float error_max = options_->error_max.value();
87 std::vector<float> ob_elevation(
nlocs);
88 data.get(Variable(
"station_elevation@MetaData"), ob_elevation);
91 std::vector<float> ob_pressure_sfc(
nlocs);
92 data.get(Variable(
"surface_pressure@ObsValue"), ob_pressure_sfc);
93 std::vector<float> ob_temperature_sfc(
nlocs);
94 data.get(Variable(
"air_temperature@ObsValue"), ob_temperature_sfc);
97 std::vector<float> currentObserr(
nlocs);
98 const std::string errgrp = options_->original_obserr.value();
99 data.get(Variable(
"surface_pressure@"+errgrp), currentObserr);
102 std::vector<float> model_elevation(
nlocs);
103 const std::string geovar_sfc_geomz = options_->geovar_sfc_geomz.value();
104 data.get(Variable(geovar_sfc_geomz +
"@GeoVaLs"), model_elevation);
105 std::vector<float> model_pres_sfc(
nlocs);
106 data.get(Variable(
"surface_pressure@GeoVaLs"), model_pres_sfc);
109 std::vector<std::vector<float>> prsl(nlevs, std::vector<float>(
nlocs));
110 for (
size_t ilev = 0; ilev < nlevs; ++ilev) {
111 const size_t level = nlevs - ilev - 1;
112 data.get(Variable(
"air_pressure@GeoVaLs"), level, prsl[ilev]);
114 std::vector<std::vector<float>> tair(nlevs, std::vector<float>(
nlocs));
115 const std::string geovar_temp = options_->geovar_temp.value();
116 for (
size_t ilev = 0; ilev < nlevs; ++ilev) {
117 const size_t level = nlevs - ilev - 1;
118 data.get(Variable(geovar_temp +
"@GeoVaLs"), level, tair[ilev]);
124 std::vector<float> model_temp_sfc(
nlocs);
125 model_temp_sfc = tair[0];
127 float obserror, new_error, error_factor;
128 float rdelz, rdp, drdp, ddiff, tges, pges, tges2, pges2, psges, pgesorig, drbx;
131 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
133 if (ob_elevation[iloc] ==
missing) {
134 obserr[iv][iloc] = 99.9f;
136 rdelz = ob_elevation[iloc]-model_elevation[iloc];
140 obserr[iv][iloc] = 50.0f;
141 }
else if (
std::abs(rdelz) > 1000.0f) {
142 obserr[iv][iloc] = 3.0f + 47.0f*(
std::abs(rdelz)-1000.0f)/4000.0f;
144 pgesorig = model_pres_sfc[iloc]*0.001;
145 psges = log(pgesorig);
149 if (ob_temperature_sfc[iloc] !=
missing) {
150 drbx = 0.5f*
std::abs(model_temp_sfc[iloc]-ob_temperature_sfc[iloc])
152 tges = 0.5f*(model_temp_sfc[iloc]+ob_temperature_sfc[iloc]);
158 tges = model_temp_sfc[iloc];
160 }
else if (rdelz > 0.0) {
161 tges2 = model_temp_sfc[iloc] - lapse_rate*rdelz;
162 drbx = 0.5f*
std::abs(model_temp_sfc[iloc]-tges2)+2.5f+0.005f*
std::abs(rdelz);
163 tges = 0.5f*(model_temp_sfc[iloc]+tges2);
165 tges = model_temp_sfc[iloc] - 0.5f*lapse_rate*rdelz;
166 tges2 = tges - lapse_rate*rdelz;
167 drbx = 0.5f*
std::abs(model_temp_sfc[iloc]-tges2)+2.5f+0.005f*
std::abs(rdelz);
168 drbx = drbx - 0.5f*lapse_rate*rdelz;
172 rdp = g_over_rd*rdelz/tges;
173 pges = exp(log(pgesorig) - rdp);
174 drdp = pges*(g_over_rd*
std::abs(rdelz)*drbx/(tges*tges));
175 ddiff = ob_pressure_sfc[iloc]*0.001f - pges;
178 obserror = currentObserr[iloc]*0.001f;
183 new_error = obserror + drdp;
184 new_error = std::max(error_min*0.001f, std::min(new_error, error_max*0.001f));
185 error_factor = std::max(0.7f, new_error/obserror);
187 obserr[iv][iloc] = error_factor;
195 const ufo::Variables & ObsErrorFactorSfcPressure::requiredVariables()
const {
Options controlling ObsErrorFactorSfcPressure ObsFunction.
real(kind_real), parameter, public rd
real(kind_real), parameter, public grav
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)