UFO
ObsErrorModelQuad.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2020 UCAR
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 
9 
10 #include <algorithm>
11 #include <cmath>
12 #include <set>
13 #include <string>
14 #include <vector>
15 
16 #include "ioda/ObsDataVector.h"
17 #include "oops/util/CompareNVectors.h"
18 #include "oops/util/IntSetParser.h"
19 #include "oops/util/Logger.h"
20 #include "oops/util/PropertiesOfNVectors.h"
21 #include "ufo/filters/Variable.h"
22 #include "ufo/utils/Constants.h"
23 
24 namespace ufo {
25 
26 static ObsFunctionMaker<ObsErrorModelQuad>
27  makerQuad_("ObsErrorModelQuad");
28 
29 // -----------------------------------------------------------------------------
30 
31 ObsErrorModelQuad::ObsErrorModelQuad(const eckit::LocalConfiguration & config)
32  : invars_() {
33  // Initialize options
34  options_.deserialize(config);
35 
36  // Initialize y-variable
37  eckit::LocalConfiguration yconf;
38  yconf.set("name", classname());
39  if (options_.chlist.value() != boost::none) {
40  yconf.set("channels", options_.chlist.value().get());
41  }
42  yconf.set("options", config);
43  Variable yvar(yconf);
44 
45  // Initialize x-variable
46  const Variable &xvar = options_.xvar.value();
47  ASSERT(xvar.size() == 1 ||
48  xvar.size() == yvar.size());
49  invars_ += xvar;
50 
51  // Get piece-wise parameters from options
52  const std::vector<float> &a = options_.a.value();
53  const std::vector<float> &b = options_.b.value();
54  const std::vector<float> &err0 = options_.err0.value();
55  const std::vector<float> &err1 = options_.err1.value();
56 
57  // Check parameter sizes/values
58  if (!oops::allVectorsSameNonZeroSize(a, b, err0, err1)) {
59  oops::Log::warning() << "At least one vector is the wrong size. "
60  << "Check will not be performed." << std::endl;
61  oops::Log::warning() << "Vector sizes: "
62  << oops::listOfVectorSizes(a, b, err0, err1)
63  << std::endl;
64  return;
65  }
66 
67  for (size_t i = 0; i < yvar.size(); ++i) {
68  ASSERT(abs(a[i]) > 0.0);
69  ASSERT(err0[i] > 0.0);
70  ASSERT(err1[i] > 0.0);
71  ASSERT(err1[i] >= err0[i]);
72  }
73 }
74 
75 // -----------------------------------------------------------------------------
76 
78 
79 // -----------------------------------------------------------------------------
80 
82  ioda::ObsDataVector<float> & out) const {
83  const float missing = util::missingValue(missing);
84 
85  // Get piece-wise parameters from options
86  const std::vector<float> &a = options_.a.value();
87  const std::vector<float> &b = options_.b.value();
88  const std::vector<float> &err0 = options_.err0.value();
89  const std::vector<float> &err1 = options_.err1.value();
90 
91  // Check out size
92  ASSERT(out.nvars() == a.size());
93 
94  // Compute x values
95  const Variable &xvar = options_.xvar.value();
97  in.get(xvar, xvals);
98 
99  // Optional save of the xfunc values
100  if (options_.save) xvals.save("ObsFunction");
101 
102  float x0, x1, c;
103 
104  for (size_t jvar = 0; jvar < out.nvars(); ++jvar) {
105  size_t ivar = std::min(jvar, xvar.size() - 1);
106 
107  // Calculate the inflection point x-values (x0, x1)
108  // and quadratic apex y-value (c)
109  if (a[jvar] < 0.0f) {
110  c = err1[jvar];
111  x1 = b[jvar];
112  x0 = x1 - sqrt((err0[jvar] - c) / a[jvar]);
113  } else {
114  c = err0[jvar];
115  x0 = b[jvar];
116  x1 = x0 + sqrt((err1[jvar] - c) / a[jvar]);
117  }
118 
119  // Calculate piece-wise function value across locations
120  for (size_t iloc = 0; iloc < in.nlocs(); ++iloc) {
121  out[jvar][iloc] = missing;
122  if (xvals[ivar][iloc] != missing) {
123  if (xvals[ivar][iloc] <= x0) {
124  out[jvar][iloc] = err0[jvar];
125  } else if (xvals[ivar][iloc] < x1) {
126  out[jvar][iloc] = a[jvar] * pow(xvals[ivar][iloc] - b[jvar], 2) + c;
127  } else {
128  out[jvar][iloc] = err1[jvar];
129  }
130  }
131  }
132  }
133 }
134 
135 // -----------------------------------------------------------------------------
136 
138  return invars_;
139 }
140 
141 // -----------------------------------------------------------------------------
142 
143 } // namespace ufo
ObsErrorModelQuad(const eckit::LocalConfiguration &)
static const std::string classname()
ObsErrorModelQuadParameters options_
const ufo::Variables & requiredVariables() const
geovals required to compute the function
void compute(const ObsFilterData &, ioda::ObsDataVector< float > &) const
compute the result of the function
oops::Parameter< bool > save
whether to save the xfunc values to the ObsSpace
oops::RequiredParameter< Variable > xvar
x variable of the piece-wise function
oops::RequiredParameter< std::vector< float > > b
x-coordinate of the quadratic function apex
oops::OptionalParameter< std::string > chlist
oops::RequiredParameter< std::vector< float > > err0
y-coordinate of the lower piecewise inflection point
oops::RequiredParameter< std::vector< float > > err1
y-coordinate of the upper piecewise inflection point
oops::RequiredParameter< std::vector< float > > a
curvature of the quadratic function
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.
void get(const Variable &varname, std::vector< float > &values) const
Fills a std::vector with values of the specified variable.
oops::Variables toOopsVariables() const
Definition: Variable.cc:139
size_t size() const
Definition: Variable.cc:78
constexpr int missing
Definition: QCflags.h:20
Definition: RunCRTM.h:27
static ObsFunctionMaker< ObsErrorModelQuad > makerQuad_("ObsErrorModelQuad")
util::Duration abs(const util::Duration &duration)