16 #include "ioda/distribution/Accumulator.h"
17 #include "ioda/ObsDataVector.h"
18 #include "ioda/ObsSpace.h"
19 #include "oops/util/missingValues.h"
22 #include "eckit/exception/Exceptions.h"
23 #include "oops/util/Logger.h"
122 std::ostringstream errString;
125 if (
profile !=
"eastward_wind" &&
profile !=
"northward_wind" ) {
126 errString <<
"Wind component must be one of eastward_wind or northward_wind" << std::endl;
127 throw eckit::BadValue(errString.str());
131 if ( vcoord !=
"air_pressure" && vcoord !=
"air_pressure_levels" ) {
132 errString <<
"Vertical coordinate must be air_pressure or air_pressure_levels" << std::endl;
133 throw eckit::BadValue(errString.str());
144 std::vector<float> ob_p;
145 std::vector<float> bg_windcomponent;
146 std::vector<float> pressure_error;
147 std::vector<float> ob_qi;
155 std::vector<std::vector<float>> cx_p(nlevs, std::vector<float>(
nlocs));
156 for (
size_t ilev = 0; ilev < nlevs; ++ilev) {
157 in.
get(
Variable(vcoord+
"@GeoVaLs"), ilev, cx_p[ilev]);
161 std::vector<std::vector<float>> cx_windcomponent(nlevs, std::vector<float>(
nlocs));
162 for (
size_t ilev = 0; ilev < nlevs; ++ilev) {
167 std::unique_ptr<ioda::Accumulator<size_t>> countQiAccumulator =
168 obsdb.distribution()->createAccumulator<
size_t>();
171 for (
size_t iloc=0; iloc <
nlocs; ++iloc) {
173 float error_press = 0.0;
174 float error_vector = 3.5;
176 double sum_top = 0.0;
177 double sum_weight = 0.0;
184 float const min_pressure_error = 500;
185 float const max_pressure_error = 50000;
186 if ( pressure_error[iloc] ==
missing ||
187 pressure_error[iloc] < min_pressure_error ||
188 pressure_error[iloc] > max_pressure_error ) {
189 errString <<
"Pressure error invalid: " << pressure_error[iloc] <<
" Pa" << std::endl;
190 throw eckit::BadValue(errString.str());
194 if ( (ob_qi[iloc] !=
missing) &&
195 (ob_qi[iloc] > 0.0) &&
196 (ob_qi[iloc] <= 100.0)) {
197 error_vector = eu_mult * (ob_qi[iloc] * 0.01) + eu_add;
199 countQiAccumulator->addTerm(iloc, 1);
204 for (
size_t ilev = 1; ilev < nlevs; ++ilev) {
206 if (cx_p[ilev][iloc] < min_press) {
210 if (pressure_error[iloc] > 0) {
211 weight = exp(-0.5 * pow(cx_p[ilev][iloc] - ob_p[iloc], 2) /
212 pow(pressure_error[iloc], 2) )
213 *
std::abs(cx_p[ilev][iloc] - cx_p[ilev - 1][iloc]);
219 double const min_weight = 0.00001;
220 if (weight < min_weight) {
224 sum_top = sum_top + weight * pow(cx_windcomponent[ilev][iloc] - bg_windcomponent[iloc], 2);
225 sum_weight = sum_weight + weight;
228 if (sum_weight > 0) {
229 error_press = sqrt(sum_top / sum_weight);
232 obserr[0][iloc] = sqrt(pow(error_vector, 2) +
233 pow(error_press, 2) );
236 const std::size_t countQi = countQiAccumulator->computeResult();
238 oops::Log::warning() <<
"Satwind Indiv Errors: " << countQi
239 <<
" observations with bad/missing QI. Using default vector err in these cases" << std::endl;
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.
SatwindIndivErrorsParameters options_
void compute(const ObsFilterData &, ioda::ObsDataVector< float > &) const
Function to calculate situation dependent observation errors for satwinds.
const ufo::Variables & requiredVariables() const
geovals required to compute the function
SatwindIndivErrors(const eckit::LocalConfiguration &)
oops::RequiredParameter< Variable > pressure_error
Name of the variable containing the input height error estimates (Pa)
oops::Parameter< float > min_press
Ignore contribution above height of minimum pressure (Pa)
oops::RequiredParameter< float > eu_mult
Vector error estimate multiply.
oops::RequiredParameter< Variable > quality_index
Name of the variable containing quality index values for use in the vector error calculation.
oops::RequiredParameter< std::string > vcoord
String containing the vertical coordinate to use for the wind component.
oops::RequiredParameter< std::string > profile
String containing the name of the wind component we are calculating the error for.
oops::RequiredParameter< float > eu_add
Vector error estimate addition.
integer function nlocs(this)
Return the number of observational locations in this Locations object.
util::Duration abs(const util::Duration &duration)
static ObsFunctionMaker< SatwindIndivErrors > makerSatwindIndivErrors_("SatwindIndivErrors")