IODA Bundle
IncrementEnsemble.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2009-2016 ECMWF.
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  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
11 #ifndef OOPS_BASE_INCREMENTENSEMBLE_H_
12 #define OOPS_BASE_INCREMENTENSEMBLE_H_
13 
14 #include <memory>
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 #include <boost/ptr_container/ptr_vector.hpp>
20 
21 #include "eckit/config/LocalConfiguration.h"
22 #include "oops/base/Accumulator.h"
23 #include "oops/base/Geometry.h"
24 #include "oops/base/Increment.h"
26 #include "oops/base/State.h"
28 #include "oops/base/Variables.h"
29 #include "oops/util/DateTime.h"
30 #include "oops/util/Logger.h"
31 
32 namespace oops {
33 
34 // -----------------------------------------------------------------------------
35 
36 /// \brief Ensemble of inrements
37 template<typename MODEL> class IncrementEnsemble {
43 
44  typedef typename boost::ptr_vector<LinearVariableChangeBase_> ChvarVec_;
45  typedef typename ChvarVec_::const_reverse_iterator ircst_;
46 
47  public:
48  /// Constructor
49  IncrementEnsemble(const Geometry_ & resol, const Variables & vars,
50  const util::DateTime &, const int rank);
51  IncrementEnsemble(const eckit::Configuration &, const State_ &, const State_ &,
52  const Geometry_ &, const Variables &);
53  /// \brief construct ensemble of perturbations by reading them from disk
54  IncrementEnsemble(const Geometry_ &, const Variables &, const eckit::Configuration &);
55  /// \brief construct ensemble of perturbations by reading two state ensembles (one member at a
56  // time) and taking the difference of each set of pairs
57  IncrementEnsemble(const Geometry_ &, const Variables &, const eckit::Configuration &,
58  const eckit::Configuration &);
59 
60  /// Accessors
61  size_t size() const {return ensemblePerturbs_.size();}
62  Increment_ & operator[](const int ii) {return ensemblePerturbs_[ii];}
63  const Increment_ & operator[](const int ii) const {return ensemblePerturbs_[ii];}
64 
65  /// Control variables
66  const Variables & controlVariables() const {return vars_;}
67 
68  private:
70  std::vector<Increment_> ensemblePerturbs_;
71 };
72 
73 // ====================================================================================
74 
75 template<typename MODEL>
77  const util::DateTime & tslot, const int rank)
78  : vars_(vars), ensemblePerturbs_()
79 {
80  ensemblePerturbs_.reserve(rank);
81  for (int m = 0; m < rank; ++m) {
82  ensemblePerturbs_.emplace_back(resol, vars_, tslot);
83  }
84  Log::trace() << "IncrementEnsemble:contructor done" << std::endl;
85 }
86 
87 // -----------------------------------------------------------------------------
88 
89 template<typename MODEL>
90 IncrementEnsemble<MODEL>::IncrementEnsemble(const eckit::Configuration & conf,
91  const State_ & xb, const State_ & fg,
92  const Geometry_ & resol, const Variables & vars)
93  : vars_(vars), ensemblePerturbs_()
94 {
95  // Check sizes and fill in timeslots
96  util::DateTime tslot = xb.validTime();
97 
98  // Read inflation field
99  std::unique_ptr<Increment_> inflationField;
100  if (conf.has("inflation field")) {
101  const eckit::LocalConfiguration inflationConfig(conf, "inflation field");
102  inflationField.reset(new Increment_(resol, vars, tslot));
103  inflationField->read(inflationConfig);
104  }
105 
106  // Get inflation value
107  double inflationValue = conf.getDouble("inflation value", 1.0);
108 
109  // Setup change of variable
110  ChvarVec_ chvars;
111  std::vector<eckit::LocalConfiguration> chvarconfs;
112  conf.get("variable changes", chvarconfs);
113  for (const auto & conf : chvarconfs) {
114  chvars.push_back(LinearVariableChangeFactory<MODEL>::create(xb, fg, resol, conf));
115  }
116  // TODO(Benjamin): one change of variable for each timeslot
117 
118  // Read ensemble
119  StateEnsemble_ ensemble(resol, conf);
120  State_ bgmean = ensemble.mean();
121 
122  ensemblePerturbs_.reserve(ensemble.size());
123  for (unsigned int ie = 0; ie < ensemble.size(); ++ie) {
124  // Ensemble will be centered around ensemble mean
125  Increment_ dx(resol, vars_, tslot);
126  dx.diff(ensemble[ie], bgmean);
127 
128  // Apply inflation
129  if (conf.has("inflation field")) {
130  dx.schur_product_with(*inflationField);
131  }
132  dx *= inflationValue;
133 
134  // Apply inverse of the linear balance operator
135  // K_1^{-1} K_2^{-1} .. K_N^{-1}
136  for (ircst_ it = chvars.rbegin(); it != chvars.rend(); ++it) {
137  dx = it->multiplyInverse(dx);
138  }
139 
140  ensemblePerturbs_.emplace_back(std::move(dx));
141  }
142  Log::trace() << "IncrementEnsemble:contructor done" << std::endl;
143 }
144 
145 // -----------------------------------------------------------------------------
146 
147 template<typename MODEL>
149  const eckit::Configuration & config)
150  : vars_(vars), ensemblePerturbs_()
151 {
152  std::vector<eckit::LocalConfiguration> memberConfig;
153  config.get("members", memberConfig);
154 
155  // Datetime for ensemble
156  util::DateTime tslot = util::DateTime(config.getString("date"));
157 
158  // Reserve memory to hold ensemble
159  ensemblePerturbs_.reserve(memberConfig.size());
160 
161  // Loop over all ensemble members
162  for (size_t jj = 0; jj < memberConfig.size(); ++jj) {
163  Increment_ dx(resol, vars_, tslot);
164  dx.read(memberConfig[jj]);
165  ensemblePerturbs_.emplace_back(std::move(dx));
166  }
167  Log::trace() << "IncrementEnsemble:contructor (by reading increment ensemble) done" << std::endl;
168 }
169 
170 // -----------------------------------------------------------------------------
171 
172 template<typename MODEL>
174  const eckit::Configuration & configBase,
175  const eckit::Configuration & configPert)
176  : vars_(vars), ensemblePerturbs_()
177 {
178  std::vector<eckit::LocalConfiguration> memberConfigBase;
179  configBase.get("members", memberConfigBase);
180 
181  std::vector<eckit::LocalConfiguration> memberConfigPert;
182  configPert.get("members", memberConfigPert);
183 
184  // Ensure input ensembles are of the same size
185  ASSERT(memberConfigBase.size() == memberConfigPert.size());
186 
187  // Reserve memory to hold ensemble
188  ensemblePerturbs_.reserve(memberConfigBase.size());
189 
190  // Loop over all ensemble members
191  for (size_t jj = 0; jj < memberConfigBase.size(); ++jj) {
192  State_ xBase(resol, memberConfigBase[jj]);
193  State_ xPert(resol, memberConfigPert[jj]);
194  Increment_ dx(resol, vars_, xBase.validTime());
195  dx.diff(xBase, xPert);
196  ensemblePerturbs_.emplace_back(std::move(dx));
197  }
198  Log::trace() << "IncrementEnsemble:contructor (by diffing state ensembles) done" << std::endl;
199 }
200 
201 // -----------------------------------------------------------------------------
202 
203 } // namespace oops
204 
205 #endif // OOPS_BASE_INCREMENTENSEMBLE_H_
Geometry class used in oops; subclass of interface class interface::Geometry.
Ensemble of inrements.
Increment< MODEL > Increment_
Increment_ & operator[](const int ii)
ChvarVec_::const_reverse_iterator ircst_
boost::ptr_vector< LinearVariableChangeBase_ > ChvarVec_
std::vector< Increment_ > ensemblePerturbs_
size_t size() const
Accessors.
StateEnsemble< MODEL > StateEnsemble_
IncrementEnsemble(const Geometry_ &resol, const Variables &vars, const util::DateTime &, const int rank)
Constructor.
const Increment_ & operator[](const int ii) const
LinearVariableChangeBase< MODEL > LinearVariableChangeBase_
Geometry< MODEL > Geometry_
const Variables & controlVariables() const
Control variables.
Increment class used in oops.
Ensemble of states.
Definition: StateEnsemble.h:26
size_t size() const
Accessors.
Definition: StateEnsemble.h:38
State_ mean() const
calculate ensemble mean
Definition: StateEnsemble.h:68
State class used in oops; subclass of interface class interface::State.
void schur_product_with(const Increment &other)
Compute Schur product of this Increment with other, assign to this Increment.
void read(const eckit::Configuration &)
Read this Increment from file.
void diff(const State_ &state1, const State_ &state2)
Set this Increment to be difference between state1 and state2.
const util::DateTime validTime() const
Accessor to the time of this State.
The namespace for the main oops code.