OOPS
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"
29 #include "oops/base/LinearModel.h"
31 #include "oops/base/Model.h"
34 #include "oops/base/State.h"
35 #include "oops/base/StateInfo.h"
37 #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.
Abstract linear forecast model used by high level algorithms and applications.
void zero()
Zero out this ModelAuxIncrement.
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.