IODA Bundle
CalcHofX.h
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 #ifndef OOPS_ASSIMILATION_CALCHOFX_H_
8 #define OOPS_ASSIMILATION_CALCHOFX_H_
9 
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 #include "eckit/config/LocalConfiguration.h"
15 
17 #include "oops/base/Observations.h"
18 #include "oops/base/ObsFilters.h"
19 #include "oops/base/ObsSpaces.h"
20 #include "oops/base/Variables.h"
21 #include "oops/interface/GeoVaLs.h"
27 #include "oops/util/Logger.h"
28 #include "oops/util/parameters/Parameter.h"
29 #include "oops/util/parameters/Parameters.h"
30 #include "oops/util/parameters/RequiredParameter.h"
31 
32 namespace oops {
33 
34 template <typename OBS>
35 class CalcHofXParameters : public Parameters {
36  OOPS_CONCRETE_PARAMETERS(CalcHofXParameters, Parameters)
37 
38  public:
39  oops::RequiredParameter<eckit::LocalConfiguration> obsOperator{"obs operator", this};
40  oops::Parameter<std::vector<ObsFilterParametersWrapper<OBS>>> obsFilters{"obs filters", {}, this};
41 };
42 
43 // -----------------------------------------------------------------------------
44 
45 /// \brief Computes observation operator (from GeoVaLs), applies bias correction
46 /// and runs QC filters
47 template <typename OBS>
48 class CalcHofX {
58  template <typename DATA> using ObsData_ = ObsDataVector<OBS, DATA>;
59  template <typename DATA> using ObsDataVec_ = std::vector<std::shared_ptr<ObsData_<DATA>>>;
60 
61  typedef std::vector<std::unique_ptr<GeoVaLs_>> GeoVaLsVec_;
62  typedef std::vector<std::unique_ptr<Locations_>> LocationsVec_;
63  typedef std::vector<std::unique_ptr<ObsFilters_>> ObsFiltersVec_;
64  typedef std::vector<std::unique_ptr<ObsOperator_>> ObsOperatorVec_;
65  typedef std::vector<std::shared_ptr<ObsVector_>> ObsVectorVec_;
66  typedef std::vector<Variables> VariablesVec_;
67 
68  public:
69 /// \brief Initializes ObsOperators, Locations, and QC data
70  CalcHofX(const ObsSpaces_ &, const eckit::Configuration &);
71 
72 /// \brief Initializes variables, obs bias, obs filters (could be different for
73 /// different iterations
74  void initialize(const ObsAuxCtrls_ &, const int iteration = 0);
75 
76 /// \brief Computes H(x) from the filled in GeoVaLs
78 
79 /// \brief accessor to the locations
80  const LocationsVec_ & locations() const { return locations_; }
81 /// \brief accessor to variables required from the model
82  const VariablesVec_ & requiredVars() const { return geovars_; }
83 /// \brief accessor to QC flags
84  const ObsDataVec_<int> & qcflags() const { return qcflags_; }
85 
86 /// \brief read QC flags from \p qcname variable from file
87  void readQcFlags(const std::string & qcname);
88 /// \brief reset QC flags and ObsErrors
89  void resetQc();
90 /// \brief save QC flags to ObsSpaces
91  void saveQcFlags(const std::string &) const;
92 /// \brief save obs error variances (modified in QC) to ObsSpaces
93  void saveObsErrors(const std::string &) const;
94 /// \brief mask obs errors with QC flags
95  void maskObsErrors();
96 
97  private:
98  eckit::LocalConfiguration obsconfig_;
99  const ObsSpaces_ & obspaces_; // ObsSpaces used in H(x)
100  ObsOperatorVec_ obsops_; // Obs operators
101  LocationsVec_ locations_; // locations
102  const ObsAuxCtrls_ * ybias_; // Obs bias
104  ObsVectorVec_ obserrs_; // Obs error variances (used in QC filters)
105  ObsFiltersVec_ filters_; // QC filters
106  VariablesVec_ geovars_; // variables required from the model
107 };
108 
109 // -----------------------------------------------------------------------------
110 
111 template <typename OBS>
113  const eckit::Configuration & config) :
114  obsconfig_(config), obspaces_(obspaces), obsops_(), locations_(),
115  ybias_(nullptr), qcflags_(), obserrs_(), filters_(),
116  geovars_(obspaces_.size())
117 {
118  std::vector<eckit::LocalConfiguration> obsconfs = config.getSubConfigurations();
119  for (size_t jj = 0; jj < obspaces_.size(); ++jj) {
120  // obsconfs[jj] contains not only options controlling the obs operator and filters (known to
121  // CalcHofX) but also those controlling the obs space (unknown to it). So we can't call
122  // validateAndDeserialize() here, since "obs space" would be treated as an unrecognized
123  // keyword. In the long term the code constructing the CalcHofX will probably need to split
124  // the contents of the "observations" vector into two vectors, one containing the "obs space"
125  // sections and the other the "obs operator" and "obs filters" sections, and pass the former to
126  // the constructor of ObsSpaces and the latter to the constructor of CalcHofX.
127  CalcHofXParameters<OBS> observerParams;
128  observerParams.deserialize(obsconfs[jj]);
129  /// Set up observation operators
130  obsops_.emplace_back(new ObsOperator_(obspaces_[jj], observerParams.obsOperator));
131  locations_.emplace_back(new Locations_(obsops_[jj]->locations()));
132 
133  /// Allocate QC flags
134  qcflags_.emplace_back(std::make_shared<ObsData_<int>>(obspaces[jj],
135  obspaces[jj].obsvariables()));
136  /// Allocate and read initial obs error
137  obserrs_.emplace_back(std::make_shared<ObsVector_>(obspaces[jj], "ObsError"));
138  }
139  Log::trace() << "CalcHofX<OBS> constructed" << std::endl;
140 }
141 
142 // -----------------------------------------------------------------------------
143 
144 template <typename OBS>
145 void CalcHofX<OBS>::initialize(const ObsAuxCtrls_ & obsaux, const int iteration) {
146  std::vector<eckit::LocalConfiguration> obsconfs = obsconfig_.getSubConfigurations();
147  ybias_ = &obsaux;
148  filters_.clear();
149  for (size_t jj = 0; jj < obspaces_.size(); ++jj) {
150  CalcHofXParameters<OBS> observerParams;
151  observerParams.deserialize(obsconfs[jj]);
152  /// Set up QC filters and run preprocess
153  filters_.emplace_back(new ObsFilters_(obspaces_[jj], observerParams.obsFilters,
154  qcflags_[jj], *obserrs_[jj], iteration));
155  filters_[jj]->preProcess();
156 
157  /// Set up variables requested from the model
158  geovars_[jj] += obsops_[jj]->requiredVars();
159  geovars_[jj] += (*ybias_)[jj].requiredVars();
160  geovars_[jj] += filters_[jj]->requiredVars();
161  }
162  Log::trace() << "CalcHofX<OBS>::initialize done" << std::endl;
163 }
164 
165 // -----------------------------------------------------------------------------
166 
167 template <typename OBS>
169  oops::Log::trace() << "CalcHofX<OBS>::compute start" << std::endl;
170 
171  Observations<OBS> yobs(obspaces_);
172  for (size_t jj = 0; jj < obspaces_.size(); ++jj) {
173  /// call prior filters
174  filters_[jj]->priorFilter(*geovals[jj]);
175  /// compute H(x)
176  oops::Variables vars;
177  vars += filters_[jj]->requiredHdiagnostics();
178  vars += (*ybias_)[jj].requiredHdiagnostics();
179  ObsDiags_ ydiags(obspaces_[jj], *locations_[jj], vars);
180  obsops_[jj]->simulateObs(*geovals[jj], yobs[jj], (*ybias_)[jj], ydiags);
181  /// call posterior filters
182  filters_[jj]->postFilter(yobs[jj], ydiags);
183  }
184  oops::Log::trace() << "CalcHofX<OBS>::compute done" << std::endl;
185  return yobs;
186 }
187 
188 // -----------------------------------------------------------------------------
189 
190 template <typename OBS>
191 void CalcHofX<OBS>::readQcFlags(const std::string & qcname) {
192  for (const auto & qcflag : qcflags_) {
193  qcflag->read(qcname);
194  }
195 }
196 
197 // -----------------------------------------------------------------------------
198 
199 template <typename OBS>
201  for (const auto & qcflag : qcflags_) {
202  qcflag->zero();
203  }
204  for (const auto & obserr : obserrs_) {
205  obserr->read("ObsError");
206  }
207 }
208 
209 // -----------------------------------------------------------------------------
210 
211 template <typename OBS>
212 void CalcHofX<OBS>::saveQcFlags(const std::string & name) const {
213  for (const auto & qcflag : qcflags_) {
214  qcflag->save(name);
215  }
216 }
217 
218 // -----------------------------------------------------------------------------
219 
220 template <typename OBS>
221 void CalcHofX<OBS>::saveObsErrors(const std::string & name) const {
222  for (const auto & obserr : obserrs_) {
223  obserr->save(name);
224  }
225 }
226 
227 // -----------------------------------------------------------------------------
228 
229 template <typename OBS>
231  for (size_t jj = 0; jj < obserrs_.size(); ++jj) {
232  obserrs_[jj]->mask(*qcflags_[jj]);
233  }
234 }
235 
236 // -----------------------------------------------------------------------------
237 
238 } // namespace oops
239 
240 #endif // OOPS_ASSIMILATION_CALCHOFX_H_
Computes observation operator (from GeoVaLs), applies bias correction and runs QC filters.
Definition: CalcHofX.h:48
ObsDataVec_< int > qcflags_
Definition: CalcHofX.h:103
Observations< OBS > Observations_
Definition: CalcHofX.h:53
void saveObsErrors(const std::string &) const
save obs error variances (modified in QC) to ObsSpaces
Definition: CalcHofX.h:221
void initialize(const ObsAuxCtrls_ &, const int iteration=0)
Initializes variables, obs bias, obs filters (could be different for different iterations.
Definition: CalcHofX.h:145
ObsSpaces< OBS > ObsSpaces_
Definition: CalcHofX.h:56
std::vector< std::unique_ptr< ObsOperator_ > > ObsOperatorVec_
Definition: CalcHofX.h:64
std::vector< std::shared_ptr< ObsVector_ > > ObsVectorVec_
Definition: CalcHofX.h:65
const ObsDataVec_< int > & qcflags() const
accessor to QC flags
Definition: CalcHofX.h:84
ObsFilters< OBS > ObsFilters_
Definition: CalcHofX.h:54
std::vector< std::unique_ptr< ObsFilters_ > > ObsFiltersVec_
Definition: CalcHofX.h:63
std::vector< std::unique_ptr< GeoVaLs_ > > GeoVaLsVec_
Definition: CalcHofX.h:61
ObsFiltersVec_ filters_
Definition: CalcHofX.h:105
ObsVector< OBS > ObsVector_
Definition: CalcHofX.h:57
const ObsAuxCtrls_ * ybias_
Definition: CalcHofX.h:102
const LocationsVec_ & locations() const
accessor to the locations
Definition: CalcHofX.h:80
eckit::LocalConfiguration obsconfig_
Definition: CalcHofX.h:98
Observations_ compute(const GeoVaLsVec_ &)
Computes H(x) from the filled in GeoVaLs.
Definition: CalcHofX.h:168
ObsVectorVec_ obserrs_
Definition: CalcHofX.h:104
void resetQc()
reset QC flags and ObsErrors
Definition: CalcHofX.h:200
void saveQcFlags(const std::string &) const
save QC flags to ObsSpaces
Definition: CalcHofX.h:212
const ObsSpaces_ & obspaces_
Definition: CalcHofX.h:99
Locations< OBS > Locations_
Definition: CalcHofX.h:50
ObsOperatorVec_ obsops_
Definition: CalcHofX.h:100
LocationsVec_ locations_
Definition: CalcHofX.h:101
const VariablesVec_ & requiredVars() const
accessor to variables required from the model
Definition: CalcHofX.h:82
CalcHofX(const ObsSpaces_ &, const eckit::Configuration &)
Initializes ObsOperators, Locations, and QC data.
Definition: CalcHofX.h:112
GeoVaLs< OBS > GeoVaLs_
Definition: CalcHofX.h:49
void maskObsErrors()
mask obs errors with QC flags
Definition: CalcHofX.h:230
ObsAuxControls< OBS > ObsAuxCtrls_
Definition: CalcHofX.h:51
std::vector< Variables > VariablesVec_
Definition: CalcHofX.h:66
ObsDiagnostics< OBS > ObsDiags_
Definition: CalcHofX.h:52
VariablesVec_ geovars_
Definition: CalcHofX.h:106
std::vector< std::unique_ptr< Locations_ > > LocationsVec_
Definition: CalcHofX.h:62
void readQcFlags(const std::string &qcname)
read QC flags from qcname variable from file
Definition: CalcHofX.h:191
std::vector< std::shared_ptr< ObsData_< DATA > >> ObsDataVec_
Definition: CalcHofX.h:59
ObsOperator< OBS > ObsOperator_
Definition: CalcHofX.h:55
oops::RequiredParameter< eckit::LocalConfiguration > obsOperator
Definition: CalcHofX.h:39
oops::Parameter< std::vector< ObsFilterParametersWrapper< OBS > > > obsFilters
Definition: CalcHofX.h:40
Locations of observations for observation operator.
Holds observation filters (usually QC) for one observation type.
Definition: ObsFilters.h:36
std::size_t size() const
Access.
Definition: ObsSpaces.h:53
Observations Class.
Definition: Observations.h:35
The namespace for the main oops code.