IODA Bundle
CostFctWeak.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2009-2016 ECMWF.
3  * (C) Copyright 2020-2021 UCAR.
4  *
5  * This software is licensed under the terms of the Apache Licence Version 2.0
6  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
7  * In applying this licence, ECMWF does not waive the privileges and immunities
8  * granted to it by virtue of its status as an intergovernmental organisation nor
9  * does it submit to any jurisdiction.
10  */
11 
12 #ifndef OOPS_ASSIMILATION_COSTFCTWEAK_H_
13 #define OOPS_ASSIMILATION_COSTFCTWEAK_H_
14 
15 #include <map>
16 #include <memory>
17 #include <string>
18 
19 #include <boost/make_unique.hpp>
20 
21 #include "eckit/config/LocalConfiguration.h"
27 #include "oops/base/Geometry.h"
28 #include "oops/base/Increment.h"
30 #include "oops/base/Model.h"
33 #include "oops/base/State.h"
34 #include "oops/base/StateInfo.h"
36 #include "oops/base/Variables.h"
39 #include "oops/mpi/mpi.h"
40 #include "oops/util/DateTime.h"
41 #include "oops/util/Duration.h"
42 #include "oops/util/Logger.h"
43 
44 namespace oops {
45 
46 /// Weak Constraint 4D-Var Cost Function
47 /*!
48  * General weak constraint constraint 4D-Var cost function.
49  */
50 
51 // -----------------------------------------------------------------------------
52 
53 template<typename MODEL, typename OBS> class CostFctWeak : public CostFunction<MODEL, OBS> {
64 
65  public:
66  CostFctWeak(const eckit::Configuration &, const eckit::mpi::Comm &);
68 
71  const bool idModel = false) const override;
74  const bool idModel = false) const override;
75  void zeroAD(CtrlInc_ &) const override;
76 
77  void runTLM(CtrlInc_ &, const bool idModel = false) const;
78  void runADJ(CtrlInc_ &, const bool idModel = false) const;
79  void runNL(CtrlVar_ &, PostProcessor<State_> &) const override;
80 
81  private:
82  void addIncr(CtrlVar_ &, const CtrlInc_ &, PostProcessor<Increment_> &) const override;
83 
84  CostJbJq<MODEL> * newJb(const eckit::Configuration &, const Geometry_ &,
85  const CtrlVar_ &) const override;
86  CostJo<MODEL, OBS> * newJo(const eckit::Configuration &) const override;
87  CostTermBase<MODEL, OBS> * newJc(const eckit::Configuration &, const Geometry_ &) const override;
88  void doLinearize(const Geometry_ &, const eckit::Configuration &,
89  const CtrlVar_ &, const CtrlVar_ &,
91  const Geometry_ & geometry() const override {return *resol_;}
92 
93  util::Duration subWinLength_;
94  util::DateTime subWinBegin_;
95  util::DateTime subWinEnd_;
96  size_t nsubwin_;
97  size_t mysubwin_;
98  std::unique_ptr<Geometry_> resol_;
99  std::unique_ptr<Model_> model_;
101  std::shared_ptr<LinearModel_> tlm_;
102  std::unique_ptr<VarCha_> an2model_;
103  std::unique_ptr<LinVarCha_> inc2model_;
104  eckit::mpi::Comm * commSpace_;
105  eckit::mpi::Comm * commTime_;
106 };
107 
108 // =============================================================================
109 
110 template<typename MODEL, typename OBS>
111 CostFctWeak<MODEL, OBS>::CostFctWeak(const eckit::Configuration & config,
112  const eckit::mpi::Comm & comm)
113  : CostFunction<MODEL, OBS>::CostFunction(config), resol_(), model_(),
114  ctlvars_(config, "analysis variables"), tlm_(), an2model_(), inc2model_(),
115  commSpace_(nullptr), commTime_(nullptr)
116 {
117  util::Duration windowLength(config.getString("window length"));
118  util::DateTime windowBegin(config.getString("window begin"));
119  subWinLength_ = util::Duration(config.getString("subwindow"));
120 
121  nsubwin_ = windowLength.toSeconds() / subWinLength_.toSeconds();
122  ASSERT(windowLength.toSeconds() == subWinLength_.toSeconds()*(int64_t)nsubwin_);
123 
124  size_t ntasks = comm.size();
125  ASSERT(ntasks % nsubwin_ == 0);
126  size_t myrank = comm.rank();
127  size_t ntaskpslot = ntasks / nsubwin_;
128  size_t mysubwin_ = myrank / ntaskpslot;
129 
130 // Define local sub-window
131  subWinBegin_ = windowBegin + mysubwin_ * subWinLength_;
133 
134 // Create a communicator for same sub-window, to be used for communications in space
135  std::string sgeom = "comm_geom_" + std::to_string(mysubwin_);
136  char const *geomName = sgeom.c_str();
137  commSpace_ = &comm.split(mysubwin_, geomName);
138 
139 // Create a communicator for same local area, to be used for communications in time
140  size_t myarea = commSpace_->rank();
141  std::string stime = "comm_time_" + std::to_string(myarea);
142  char const *timeName = stime.c_str();
143  commTime_ = &comm.split(myarea, timeName);
144  ASSERT(commTime_->size() == nsubwin_);
145 
146 // Now can setup the rest
147  resol_.reset(new Geometry_(eckit::LocalConfiguration(config, "geometry"),
148  *commSpace_, *commTime_));
149  model_.reset(new Model_(*resol_, eckit::LocalConfiguration(config, "model")));
150  this->setupTerms(config);
151 
152  an2model_ = boost::make_unique<VarCha_>(*resol_, config);
153 
154  Log::trace() << "CostFctWeak constructed" << std::endl;
155 }
156 
157 // -----------------------------------------------------------------------------
158 
159 template <typename MODEL, typename OBS>
160 CostJbJq<MODEL> * CostFctWeak<MODEL, OBS>::newJb(const eckit::Configuration & jbConf,
161  const Geometry_ & resol,
162  const CtrlVar_ & xb) const {
163  return new CostJbJq<MODEL>(jbConf, *commTime_, resol, ctlvars_, xb.state());
164 }
165 
166 // -----------------------------------------------------------------------------
167 
168 template <typename MODEL, typename OBS>
169 CostJo<MODEL, OBS> * CostFctWeak<MODEL, OBS>::newJo(const eckit::Configuration & joConf) const {
170  return new CostJo<MODEL, OBS>(joConf, *commSpace_,
171  subWinBegin_, subWinEnd_, *commTime_);
172 }
173 
174 // -----------------------------------------------------------------------------
175 
176 template <typename MODEL, typename OBS>
177 CostTermBase<MODEL, OBS> * CostFctWeak<MODEL, OBS>::newJc(const eckit::Configuration & jcConf,
178  const Geometry_ & resol) const {
179  const eckit::LocalConfiguration jcdfi(jcConf, "jcdfi");
180  const util::DateTime vt(subWinBegin_ + subWinLength_/2);
181  return new CostJcDFI<MODEL, OBS>(jcdfi, resol, vt, subWinLength_);
182 }
183 
184 // -----------------------------------------------------------------------------
185 
186 template <typename MODEL, typename OBS>
188  ASSERT(xx.state().validTime() == subWinBegin_);
189 
190  State_ xm(xx.state().geometry(), model_->variables(), subWinBegin_);
191  an2model_->changeVar(xx.state(), xm);
192  model_->forecast(xm, xx.modVar(), subWinLength_, post);
193  an2model_->changeVarInverse(xm, xx.state());
194 
195  ASSERT(xx.state().validTime() == subWinEnd_);
196 }
197 
198 // -----------------------------------------------------------------------------
199 
200 template<typename MODEL, typename OBS>
202  const eckit::Configuration & innerConf,
203  const CtrlVar_ & bg, const CtrlVar_ & fg,
205  PostProcessorTLAD<MODEL> & pptraj) {
206  Log::trace() << "CostFctWeak::doLinearize start" << std::endl;
207  eckit::LocalConfiguration conf(innerConf, "linear model");
208 // Setup linear model (and trajectory)
209  tlm_.reset(new LinearModel_(resol, conf));
210  pp.enrollProcessor(new TrajectorySaver<MODEL>(conf, resol, fg.modVar(), tlm_, pptraj));
211 
212 // Setup change of variables
213  inc2model_.reset(LinearVariableChangeFactory<MODEL>::create(bg.state(), fg.state(),
214  resol, conf));
215  inc2model_->setInputVariables(ctlvars_);
216  Log::trace() << "CostFctWeak::doLinearize done" << std::endl;
217 }
218 
219 // -----------------------------------------------------------------------------
220 
221 template <typename MODEL, typename OBS>
225  const bool idModel) const {
226  Log::trace() << "CostFctWeak: runTLM start" << std::endl;
227  inc2model_->setOutputVariables(tlm_->variables());
228 
229  ASSERT(dx.state().validTime() == subWinBegin_);
230 
231  Increment_ dxmodel(dx.state().geometry(), tlm_->variables(), subWinBegin_);
232  inc2model_->multiply(dx.state(), dxmodel);
233  tlm_->forecastTL(dxmodel, dx.modVar(), subWinLength_, post, cost, idModel);
234  inc2model_->multiplyInverse(dxmodel, dx.state());
235 
236  ASSERT(dx.state().validTime() == subWinEnd_);
237  Log::trace() << "CostFctWeak: runTLM done" << std::endl;
238 }
239 
240 // -----------------------------------------------------------------------------
241 
242 template <typename MODEL, typename OBS>
243 void CostFctWeak<MODEL, OBS>::runTLM(CtrlInc_ & dx, const bool idModel) const {
246  inc2model_->setOutputVariables(tlm_->variables());
247 
248  ASSERT(dx.state().validTime() == subWinBegin_);
249 
250  Increment_ dxmodel(dx.state().geometry(), tlm_->variables(), subWinBegin_);
251  if (idModel) {
252  dx.state().updateTime(subWinLength_);
253  } else {
254  inc2model_->multiply(dx.state(), dxmodel);
255  tlm_->forecastTL(dxmodel, dx.modVar(), subWinLength_, post, cost);
256  inc2model_->multiplyInverse(dxmodel, dx.state());
257  }
258 
259  ASSERT(dx.state().validTime() == subWinEnd_);
260 }
261 
262 // -----------------------------------------------------------------------------
263 
264 template <typename MODEL, typename OBS>
266  dx.state().zero(subWinEnd_);
267  dx.modVar().zero();
268  dx.obsVar().zero();
269 }
270 
271 // -----------------------------------------------------------------------------
272 
273 template <typename MODEL, typename OBS>
277  const bool idModel) const {
278  Log::trace() << "CostFctWeak: runADJ start" << std::endl;
279  inc2model_->setOutputVariables(tlm_->variables());
280 
281  ASSERT(dx.state().validTime() == subWinEnd_);
282 
283  Increment_ dxmodel(dx.state().geometry(), tlm_->variables(), subWinEnd_);
284  inc2model_->multiplyInverseAD(dx.state(), dxmodel);
285  tlm_->forecastAD(dxmodel, dx.modVar(), subWinLength_, post, cost, idModel);
286  inc2model_->multiplyAD(dxmodel, dx.state());
287 
288  ASSERT(dx.state().validTime() == subWinBegin_);
289  Log::trace() << "CostFctWeak: runADJ done" << std::endl;
290 }
291 
292 // -----------------------------------------------------------------------------
293 
294 template <typename MODEL, typename OBS>
295 void CostFctWeak<MODEL, OBS>::runADJ(CtrlInc_ & dx, const bool idModel) const {
298  inc2model_->setOutputVariables(tlm_->variables());
299 
300  ASSERT(dx.state().validTime() == subWinEnd_);
301 
302  Increment_ dxmodel(dx.state().geometry(), tlm_->variables(), subWinEnd_);
303  if (idModel) {
304  dx.state().updateTime(-subWinLength_);
305  } else {
306  inc2model_->multiplyInverseAD(dx.state(), dxmodel);
307  tlm_->forecastAD(dxmodel, dx.modVar(), subWinLength_, post, cost);
308  inc2model_->multiplyAD(dxmodel, dx.state());
309  }
310 
311  ASSERT(dx.state().validTime() == subWinBegin_);
312 }
313 
314 // -----------------------------------------------------------------------------
315 
316 template<typename MODEL, typename OBS>
318  PostProcessor<Increment_> & post) const {
319  xx.state() += dx.state();
320 }
321 
322 // -----------------------------------------------------------------------------
323 
324 } // namespace oops
325 
326 #endif // OOPS_ASSIMILATION_COSTFCTWEAK_H_
ObsAuxIncrs_ & obsVar()
Get augmented observation control variable.
Increment_ & state()
Get state control variable.
ModelAuxIncr_ & modVar()
Get augmented model control variable.
Control variable.
ModelAux_ & modVar()
Get augmented model control variable.
State_ & state()
Get state control variable.
Weak Constraint 4D-Var Cost Function.
Definition: CostFctWeak.h:53
CostTermBase< MODEL, OBS > * newJc(const eckit::Configuration &, const Geometry_ &) const override
Definition: CostFctWeak.h:177
VariableChange< MODEL > VarCha_
Definition: CostFctWeak.h:62
std::unique_ptr< Geometry_ > resol_
Definition: CostFctWeak.h:98
eckit::mpi::Comm * commSpace_
Definition: CostFctWeak.h:104
CostJbJq< MODEL > * newJb(const eckit::Configuration &, const Geometry_ &, const CtrlVar_ &) const override
Definition: CostFctWeak.h:160
void addIncr(CtrlVar_ &, const CtrlInc_ &, PostProcessor< Increment_ > &) const override
Definition: CostFctWeak.h:317
util::DateTime subWinEnd_
Definition: CostFctWeak.h:95
ControlVariable< MODEL, OBS > CtrlVar_
Definition: CostFctWeak.h:56
util::DateTime subWinBegin_
Definition: CostFctWeak.h:94
std::unique_ptr< Model_ > model_
Definition: CostFctWeak.h:99
CostFunction< MODEL, OBS > CostFct_
Definition: CostFctWeak.h:57
Increment< MODEL > Increment_
Definition: CostFctWeak.h:54
void runTLM(CtrlInc_ &, PostProcessorTLAD< MODEL > &, PostProcessor< Increment_ >, const bool idModel=false) const override
Definition: CostFctWeak.h:222
CostJo< MODEL, OBS > * newJo(const eckit::Configuration &) const override
Definition: CostFctWeak.h:169
ControlIncrement< MODEL, OBS > CtrlInc_
Definition: CostFctWeak.h:55
std::unique_ptr< VarCha_ > an2model_
Definition: CostFctWeak.h:102
State< MODEL > State_
Definition: CostFctWeak.h:59
void runNL(CtrlVar_ &, PostProcessor< State_ > &) const override
Definition: CostFctWeak.h:187
std::unique_ptr< LinVarCha_ > inc2model_
Definition: CostFctWeak.h:103
LinearVariableChangeBase< MODEL > LinVarCha_
Definition: CostFctWeak.h:63
util::Duration subWinLength_
Definition: CostFctWeak.h:93
eckit::mpi::Comm * commTime_
Definition: CostFctWeak.h:105
std::shared_ptr< LinearModel_ > tlm_
Definition: CostFctWeak.h:101
Model< MODEL > Model_
Definition: CostFctWeak.h:60
void runADJ(CtrlInc_ &, PostProcessorTLAD< MODEL > &, PostProcessor< Increment_ >, const bool idModel=false) const override
Definition: CostFctWeak.h:274
const Variables ctlvars_
Definition: CostFctWeak.h:100
void doLinearize(const Geometry_ &, const eckit::Configuration &, const CtrlVar_ &, const CtrlVar_ &, PostProcessor< State_ > &, PostProcessorTLAD< MODEL > &) override
Definition: CostFctWeak.h:201
CostFctWeak(const eckit::Configuration &, const eckit::mpi::Comm &)
Definition: CostFctWeak.h:111
Geometry< MODEL > Geometry_
Definition: CostFctWeak.h:58
const Geometry_ & geometry() const override
Definition: CostFctWeak.h:91
void zeroAD(CtrlInc_ &) const override
Definition: CostFctWeak.h:265
LinearModel< MODEL > LinearModel_
Definition: CostFctWeak.h:61
Cost Function.
Definition: CostFunction.h:53
void setupTerms(const eckit::Configuration &)
Definition: CostFunction.h:194
Jb + Jq Cost Function.
Definition: CostJbJq.h:39
Jc DFI Cost Function.
Definition: CostJcDFI.h:44
Jo Cost Function.
Definition: CostJo.h:52
Base Class for Cost Function Terms.
Definition: CostTermBase.h:36
Geometry class used in oops; subclass of interface class interface::Geometry.
Increment class used in oops.
Encapsulates the linear forecast model.
Abstract nonlinear forecast model used by high level algorithms and applications.
Control model post processing.
Definition: PostProcessor.h:30
void enrollProcessor(PostBase_ *pp)
Definition: PostProcessor.h:38
Control model post processing.
State class used in oops; subclass of interface class interface::State.
Save trajectory during forecast run.
Encapsulates the nonlinear variable change Note: to see methods that need to be implemented in the im...
void updateTime(const util::Duration &dt)
Updates this Increment's valid time by dt (used in PseudoModel)
Geometry_ geometry() const
Accessor to geometry associated with this Increment.
void zero()
Zero out this Increment.
const util::DateTime validTime() const
Accessor to the time of this Increment.
Geometry_ geometry() const
Accessor to geometry associated with this State.
const util::DateTime validTime() const
Accessor to the time of this State.
The namespace for the main oops code.