UFO
WindDirAngleDiff.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 <valarray>
13 #include <vector>
14 
15 #include "ioda/ObsDataVector.h"
16 #include "oops/util/missingValues.h"
17 #include "ufo/filters/Variable.h"
18 #include "ufo/utils/Constants.h"
19 
20 namespace ufo {
21 
23 
24 // -----------------------------------------------------------------------------
25 
26 WindDirAngleDiff::WindDirAngleDiff(const eckit::LocalConfiguration & conf)
27  : invars_() {
28  oops::Log::debug() << "WindDirAngleDiff: config = " << conf << std::endl;
29  // Initialize options
30  options_.deserialize(conf);
31 
32  // We need to retrieve the observed wind components.
33  invars_ += Variable("eastward_wind@ObsValue");
34  invars_ += Variable("northward_wind@ObsValue");
35 
36  // Typical use would be HofX group, but during testing, we include option for GsiHofX
37  std::string test_hofx = options_.test_hofx.value();
38  invars_ += Variable("eastward_wind@" + test_hofx);
39  invars_ += Variable("northward_wind@" + test_hofx);
40 
41  // TODO(gthompsn): Need to include a check that whatever HofX group name used actually exists.
42 }
43 
44 // -----------------------------------------------------------------------------
45 
46 WindDirAngleDiff::~WindDirAngleDiff() {}
47 
48 // -----------------------------------------------------------------------------
49 
50 void WindDirAngleDiff::compute(const ObsFilterData & in,
51  ioda::ObsDataVector<float> & out) const {
52  const size_t nlocs = in.nlocs();
53  const float missing = util::missingValue(missing);
54  const double deg = Constants::rad2deg;
55 
56  // Ensure that only one output variable is expected.
57  ASSERT(out.nvars() == 1);
58 
59  // Retrieve minimum_uv value and assure it is sensible.
60  const float min_uv = std::max(0.0001f, options_.minimum_uv.value());
61 
62  // Retrieve observations of wind components
63  std::vector<float> u, v;
64  in.get(Variable("eastward_wind@ObsValue"), u);
65  in.get(Variable("northward_wind@ObsValue"), v);
66  // Retrieve Model HofX wind components
67  std::string test_hofx = options_.test_hofx.value();
68  std::vector<float> um, vm;
69  in.get(Variable("eastward_wind@" + test_hofx), um);
70  in.get(Variable("northward_wind@" + test_hofx), vm);
71 
72  double wdir_obs, wdir_model;
73 
74  for (size_t jj = 0; jj < nlocs; ++jj) {
75  if (u[jj] != missing && v[jj] != missing) {
76  if (std::abs(u[jj]) < min_uv && std::abs(v[jj]) < min_uv) {
77  out[0][jj] = 0.0;
78  } else {
79  wdir_obs = std::atan2(-u[jj], -v[jj])*deg;
80  wdir_model = std::atan2(-um[jj], -vm[jj])*deg;
81  out[0][jj] = std::min({std::abs(wdir_obs-wdir_model),
82  std::abs(wdir_obs-wdir_model+360.0),
83  std::abs(wdir_obs-wdir_model-360.0)});
84  }
85  } else {
86  out[0][jj] = missing;
87  }
88  }
89 }
90 
91 // -----------------------------------------------------------------------------
92 
93 const ufo::Variables & WindDirAngleDiff::requiredVariables() const {
94  return invars_;
95 }
96 
97 // -----------------------------------------------------------------------------
98 
99 } // namespace ufo
constexpr int missing
Definition: QCflags.h:20
real(kind_real), parameter, public rad2deg
integer function nlocs(this)
Return the number of observational locations in this Locations object.
Definition: RunCRTM.h:27
util::Duration abs(const util::Duration &duration)
static ObsFunctionMaker< WindDirAngleDiff > makerObsFuncWindDirAngleDiff_("WindDirAngleDiff")