OOPS
LocalEnsembleSolver.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 
8 #ifndef OOPS_ASSIMILATION_LOCALENSEMBLESOLVER_H_
9 #define OOPS_ASSIMILATION_LOCALENSEMBLESOLVER_H_
10 
11 #include <map>
12 #include <memory>
13 #include <string>
14 
15 #include "eckit/config/LocalConfiguration.h"
17 #include "oops/base/Departures.h"
20 #include "oops/base/ObsEnsemble.h"
21 #include "oops/base/Observations.h"
22 #include "oops/base/ObsSpaces.h"
23 #include "oops/base/QCData.h"
27 #include "oops/util/Logger.h"
28 #include "oops/util/Timer.h"
29 
30 namespace oops {
31 
32 /// \brief Base class for LETKF-type solvers
33 template <typename MODEL, typename OBS>
46 
47  public:
48  static const std::string classname() {return "oops::LocalEnsembleSolver";}
49 
50  /// initialize solver with \p obspaces, \p geometry, full \p config and \p nens ensemble size
51  LocalEnsembleSolver(ObsSpaces_ & obspaces, const Geometry_ & geometry,
52  const eckit::Configuration & config, size_t nens);
53  virtual ~LocalEnsembleSolver() = default;
54 
55  /// computes ensemble H(\p xx), returns mean H(\p xx), saves as hofx \p iteration
56  virtual Observations_ computeHofX(const StateEnsemble4D_ & xx, size_t iteration,
57  bool readFromDisk);
58 
59  /// update background ensemble \p bg to analysis ensemble \p an at a grid point location \p i
60  virtual void measurementUpdate(const IncrementEnsemble4D_ & bg,
61  const GeometryIterator_ & i, IncrementEnsemble4D_ & an) = 0;
62 
63  /// copy \p an[\p i] = \p bg[\p i] (e.g. when there are no local observations to update state)
64  virtual void copyLocalIncrement(const IncrementEnsemble4D_ & bg,
65  const GeometryIterator_ & i, IncrementEnsemble4D_ & an) const;
66 
67  protected:
68  const eckit::LocalConfiguration obsconf_; // configuration for observations
69  const ObsSpaces_ & obspaces_; // ObsSpaces
70  CalcHofX_ hofx_; // observer
71  Departures_ omb_; // obs - mean(H(x))
72  DeparturesEnsemble_ Yb_; // ensemble perturbations in the observation space
73 };
74 
75 // -----------------------------------------------------------------------------
76 
77 template <typename MODEL, typename OBS>
79  const Geometry_ & geometry,
80  const eckit::Configuration & config, size_t nens)
81  : obsconf_(config), obspaces_(obspaces),
82  hofx_(obspaces, geometry, config),
83  omb_(obspaces_), Yb_(obspaces_, nens)
84 {
85 }
86 
87 // -----------------------------------------------------------------------------
88 
89 template <typename MODEL, typename OBS>
91  size_t iteration, bool readFromDisk) {
92  util::Timer timer(classname(), "computeHofX");
93 
94  ASSERT(ens_xx.size() == Yb_.size());
95 
96  const size_t nens = ens_xx.size();
97  ObsEnsemble_ obsens(obspaces_, nens);
98  std::shared_ptr<QCData_> qc;
99 
100  if (readFromDisk) {
101  // read hofx from disk
102  Log::debug() << "Read H(X) from disk" << std::endl;
103  for (size_t jj = 0; jj < nens; ++jj) {
104  obsens[jj].read("hofx"+std::to_string(iteration)+"_"+std::to_string(jj+1));
105  Log::test() << "H(x) for member " << jj+1 << ":" << std::endl << obsens[jj] << std::endl;
106  }
107  qc.reset(new QCData_(obspaces_, "EffectiveQC", "EffectiveError"));
108 
109  } else {
110  // compute and save H(x)
111  Log::debug() << "Computing H(X) online" << std::endl;
112  for (size_t jj = 0; jj < nens; ++jj) {
113  obsens[jj] = hofx_.compute(ens_xx[jj]);
114  Log::test() << "H(x) for member " << jj+1 << ":" << std::endl << obsens[jj] << std::endl;
115  obsens[jj].save("hofx"+std::to_string(iteration)+"_"+std::to_string(jj+1));
116  }
117  // QC flags and Obs errors are set to that of the last ensemble member
118  // TODO(someone) combine qc flags from all ensemble members
119  qc = hofx_.qc();
120  hofx_.saveQcFlags("EffectiveQC");
121  hofx_.maskObsErrors(*qc);
122  hofx_.saveObsErrors("EffectiveError");
123  }
124 
125  // calculate H(x) ensemble mean
126  Observations_ yb_mean(obsens.mean());
127 
128  // calculate H(x) ensemble perturbations
129  for (size_t iens = 0; iens < nens; ++iens) {
130  Yb_[iens] = obsens[iens] - yb_mean;
131  Yb_[iens].mask(*qc);
132  }
133 
134  // calculate obs departures and mask with qc flag
135  Observations_ yobs(obspaces_, "ObsValue");
136  omb_ = yobs - yb_mean;
137  omb_.mask(*qc);
138 
139  // return mean H(x)
140  return yb_mean;
141 }
142 
143 // -----------------------------------------------------------------------------
144 
145 template <typename MODEL, typename OBS>
147  const GeometryIterator_ & i,
148  IncrementEnsemble4D_ & ana_pert) const {
149  // ana_pert[i]=bkg_pert[i]
150  for (size_t itime=0; itime < bkg_pert[0].size(); ++itime) {
151  for (size_t iens=0; iens < bkg_pert.size(); ++iens) {
152  LocalIncrement gp = bkg_pert[iens][itime].getLocal(i);
153  ana_pert[iens][itime].setLocal(gp, i);
154  }
155  }
156 }
157 
158 // =============================================================================
159 
160 /// \brief factory for LETKF solvers
161 template <typename MODEL, typename OBS>
165  public:
166  static std::unique_ptr<LocalEnsembleSolver<MODEL, OBS>> create(ObsSpaces_ &, const Geometry_ &,
167  const eckit::Configuration &,
168  size_t);
169  virtual ~LocalEnsembleSolverFactory() = default;
170  protected:
171  explicit LocalEnsembleSolverFactory(const std::string &);
172  private:
174  const eckit::Configuration &, size_t) = 0;
175  static std::map < std::string, LocalEnsembleSolverFactory<MODEL, OBS> * > & getMakers() {
176  static std::map < std::string, LocalEnsembleSolverFactory<MODEL, OBS> * > makers_;
177  return makers_;
178  }
179 };
180 
181 // -----------------------------------------------------------------------------
182 
183 template<class MODEL, class OBS, class T>
187 
188  virtual LocalEnsembleSolver<MODEL, OBS> * make(ObsSpaces_ & obspaces, const Geometry_ & geometry,
189  const eckit::Configuration & conf, size_t nens)
190  { return new T(obspaces, geometry, conf, nens); }
191  public:
192  explicit LocalEnsembleSolverMaker(const std::string & name)
193  : LocalEnsembleSolverFactory<MODEL, OBS>(name) {}
194 };
195 
196 // =============================================================================
197 
198 template <typename MODEL, typename OBS>
200  if (getMakers().find(name) != getMakers().end()) {
201  throw std::runtime_error(name + " already registered in local ensemble solver factory.");
202  }
203  getMakers()[name] = this;
204 }
205 
206 // -----------------------------------------------------------------------------
207 
208 template <typename MODEL, typename OBS>
209 std::unique_ptr<LocalEnsembleSolver<MODEL, OBS>>
211  const eckit::Configuration & conf, size_t nens) {
212  Log::trace() << "LocalEnsembleSolver<MODEL, OBS>::create starting" << std::endl;
213  const std::string id = conf.getString("local ensemble DA.solver");
214  typename std::map<std::string, LocalEnsembleSolverFactory<MODEL, OBS>*>::iterator
215  jloc = getMakers().find(id);
216  if (jloc == getMakers().end()) {
217  Log::error() << id << " does not exist in local ensemble solver factory." << std::endl;
218  Log::error() << "LETKF solver Factory has " << getMakers().size() << " elements:" << std::endl;
219  for (typename std::map<std::string, LocalEnsembleSolverFactory<MODEL, OBS>*>::const_iterator
220  jj = getMakers().begin(); jj != getMakers().end(); ++jj) {
221  Log::error() << "A " << jj->first << " LocalEnsembleSolver" << std::endl;
222  }
223  throw std::runtime_error(id + " does not exist in local ensemble solver factory.");
224  }
225  std::unique_ptr<LocalEnsembleSolver<MODEL, OBS>>
226  ptr(jloc->second->make(obspaces, geometry, conf, nens));
227  Log::trace() << "LocalEnsembleSolver<MODEL, OBS>::create done" << std::endl;
228  return ptr;
229 }
230 
231 // -----------------------------------------------------------------------------
232 
233 } // namespace oops
234 #endif // OOPS_ASSIMILATION_LOCALENSEMBLESOLVER_H_
oops
The namespace for the main oops code.
Definition: ErrorCovarianceL95.cc:22
oops::LocalEnsembleSolver::QCData_
QCData< OBS > QCData_
Definition: LocalEnsembleSolver.h:44
oops::LocalEnsembleSolverMaker
Definition: LocalEnsembleSolver.h:184
oops::LocalEnsembleSolver::CalcHofX_
CalcHofX< MODEL, OBS > CalcHofX_
Definition: LocalEnsembleSolver.h:35
oops::QCData
container for QC-related things (flags & obserrors)
Definition: QCData.h:24
oops::GeometryIterator
Definition: oops/interface/GeometryIterator.h:32
oops::LocalEnsembleSolver::obspaces_
const ObsSpaces_ & obspaces_
Definition: LocalEnsembleSolver.h:69
oops::LocalEnsembleSolver::ObsEnsemble_
ObsEnsemble< OBS > ObsEnsemble_
Definition: LocalEnsembleSolver.h:41
DeparturesEnsemble.h
oops::LocalEnsembleSolverFactory
factory for LETKF solvers
Definition: LocalEnsembleSolver.h:162
StateEnsemble4D.h
QCData.h
oops::CalcHofX
Computes observation operator (while running model, or with State4D)
Definition: CalcHofX.h:38
ObsSpaces.h
oops::LocalEnsembleSolver::ObsSpaces_
ObsSpaces< OBS > ObsSpaces_
Definition: LocalEnsembleSolver.h:43
oops::LocalEnsembleSolver::hofx_
CalcHofX_ hofx_
Definition: LocalEnsembleSolver.h:70
oops::LocalEnsembleSolverFactory::create
static std::unique_ptr< LocalEnsembleSolver< MODEL, OBS > > create(ObsSpaces_ &, const Geometry_ &, const eckit::Configuration &, size_t)
Definition: LocalEnsembleSolver.h:210
oops::LocalEnsembleSolver::IncrementEnsemble4D_
IncrementEnsemble4D< MODEL > IncrementEnsemble4D_
Definition: LocalEnsembleSolver.h:40
oops::StateEnsemble4D::size
unsigned int size() const
Accessors.
Definition: StateEnsemble4D.h:38
oops::LocalEnsembleSolver::Observations_
Observations< OBS > Observations_
Definition: LocalEnsembleSolver.h:42
Departures.h
ObsEnsemble.h
oops::LocalEnsembleSolver::GeometryIterator_
GeometryIterator< MODEL > GeometryIterator_
Definition: LocalEnsembleSolver.h:39
oops::LocalEnsembleSolverFactory::Geometry_
Geometry< MODEL > Geometry_
Definition: LocalEnsembleSolver.h:163
oops::LocalEnsembleSolverFactory::getMakers
static std::map< std::string, LocalEnsembleSolverFactory< MODEL, OBS > * > & getMakers()
Definition: LocalEnsembleSolver.h:175
oops::LocalEnsembleSolverFactory::ObsSpaces_
ObsSpaces< OBS > ObsSpaces_
Definition: LocalEnsembleSolver.h:164
oops::LocalEnsembleSolver::Departures_
Departures< OBS > Departures_
Definition: LocalEnsembleSolver.h:36
Observations.h
oops::LocalEnsembleSolver::measurementUpdate
virtual void measurementUpdate(const IncrementEnsemble4D_ &bg, const GeometryIterator_ &i, IncrementEnsemble4D_ &an)=0
update background ensemble bg to analysis ensemble an at a grid point location i
oops::LocalEnsembleSolver
Base class for LETKF-type solvers.
Definition: LocalEnsembleSolver.h:34
oops::LocalEnsembleSolver::LocalEnsembleSolver
LocalEnsembleSolver(ObsSpaces_ &obspaces, const Geometry_ &geometry, const eckit::Configuration &config, size_t nens)
initialize solver with obspaces, geometry, full config and nens ensemble size
Definition: LocalEnsembleSolver.h:78
oops::Departures
Difference between two observation vectors.
Definition: oops/base/Departures.h:44
oops::LocalEnsembleSolver::classname
static const std::string classname()
Definition: LocalEnsembleSolver.h:48
oops::LocalEnsembleSolverFactory::make
virtual LocalEnsembleSolver< MODEL, OBS > * make(ObsSpaces_ &, const Geometry_ &, const eckit::Configuration &, size_t)=0
oops::LocalEnsembleSolver::omb_
Departures_ omb_
Definition: LocalEnsembleSolver.h:71
oops::LocalEnsembleSolver::StateEnsemble4D_
StateEnsemble4D< MODEL > StateEnsemble4D_
Definition: LocalEnsembleSolver.h:45
oops::LocalEnsembleSolver::DeparturesEnsemble_
DeparturesEnsemble< OBS > DeparturesEnsemble_
Definition: LocalEnsembleSolver.h:37
oops::LocalEnsembleSolverMaker::Geometry_
Geometry< MODEL > Geometry_
Definition: LocalEnsembleSolver.h:185
oops::LocalEnsembleSolver::copyLocalIncrement
virtual void copyLocalIncrement(const IncrementEnsemble4D_ &bg, const GeometryIterator_ &i, IncrementEnsemble4D_ &an) const
copy an[i] = bg i \a
Definition: LocalEnsembleSolver.h:146
oops::LocalEnsembleSolver::computeHofX
virtual Observations_ computeHofX(const StateEnsemble4D_ &xx, size_t iteration, bool readFromDisk)
computes ensemble H(xx), returns mean H(xx), saves as hofx iteration
Definition: LocalEnsembleSolver.h:90
oops::IncrementEnsemble4D::size
unsigned int size() const
Accessors.
Definition: IncrementEnsemble4D.h:61
oops::LocalEnsembleSolver::Yb_
DeparturesEnsemble_ Yb_
Definition: LocalEnsembleSolver.h:72
oops::IncrementEnsemble4D
Ensemble of 4D inrements.
Definition: IncrementEnsemble4D.h:37
IncrementEnsemble4D.h
oops::LocalIncrement
Definition: LocalIncrement.h:19
oops::Geometry
Geometry class used in oops; subclass of interface class above.
Definition: oops/interface/Geometry.h:189
oops::ObsEnsemble
Ensemble of observations (can hold ensemble of H(x))
Definition: ObsEnsemble.h:21
oops::LocalEnsembleSolver::Geometry_
Geometry< MODEL > Geometry_
Definition: LocalEnsembleSolver.h:38
oops::DeparturesEnsemble
Ensemble of Departures (can hold ensemble perturbations in the observation space)
Definition: oops/base/DeparturesEnsemble.h:23
oops::LocalEnsembleSolverFactory::LocalEnsembleSolverFactory
LocalEnsembleSolverFactory(const std::string &)
Definition: LocalEnsembleSolver.h:199
oops::Observations
Observations Class.
Definition: oops/base/Departures.h:30
oops::StateEnsemble4D
Ensemble of 4D states.
Definition: StateEnsemble4D.h:26
oops::LocalEnsembleSolver::~LocalEnsembleSolver
virtual ~LocalEnsembleSolver()=default
GeometryIterator.h
oops::LocalEnsembleSolver::obsconf_
const eckit::LocalConfiguration obsconf_
Definition: LocalEnsembleSolver.h:68
oops::ObsSpaces
Definition: ObsSpaces.h:41
compare.error
int error
Definition: compare.py:168
oops::ObsEnsemble::mean
Observations_ mean() const
Compute ensemble mean.
Definition: ObsEnsemble.h:58
oops::LocalEnsembleSolverMaker::LocalEnsembleSolverMaker
LocalEnsembleSolverMaker(const std::string &name)
Definition: LocalEnsembleSolver.h:192
oops::LocalEnsembleSolverFactory::~LocalEnsembleSolverFactory
virtual ~LocalEnsembleSolverFactory()=default
oops::LocalEnsembleSolverMaker::make
virtual LocalEnsembleSolver< MODEL, OBS > * make(ObsSpaces_ &obspaces, const Geometry_ &geometry, const eckit::Configuration &conf, size_t nens)
Definition: LocalEnsembleSolver.h:188
oops::LocalEnsembleSolverMaker::ObsSpaces_
ObsSpaces< OBS > ObsSpaces_
Definition: LocalEnsembleSolver.h:186
CalcHofX.h
Geometry.h