OOPS
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  void write(const eckit::Configuration &) const;
61 
62  /// Accessors
63  size_t size() const {return ensemblePerturbs_.size();}
64  Increment_ & operator[](const int ii) {return ensemblePerturbs_[ii];}
65  const Increment_ & operator[](const int ii) const {return ensemblePerturbs_[ii];}
66 
67  /// Control variables
68  const Variables & controlVariables() const {return vars_;}
69 
70  private:
72  std::vector<Increment_> ensemblePerturbs_;
73 };
74 
75 // ====================================================================================
76 
77 template<typename MODEL>
79  const util::DateTime & tslot, const int rank)
80  : vars_(vars), ensemblePerturbs_()
81 {
82  ensemblePerturbs_.reserve(rank);
83  for (int m = 0; m < rank; ++m) {
84  ensemblePerturbs_.emplace_back(resol, vars_, tslot);
85  }
86  Log::trace() << "IncrementEnsemble:contructor done" << std::endl;
87 }
88 
89 // -----------------------------------------------------------------------------
90 
91 template<typename MODEL>
92 IncrementEnsemble<MODEL>::IncrementEnsemble(const eckit::Configuration & conf,
93  const State_ & xb, const State_ & fg,
94  const Geometry_ & resol, const Variables & vars)
95  : vars_(vars), ensemblePerturbs_()
96 {
97  // Check sizes and fill in timeslots
98  util::DateTime tslot = xb.validTime();
99 
100  // Read inflation field
101  std::unique_ptr<Increment_> inflationField;
102  if (conf.has("inflation field")) {
103  const eckit::LocalConfiguration inflationConfig(conf, "inflation field");
104  inflationField.reset(new Increment_(resol, vars, tslot));
105  inflationField->read(inflationConfig);
106  }
107 
108  // Get inflation value
109  double inflationValue = conf.getDouble("inflation value", 1.0);
110 
111  // Setup change of variable
112  ChvarVec_ chvars;
113  std::vector<eckit::LocalConfiguration> chvarconfs;
114  conf.get("variable changes", chvarconfs);
115  for (const auto & conf : chvarconfs) {
116  chvars.push_back(LinearVariableChangeFactory<MODEL>::create(xb, fg, resol, conf));
117  }
118  // TODO(Benjamin): one change of variable for each timeslot
119 
120  // Read ensemble
121  StateEnsemble_ ensemble(resol, conf);
122  State_ bgmean = ensemble.mean();
123 
124  ensemblePerturbs_.reserve(ensemble.size());
125  for (unsigned int ie = 0; ie < ensemble.size(); ++ie) {
126  // Ensemble will be centered around ensemble mean
127  Increment_ dx(resol, vars_, tslot);
128  dx.diff(ensemble[ie], bgmean);
129 
130  // Apply inflation
131  if (conf.has("inflation field")) {
132  dx.schur_product_with(*inflationField);
133  }
134  dx *= inflationValue;
135 
136  // Apply inverse of the linear balance operator
137  // K_1^{-1} K_2^{-1} .. K_N^{-1}
138  for (ircst_ it = chvars.rbegin(); it != chvars.rend(); ++it) {
139  dx = it->multiplyInverse(dx);
140  }
141 
142  ensemblePerturbs_.emplace_back(std::move(dx));
143  }
144  Log::trace() << "IncrementEnsemble:contructor done" << std::endl;
145 }
146 
147 // -----------------------------------------------------------------------------
148 
149 template<typename MODEL>
151  const eckit::Configuration & config)
152  : vars_(vars), ensemblePerturbs_()
153 {
154  std::vector<eckit::LocalConfiguration> memberConfig;
155  config.get("members", memberConfig);
156 
157  // Datetime for ensemble
158  util::DateTime tslot = util::DateTime(config.getString("date"));
159 
160  // Reserve memory to hold ensemble
161  ensemblePerturbs_.reserve(memberConfig.size());
162 
163  // Loop over all ensemble members
164  for (size_t jj = 0; jj < memberConfig.size(); ++jj) {
165  Increment_ dx(resol, vars_, tslot);
166  dx.read(memberConfig[jj]);
167  ensemblePerturbs_.emplace_back(std::move(dx));
168  }
169  Log::trace() << "IncrementEnsemble:contructor (by reading increment ensemble) done" << std::endl;
170 }
171 
172 // -----------------------------------------------------------------------------
173 
174 template<typename MODEL>
176  const eckit::Configuration & configBase,
177  const eckit::Configuration & configPert)
178  : vars_(vars), ensemblePerturbs_()
179 {
180  std::vector<eckit::LocalConfiguration> memberConfigBase;
181  configBase.get("members", memberConfigBase);
182 
183  std::vector<eckit::LocalConfiguration> memberConfigPert;
184  configPert.get("members", memberConfigPert);
185 
186  // Ensure input ensembles are of the same size
187  ASSERT(memberConfigBase.size() == memberConfigPert.size());
188 
189  // Reserve memory to hold ensemble
190  ensemblePerturbs_.reserve(memberConfigBase.size());
191 
192  // Loop over all ensemble members
193  for (size_t jj = 0; jj < memberConfigBase.size(); ++jj) {
194  State_ xBase(resol, memberConfigBase[jj]);
195  State_ xPert(resol, memberConfigPert[jj]);
196  Increment_ dx(resol, vars_, xBase.validTime());
197  dx.diff(xBase, xPert);
198  ensemblePerturbs_.emplace_back(std::move(dx));
199  }
200  Log::trace() << "IncrementEnsemble:contructor (by diffing state ensembles) done" << std::endl;
201 }
202 
203 // -----------------------------------------------------------------------------
204 
205 template<typename MODEL>
206 void IncrementEnsemble<MODEL>::write(const eckit::Configuration & config) const
207 {
208  eckit::LocalConfiguration outConfig(config);
209  for (size_t ii=0; ii < size(); ++ii) {
210  outConfig.set("member", ii+1);
211  ensemblePerturbs_[ii].write(outConfig);
212  }
213 }
214 
215 // -----------------------------------------------------------------------------
216 
217 } // namespace oops
218 
219 #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.
void write(const eckit::Configuration &) const
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.